2022年9月12日 星期一

設定 Apache 的 mod_reqtimeout 避免 DDOS 攻擊

如何緩解Slowloris 攻擊?

對於易受Slowloris 攻擊的Web 服務器,有一些方法可以減輕某些影響。易受攻擊的服務器的緩解措施可以分為3 大類:

增加服務器可用性- 增加服務器在任何時間允許的最大客戶端數量,這將增加攻擊者使服務器過載前必須建立的連接數。實際上,無論增加多少,攻擊者都可以擴展攻擊數量以攻克服務器容量。

限制傳入請求的速率- 基於某些使用因素限制訪問,這將有助於緩解Slowloris 攻擊。限制單個IP 地址允許建立的最大連接數,限制慢速傳輸速度,以及限制客戶端允許保持連接的最長時間,這些技巧都是限制慢速攻擊的有效方法。


在 Apache 2.4 中已經內建 mod_reqtimeout,只需要先在 httpd.conf 中把 # 拿掉啟用即可

LoadModule reqtimeout_module modules/mod_reqtimeout.so


例子

等待5秒以完成TLS握手,等待10秒以接收請求標頭,等待30秒以接收請求正文:

RequestReadTimeout handshake=5 header=10 body=30

至少等待10秒鐘以接收請求正文。如果客戶端發送數據,則每接收1000個字節,將超時增加1秒,沒有超時上限(除非間接限制為 LimitRequestBody):

RequestReadTimeout body=10,MinRate=1000

至少等待10秒鐘以接收請求標頭。如果客戶端發送數據,則每接收500個字節將超時增加1秒。但請求標頭的時間不得超過30秒:

RequestReadTimeout header=10-30,MinRate=500

通常,服務器應同時配置標頭超時和主體超時。如果將通用配置用於http和https虛擬主機,則超時不應設置得太低:

RequestReadTimeout header=20-40,MinRate=500 body=20,MinRate=500


接下來就是設定

<IfModule reqtimeout_module>

RequestReadTimeout header=20-30,MinRate=256 body=100-120,MinRate=512

</IfModule>

2022年9月5日 星期一

什麼是反惡意軟件服務可執行文件(antimalware service executable)?

 什麼是反惡意軟件服務可執行文件(antimalware service executable)?

反惡意軟件服務可執行文件(antimalware service executable)是Windows 10 系統內建 Windows Defender 防火牆下的一個後台進程。此程序也稱為MsMpEng.exe,是Windows操作系統的一部分,始終在後台運行。當用戶訪問檔案時, Windows Defender 負責掃描檢查是否夾帶病毒軟體、安裝病毒定義檔等工作,因此需要使用到磁碟資源、記憶體RAM和CPU。您可以從Windows 10附帶的Windows Defender安全中心應用程序配置Windows Defender,執行掃描並檢查其掃描歷史記錄。

它是病毒嗎?

目前,還沒有任何證據與報告來假裝模仿反惡意軟件服務可執行文件。Windows Defender本身就是一個防病毒軟件。常規後台掃描對於任何防病毒程序都是正常的。因此我們可以相信antimalware service executable這個後台進程對我們來說是安全的。

它為什麼佔用CPU或磁盤資源?

突然的大量使用到CPU或磁盤資源使用表示它可能在掃描您的計算機以查找惡意軟件或定期安裝包含新惡意軟件信息的更新。所有這些程序都需要使用一些系統資源來檢查您的PC並保護您的安全。

怎麼解決antimalware service executable 對於CPU/記憶體使用率過高呢?

但是很多剛剛更新成windows10的用戶不習慣,他們覺得資源占用的情況太過明顯,想要關閉反惡意軟件服務可執行文件(antimalware service executable)以解決CPU/記憶體使用率過高的問題。到底該怎麼解決antimalware service executable 對於CPU/記憶體使用率過高呢?

 

事實上,如果您沒有安裝任何其他防病毒軟件,我們建議您不要禁用Windows Defender防病毒工具和關閉antimalware service executable。雖然,您無法永久禁用它。因為如果Windows Defender未檢測到安裝的其他防病毒應用程序,它將在短時間後重新啟用。


將antimalware service executable 添加到 Windows Defender 的排除列表中

步驟 1. 同時按住Windows鍵+ I ,打開「設定」。點擊「更新與安全性」。

步驟 2. 點擊「Windows Defender」,點擊添加「排除項目」。

步驟 3. 點擊「排除.exe, .com, .scr 程序」。

添加到Windows Defender - 1

步驟 4. 輸入:MsMpEng.exe ,點擊「確定」。


2022年8月30日 星期二

XAMPP CI3 Git 洩漏?

 許多工程師在撰寫程式時,會使用 Git 來做版本控管,在使用 Git 的時候,目錄底下會產生一個 .git 的隱藏檔案,裡面就是 git repository,會儲存程式的修改、新增、刪除等紀錄。

若工程師直接將含有 .git 目錄的專案放到網頁伺服器的公開目錄,駭客便有可能下載 .git 中的資料,利用 git 的機制將原始碼重建。

因此當工程師開發完成時,可能有兩個方法發佈較為妥當:

額外將網頁程式碼製作一個副本 (不含 .git),再發佈到網頁伺服器。

直接將含 git 目錄的專案放到網頁伺服器,但同時做好網頁的權限控管,也就是當你瀏覽 /.git 底下的全部內容時,會回傳 403。

假如工程師在測試登入功能時,將 admin 的帳密紀錄在程式的註解中,並使用 git 紀錄到歷史版本中,當工程師不小心上傳 .git,並且沒有做權限控管,那麼駭客就能從洩漏的 .git 目錄中拿到帳密。

此外,因為 .git 洩漏是已知且普遍的問題,有眾多工具可以協助駭客下載 .git 目錄並重建原始碼,只要網頁不小心將 .git 上傳,那就有許多人可以將網頁的 .git 下載下來,反倒甚至出現針對這種工具漏洞的攻擊:

攻擊者會構建惡意的 .git 目錄,故意將其中的一些資料路徑修改,例如將文件路徑加上很多 ../../../ ,一旦重建工具沒有檢查路徑,重構資料就可以隨意覆蓋到你的正常檔案。


一般來說,只要網址/.git 可以看到東西,基本上就能將程式還原,但是有時候網址輸入 /.git 會出現 403 (「無權」訪問指定的URL而非 「檔案不存在」,代表 .git 目錄可能是存在的,你可以嘗試 /.git/config,看他有沒有擋),或是用其他方式拿到 .git 的資料,例如下載

網址/.git/logs/HEAD 儲存 git 的 log,可以找到歷史 commit

網址/.git/refs/heads/master 會記錄 master 的 commit hash,可以分解出該 commit 的資料

網址/.git/refs/heads 底下會放所有分支的名字資料夾

網址/.git/refs/stash 用於暫時保存 git 工作進度,可以把做到一半的東西先藏起來(stash),不要 commit 出去

git stash list 顯示 stash 內的所有內容

git stash pop 把剛剛做到一半存在 stash 的資料還原

網址/.git/info/packs packs 的件提取與恢復 (比較少考)

網址/.git/index 會儲存 git add 的資料


<Directory "C:/xampp/htdocs">

    Options Includes FollowSymLinks ExecCGI


    AllowOverride All


    Require all granted

    Header set Access-Control-Allow-Origin *

    RedirectMatch 404 /\\.(svn|git|hg|bzr|cvs)(/|$)

</Directory>


<DirectoryMatch "^/.*/\.git/">

    Order allow,deny

    Require all denied

</DirectoryMatch>

2022年3月9日 星期三

Apache 核心功能 AcceptFilter Directive 深入探討

AcceptFilter 指令簡介

AcceptFilter 是 Apache HTTP 伺服器中一個重要的指令,用於配置伺服器如何接受新的連線請求。它直接影響伺服器的效能,尤其是當伺服器面臨高併發連線時。

AcceptFilter 的作用

  • 控制連線接受方式: AcceptFilter 指令指定了 Apache 如何處理 incoming connections。不同的配置會影響伺服器處理連線的順序和方式。
  • 影響伺服器效能: 合理配置 AcceptFilter 可以提升伺服器的效能,特別是在高併發環境下。
  • 適應不同硬件環境: 不同的硬件配置和作業系統可能需要不同的 AcceptFilter 設定。

AcceptFilter 的值

常見的 AcceptFilter 值有:

  • accept: 這是最基本的配置,按照連線到來的順序依次處理。
  • prefork: 為每個子進程預先分配一個 accept() 鎖,提高處理連線的速度。
  • http: 使用 HTTP 協議的 accept() 系統調用。
  • mPM: 由多處理模組 (MPM) 決定如何處理連線。

不同 AcceptFilter 值的比較

AcceptFilter 值描述優點缺點
accept按順序處理連線配置簡單在高併發下可能導致性能瓶頸
prefork為每個子進程預先分配 accept() 鎖提高連線處理速度可能消耗更多系統資源
http使用 HTTP 協議的 accept() 系統調用可以利用一些 HTTP 特性可能不適用於所有情況
mPM由 MPM 決定靈活性高配置較複雜

如何選擇合適的 AcceptFilter

選擇合適的 AcceptFilter 取決於以下因素:

  • 硬件配置: CPU、記憶體等硬件資源的限制會影響 AcceptFilter 的選擇。
  • 作業系統: 不同的作業系統對 AcceptFilter 的支持可能有所不同。
  • 應用程序需求: 不同的應用程序對連線處理的要求也不同。
  • 伺服器負載: 高併發環境下,需要選擇能高效處理連線的配置。

示例配置

Apache
<IfModule mpm_prefork_module>
    AcceptFilter prefork
</IfModule>

上述配置表示使用 prefork 模式,為每個子進程預先分配 accept() 鎖。

注意事項

  • MPM 的影響: AcceptFilter 的效果會受到 MPM 的影響,不同的 MPM 有不同的特性。
  • 其他配置項: AcceptFilter 只是 Apache 配置的一部分,需要與其他配置項配合使用才能達到最佳效果。
  • 性能測試: 最好的方式是通過性能測試來確定最適合的 AcceptFilter 配置。

總結

AcceptFilter 是 Apache 伺服器中一個重要的配置項,它直接影響伺服器的性能。選擇合適的 AcceptFilter 值需要綜合考慮硬件、軟體、應用程序等多方面的因素。通過合理的配置,可以提升伺服器的性能,提高用戶體驗。

2022年3月8日 星期二

Apache假死堵塞卡死無響應解決方法

 啟用MPM模組配置文件

Apache針對不同的作業系統提供了多個不同的MPM模組,例如:mpm_beos、mpm_event、mpm_netware、mpmt_os2、mpm_prefork、mpm_winnt、mpm_worker。

Windows作業系統上默認的MPM模組是mpm_winnt,mpm_winnt模組是專門針對Windows作業系統而優化設計的MPM模組。它只創建一個單獨的子進程,並在這個子進程中輪流產生多個線程來處理請求。

在對Apache的MPM模組具備一定了解後,我們就可以針對不同的MPM模組來修改Apache的最大並發連接數配置了

修改任何文件,建議做好備份。

apache\conf\httpd.conf文件中啟用該配置文件


# Server-pool management (MPM specific)

Include conf/extra/httpd-mpm.conf (去掉該行前面的注釋符號"#")

對應的配置參數作用如下:


ThreadsPerChild:每個子進程的最大並發線程數。 

MaxRequestsPerChild:每個子進程允許處理的請求總數。如果累計處理的請求數超過該值,該子進程將會結束(然後根據需要確定是否創建新的子進程),該值設為0表示不限制請求總數(子進程永不結束)。 

該參數建議設為非零的值,可以帶來以下兩個好處: 

1. 可以防止程序中可能存在的記憶體泄漏無限進行下去,從而耗盡記憶體。 

2. 給進程一個有限壽命,從而有助於當伺服器負載減輕的時候減少活動進程的數量。

注意:在以上涉及到統計請求數量的參數中,對於KeepAlive的連接,只有第一個請求會被計數。


修改MPM模組配置http-mpm.conf文件中的相關配置


在Apace安裝目錄/conf/extra目錄中有一個名為httpd-mpm.conf


#由於mpm_winnt模組只會創建1個子進程,因此這裡對單個子進程的參數設置就相當於對整個Apache的參數設置。

<IfModule mpm_winnt_module>

ThreadsPerChild 521 #默認值是150,推薦設置:小型網站=1000 中型網站=1000~2000 大型網站=2000~3500

MaxRequestsPerChild 3000 #推薦設置:小=10000 中或大=20000~100000

</IfModule>

再考慮一個可能,(apache 2.4)


apache 2.4 IE10瀏覽器會導致Apache2.4版本阻塞假死,有一種說法,用IE10登錄了網站,導致了apache的卡死,這裡做一個防範:

在配置文件httpd.conf中添加如下兩句


AcceptFilter http none

AcceptFilter https none



原文網址:https://kknews.cc/code/2no3569.html

2022年3月7日 星期一

《面試官別再問》Nginx常見的面試題

1. 什麼是Nginx?

Nginx是一個輕量級/高性能的反向代理Web服務器,他實現非常高效的反向代理、負載平衡,他可以處理2-3萬並發連接數,官方監測能支持5萬並發,現在中國使用nginx網站用戶有很多,例如:新浪、網易、 騰訊等。


2. 為什麼要用Nginx?

跨平台、配置簡單、方向代理、高並發連接:處理2-3萬並發連接數,官方監測能支持5萬並發,內存消耗小:開啟10個nginx才佔150M內存,nginx處理靜態文件好,耗費內存少,

而且Nginx內置的健康檢查功能:如果有一個服務器宕機,會做一個健康檢查,再發送的請求就不會發送到宕機的服務器了。重新將請求提交到其他的節點上。

使用Nginx的話還能:

節省寬帶:支持GZIP壓縮,可以添加瀏覽器本地緩存

穩定性高:宕機的概率非常小

接收用戶請求是異步的


2. 為什麼Nginx性能這麼高?

因為他的事件處理機制:異步非阻塞事件處理機制:運用了epoll模型,提供了一個隊列,排隊解決

Nginx怎麼處理請求的?

nginx接收一個請求後,首先由listen和server_name指令匹配server模塊,再匹配server模塊裡的location,location就是實際地址

    server                                  # 第一個Server區塊開始,表示一個獨立的虛擬主機站點

        listen       80;                    # 提供服務的端口,默認80

        server_name  localhost;             # 提供服務的域名主機名

        location / {                        # 第一個location區塊開始

            root   html;                    # 站點的根目錄,相當於Nginx的安裝目錄

            index  index.html index.htm;    # 默認的首頁文件,多個用空格分開

        }                                   # 第一個location區塊結果

    }


3. 什麼是正向代理和反向代理?

正向代理就是一個人發送一個請求直接就到達了目標的服務器

反方代理就是請求統一被Nginx接收,nginx反向代理服務器接收到之後,按照一定的規 則分發給了後端的業務處理服務器進行處理了

使用“反向代理服務器的優點是什麼?

反向代理服務器可以隱藏源服務器的存在和特徵。它充當互聯網雲和web服務器之間的中間層。這對於安全方面來說是很好的,特別是當您使用web託管服務時。


4. Nginx的優缺點?

優點:

佔內存小,可實現高並發連接,處理響應快

可實現http服務器、虛擬主機、方向代理、負載均衡

Nginx配置簡單

可以不暴露正式的服務器IP地址

缺點: 動態處理差:nginx處理靜態文件好,耗費內存少,但是處理動態頁面則很雞肋,現在一般前端用nginx作為反向代理抗住壓力,


5. Nginx應用場景?

http服務器。Nginx是一個http服務可以獨立提供http服務。可以做網頁靜態服務器。

虛擬主機。可以實現在一台服務器虛擬出多個網站,例如個人網站使用的虛擬機。

反向代理,負載均衡。當網站的訪問量達到一定程度後,單台服務器不能滿足用戶的請求時,需要用多台服務器集群可以使用nginx做反向代理。並且多台服務器可以平均分擔負載,不會應為某台服務器負載高宕機而某台服務器閒置的情況。

nginz 中也可以配置安全管理、比如可以使用Nginx搭建API接口網關,對每個接口服務進行攔截。


6. 限流怎麼做的?

Nginx限流就是限制用戶請求速度,防止服務器受不了

限流有3種

正常限制訪問頻率(正常流量)

突發限制訪問頻率(突發流量)

限制並發連接數


1、正常限制訪問頻率(正常流量):

限制一個用戶發送的請求,我Nginx多久接收一個請求。

Nginx中使用ngx_http_limit_req_module模塊來限制的訪問頻率,限制的原理實質是基於漏桶算法原理來實現的。在nginx.conf配置文件中可以使用limit_req_zone命令及limit_req命令限制單個IP的請求處理頻率。

    #定義限流維度,一個用戶一分鐘一個請求進來,多餘的全部漏掉

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/m;


#綁定限流維度

server{

location/seckill.html{

limit_req zone=zone;

proxy_pass http://lj_seckill;

}


}

1r/s代表1秒一個請求,1r/m一分鐘接收一個請求, 如果Nginx這時還有別人的請求沒有處理完,Nginx就會拒絕處理該用戶請求。

2、突發限制訪問頻率(突發流量):

限制一個用戶發送的請求,我Nginx多久接收一個。

    #定義限流維度,一個用戶一分鐘一個請求進來,多餘的全部漏掉

limit_req_zone $binary_remote_addr zone=one:10m rate=1r/m;


#綁定限流維度

server{

location/seckill.html{

limit_req zone=zone burst=5 nodelay;

proxy_pass http://lj_seckill;

}


}

上面的配置一定程度可以限制訪問頻率,但是也存在著一個問題:如果突發流量超出請求被拒絕處理,無法處理活動時候的突發流量,這時候應該如何進一步處理呢?Nginx提供burst參數結合nodelay參數可以解決流量突發的問題,可以設置能處理的超過設置的請求數外能額外處理的請求數。我們可以將之前的例子添加burst參數以及nodelay參數:

為什麼就多了一個burst=5 nodelay; 呢,多了這個可以代表Nginx對於一個用戶的請求會立即處理前五個,多餘的就慢慢來落,沒有其他用戶的請求我就處理你的,有其他的請求的話我Nginx就漏掉不接受你的請求

3、 限制並發連接數

Nginx中的ngx_http_limit_conn_module模塊提供了限制並發連接數的功能,可以使用limit_conn_zone指令以及limit_conn執行進行配置。

    http {

        limit_conn_zone $binary_remote_addr zone=myip:10m;

        limit_conn_zone $server_name zone=myServerName:10m;

    }


    server {

        location / {

            limit_conn myip 10;

            limit_conn myServerName 100;

            rewrite / http://www.lijie.net permanent;

        }

    }

面配置了單個IP同時並發連接數最多只能10個連接,並且設置了整個虛擬服務器同時最大並發數最多只能100個鏈接。當然,只有當請求的header被服務器處理後,虛擬服務器的連接數才會計數。剛才有提到過Nginx是基於漏桶算法原理實現的,實際上限流一般都是基於漏桶算法和令牌桶算法實現的。


7. 為什麼要做動靜分離?

Nginx是當下最熱的Web容器,網站優化的重要點在於靜態化網站,網站靜態化的關鍵點則是是動靜分離,動靜分離是讓動態網站裡的動態網頁根據一定規則把不變的資源和經常變的資源區分開來,動靜資源做好了拆分以後,我們則根據靜態資源的特點將其做緩存操作。

讓靜態的資源只走靜態資源服務器,動態的走動態的服務器

Nginx的靜態處理能力很強,但是動態處理能力不足,因此,在企業中常用動靜分離技術。

對於靜態資源比如圖片,js,css等文件,我們則在反向代理服務器nginx中進行緩存。這樣瀏覽器在請求一個靜態資源時,代理服務器nginx就可以直接處理,無需將請求轉發給後端服務器tomcat。若用戶請求的動態文件,比如servlet,jsp則轉發給Tomcat服務器處理,從而實現動靜分離。這也是反向代理服務器的一個重要的作用。

Nginx怎麼做的動靜分離?

只需要指定路徑對應的目錄。location/可以使用正則表達式匹配。並指定對應的硬盤中的目錄。如下:

    location /image/ {

        root   /usr/local/static/;

        autoindex on;

    }

    

8. Nginx負載均衡的算法怎麼實現的?策略有哪些?

為了避免服務器崩潰,大家會通過負載均衡的方式來分擔服務器壓力。將對台服務器組成一個集群,當用戶訪問時,先訪問到一個轉發服務器,再由轉發服務器將訪問分發到壓力更小的服務器。

Nginx負載均衡實現的策略有以下五種:

1 輪詢(默認)

每個請求按時間順序逐一分配到不同的後端服務器,如果後端某個服務器宕機,能自動剔除故障系統。

    upstream backserver { 

        server 192.168.0.12; 

        server 192.168.0.13; 

    } 

2 權重weight

weight的值越大分配

到的訪問概率越高,主要用於後端每台服務器性能不均衡的情況下。其次是為在主從的情況下設置不同的權值,達到合理有效的地利用主機資源。

    upstream backserver { 

        erver 192.168.0.12 weight=2; 

        erver 192.168.0.13 weight=8; 

    } 

權重越高,在被訪問的概率越大,如上例,分別是20%,80%。

3 ip_hash( IP綁定)

每個請求按訪問IP的哈希結果分配,使來自同一個IP的訪客固定訪問一台後端服務器,并且可以有效解决动态网页存在的session共享问题

    upstream backserver { 

        ip_hash; 

        server 192.168.0.12:88; 

        server 192.168.0.13:80; 

    } 

4 fair(第三方插件)

必須安裝upstream_fair模塊。

對比weight、ip_hash更加智能的負載均衡算法,fair算法可以根據頁面大小和加載時間長短智能地進行負載均衡,響應時間短的優先分配。

    upstream backserver { 

        server server1; 

        server server2; 

        fair; 

    } 

哪個服務器的響應速度快,就將請求分配到那個服務器上。

5、url_hash(第三方插件)

必須安裝Nginx的hash軟件包

按訪問url的hash結果來分配請求,使每個url定向到同一個後端服務器,可以進一步提高後端緩存服務器的效率。

    upstream backserver { 

        server squid1:3128; 

        server squid2:3128; 

        hash $request_uri; 

        hash_method crc32; 

    } 

    

9. nginx中500、502、503、504 有什麼區別?

500:Internal Server Error 內部服務錯誤,比如腳本錯誤,編程語言語法錯誤。

502:Bad Gateway錯誤,網關錯誤。比如服務器當前連接太多,響應太慢,頁面素材太多、帶寬慢。

503:Service Temporarily Unavailable,服務不可用,web服務器不能處理HTTP請求,可能是臨時超載或者是服務器進行停機維護。

504:Gateway timeout 網關超時,程序執行時間過長導致響應超時,例如程序需要執行20秒,而nginx最大響應等待時間為10秒,這樣就會出現超時。


10. Nginx服務器上的Master和Worker進程分別是什麼?

Master進程:讀取及評估配置和維持

Worker進程:解決請求


11. 如何用Nginx解決前端跨域問題?

使用Nginx轉發請求。把跨域的接口寫成調本域的接口,然後將這些接口轉發到真正的請求地址。


12. Nginx VS Apache

Apache 通過創建進程和線程來處理其他的連接。管理員可以通過設置來控制服務器所能允許的最大進程數量。這個配置因機器的可用內存而異。過多的進程會耗盡內存從而使得機器使用磁盤上的交換內存,這嚴重的降低了性能。而且,當達到進程的上限之後,Apache 會拒絕新的連接。

Apache可以通過設置來運行在 pre-forked 模式或 worker multi-process 模式 ( MPM )。當其他的用戶連接時,兩種方式都會創建新的進程。區別在於,pre-forked 模式為每一個進程創建一個線程,用來處理一個用戶的請求。worker 模式也創建新的進程,但是每一個進程至少有一個線程,每一個線程用來處理單個用戶的單個請求。所以,一個 worker mode 的進程處理至少一個連接,而一個 per-fork 模式的進程只處理一個連接。

相比於 forked 模式,worker 模式使用更少的內存,原因是進程比線程消耗更多的內存,線程只是運行在進程中的代碼。

此外,worker 模式不是線程安全的。這意味著如果你使用像 mod_php 這樣的非線程安全的模塊來服務 php 頁面時,你需要使用 pre-forked 模式,因此要消耗更多的內存。所以,當選擇模塊和配置服務器時,你必須要面對是線程還是進程更優的問題以及一些約束的問題。

在調整 Apache 時的一個限制因素是內存以及當爭奪同一個 CPU 和內存時潛在的線程死鎖問題。如果一個線程停止了,用戶會一直處於等待頁面出現的狀態,直到進程將該線程回收,以便可以發回頁面。如果一個線程發生了死鎖,它不知道如何重啟,因此會一直處於卡住狀態。

Openresty

和 Apache 相比,Nginx 的工作方式有很大不同,主要是在於它如何處理線程。

Nginx 並不會為每一個的 web 請求創建新的進程,相反,管理員可以配置 Nginx 主進程的工作進程的數量(一個常見的做法是為每一個 CPU 配置一個工作進程)。所有這些進程都是單線程的。每一個工作進程可以處理數千個並發的請求。它通過一個線程來異步的完成了這些工作,而沒有使用多線程的編程模型。

Nginx 還拆分了緩存加載器 ( cache loader ) 和緩存管理器 ( cache manager ) 進程用來從磁盤中讀取數據並將其加載到緩存中,當緩存直接讀取的時候緩存過期。

Nginx 有一系列的模塊組成,這些模塊在編譯的時候就被包含進去了。這意味著,用戶下載源碼並選擇他們要編譯的模塊。這些模塊中包括連接後端應用服務器,負載均衡,代理服務器以及其他。並沒有 PHP 的模塊,因為 Nginx 可以自己編譯 PHP 代碼。

2022年3月4日 星期五

《面試官別再問》PHP 面試整理

1. 列舉一些PHP 中的設計模式?

    單例模式:保證在整個應用程序的生命週期中,任何一個時刻,單例類的實例都只存在一個,同時這個類還必須提供一個訪問該類的全局訪問點。

    工廠模式:定義一個創建物件的接口,但是讓子類去實例化具體類。工廠方法模式讓類的實例化延遲到子類中。

    觀察者模式:觀察者模式有時也被稱作發布/訂閱模式,該模式用於為物件實現發布/訂閱功能:一旦主體物件狀態發生改變,與之關聯的觀察者物件會收到通知,並進行相應操作。

    適配器模式:適配器模式將一個類的接口轉換成客戶希望的另外一個接口,使得原本由於接口不兼容而不能一起工作的那些類可以在一起工作。

    依賴注入模式:依賴注入(DependencyInjection)是控制反轉(Inversion ofControl)的一種實現方式。要實現控制反轉,通常的解決方案是將創建被調用者實例的工作交由IoC 容器來完成,然後在調用者中註入被調用者(通過構造器/方法注入實現),這樣我們就實現了調用者與被調用者的解耦,該過程被稱為依賴注入。

    門面模式:門面模式(Facade)又稱外觀模式,用於為子系統中的一組接口提供一個一致的界面。


2. Session可不可以設置失效時間,比如30分鐘過期

    設置seesion.cookie_lifetime有30分鐘,並設置session.gc_maxlifetime為30分鐘

    自己為每一個Session值增加timestamp

    每次訪問之前, 判斷時間戳


3. 類的靜態調用和實例化調用各自的利弊

    靜態方法是類中的一個成員方法,屬於整個類,即使不用創建任何對像也可以直接調用!靜態方法效率上要比實例化高,靜態方法的缺點是不自動銷毀,而實例化的則可以做銷毀。


4. Redis五種資料類型及應用場景

    String: 一般做一些複雜的計數功能的緩存

    List: 做簡單的消息隊列的功能

    Hash: 單點登錄

    Set: 做全局去重的功能

    SortedSet: 做排行榜應用,取TopN操作;延時任務;做範圍查找


    Redis string 是redis 最基本的類型,你可以理解成與Memcached 一模一樣的類型,一個key 對應一個value。value其實不僅是String,也可以是數字。string 類型是二進制安全的。

    意思是redis 的string 可以包含任何資料。比如jpg圖片或者序列化的物件。string 類型是Redis 最基本的資料類型,string 類型的值最大能存儲512MB。

    常用命令:get、set、incr、decr、mget等。

    應用場景: String是最常用的一種資料類型,普通的key/ value 存儲都可以歸為此類,即可以完全實現目前Memcached 的功能,並且效率更高。還可以享受Redis的定時持久化,操作日誌及Replication等功能。

    Redis hash 是一個鍵值(key => value)對集合。Redis hash 是一個string 類型的field 和value 的映射表,hash 特別適合用於存儲物件。

    常用命令:hget,hset,hgetall 等。

    應用場景:我們簡單舉個實例來描述下Hash的應用場景,比如我們要存儲一個用戶信息對像資料,包含以下信息:

    用戶ID為查找的key,存儲的value用戶物件包含姓名,年齡,生日等信息。

    使用場景:存儲部分變更資料,如用戶信息等。

    Redis list 列表是簡單的字符串列表,按照插入順序排序。你可以添加一個元素到列表的頭部(左邊)或者尾部(右邊)。

    常用命令:lpush(添加左邊元素),rpush,lpop(移除左邊第一個元素),rpop,lrange(獲取列表片段,LRANGE key start stop)等。

    應用場景:Redis list的應用場景非常多,也是Redis最重要的資料結構之一,比如twitter的關注列表,粉絲列表等都可以用Redis的list結構來實現。

    Redis set是string類型的無序集合。集合是通過hashtable實現的,概念和數學中個的集合基本類似,可以交集,並集,差集等等,set中的元素是沒有順序的。所以添加,刪除,查找的複雜度都是O(1)。

    sadd 命令:添加一個string 元素到key 對應的set 集合中,成功返回1,如果元素已經在集合中返回0,如果key 對應的set 不存在則返回錯誤。

    常用命令:sadd,spop,smembers,sunion 等。

    應用場景:Redis set對外提供的功能與list類似是一個列表的功能,特殊之處在於set是可以自動排重的,當你需要存儲一個列表資料,又不希望出現重複資料時,set是一個很好的選擇,並且set提供了判斷某個成員是否在一個set集合內的重要接口,這個也是list所不能提供的。

    Set 就是一個集合,集合的概念就是一堆不重複值的組合。利用Redis提供的Set資料結構,可以存儲一些集合性的資料。

    Redis zset 和set 一樣也是string類型元素的集合,且不允許重複的成員。

    zadd 命令:添加元素到集合,元素在集合中存在則更新對應score。

    常用命令:zadd,zrange,zrem,zcard等

    使用場景:Redis sorted set的使用場景與set類似,區別是set不是自動有序的,而sorted set可以通過用戶額外提供一個優先級(score)的參數來為成員排序,並且是插入有序的,即自動排序。

    當你需要一個有序的並且不重複的集合列表,那麼可以選擇sorted set資料結構,比如twitter 的public timeline可以以發表時間作為score來存儲,這樣獲取時就是自動按時間排好序的。和Set相比,Sorted Set關聯了一個double類型權重參數score,使得集合中的元素能夠按score進行有序排列,redis正是通過分數來為集合中的成員進行從小到大的排序。

    zset的成員是唯一的,但分數(score)卻可以重複。比如一個存儲全班同學成績的Sorted Set,其集合value可以是同學的學號,而score就可以是其考試得分,這樣在資料插入集合的時候,就已經進行了天然的排序。另外還可以用Sorted Set來做帶權重的隊列,比如普通消息的score為1,重要消息的score為2,然後工作線程可以選擇按score的倒序來獲取工作任務。讓重要的任務優先執行。


5. Redis 緩存雪崩、擊穿、穿透

    什麼是緩存雪崩?

    當某一個時刻出現大規模的緩存失效的情況,那麼就會導致大量的請求直接打在資料庫上面,導致資料庫壓力巨大,如果在高並發的情況下,可能瞬間就會導致資料庫宕機。這時候如果運維馬上又重啟資料庫,馬上又會有新的流量把資料庫打死。這就是緩存雪崩。

    解決方案:

    1、在原有的失效時間上加上一個隨機值,比如1-5分鐘隨機。這樣就避免了因為採用相同的過期時間導致的緩存雪崩。

    2、使用熔斷機制。當流量到達一定的閾值時,就直接返回“系統擁擠”之類的提示,防止過多的請求打在數據庫上。至少能保證一部分用戶是可以正常使用,其他用戶多刷新幾次也能得到結果。

    3、提高數據庫的容災能力,可以使用分庫分錶,讀寫分離的策略。

    什麼是緩存擊穿?

    其實跟緩存雪崩有點類似,緩存雪崩是大規模的key失效,而緩存擊穿是一個熱點的Key,有大並發集中對其進行訪問,突然間這個Key失效了,導致大並發全部打在數據庫上,導致數據庫壓力劇增。這種現象就叫做緩存擊穿。

    解決方案:

    1、上面說過了,如果業務允許的話,對於熱點的key可以設置永不過期的key。

    2、使用互斥鎖。如果緩存失效的情況,只有拿到鎖才可以查詢數據庫,降低了在同一時刻打在數據庫上的請求,防止數據庫打死。當然這樣會導致系統的性能變差。

    什麼是緩存穿透?

    使用Redis大部分情況都是通過Key查詢對應的值,假如發送的請求傳進來的key是不存在Redis中的,那麼就查不到緩存,查不到緩存就會去數據庫查詢。假如有大量這樣的請求,這些請求像“穿透”了緩存一樣直接打在數據庫上,這種現象就叫做緩存穿透。

    解決方案:

    1、把無效的Key存進Redis中。如果Redis查不到數據,數據庫也查不到,我們把這個Key值保存進Redis,設置value="null",當下次再通過這個Key查詢時就不需要再查詢數據庫。這種處理方式肯定是有問題的,假如傳進來的這個不存在的Key值每次都是隨機的,那存進Redis也沒有意義。

    2、使用布隆過濾器。布隆過濾器的作用是某個key 不存在,那麼就一定不存在,它說某個key 存在,那麼很大可能是存在(存在一定的誤判率)。於是我們可以在緩存之前再加一層布隆過濾器,在查詢的時候先去布隆過濾器查詢key 是否存在,如果不存在就直接返回。


6. php7新特性

    1.可以使用字符串(string), 整數(int), 浮點數(float), 以及布爾值(bool),來聲明函數的參數類型與函數返回值

    2.新增操作符“<=>” 語法:$c = $a <=> $b 

    如果$a > $b, $c 的值為1

    如果$a == $b, $c 的值為0

    如果$a < $b, $c 的值為-1

    3.新增操作符“??” 如果變數存在且值不為NULL, 它就會返回自身的值,否則返回它的第二個操作數。

    //原寫法

    $username = isset($_GET['user]) ? $_GET['user] : 'nobody';

    //新寫法

    $username = $_GET['user'] ?? 'nobody';

    4.define() 定義常量陣列

    define('ARR',['a','b']);

    echo ARR[1];// a

    5.命名空間引用優化

    // PHP7以前语法的写法

    use FooLibrary\Bar\Baz\ClassA;

    use FooLibrary\Bar\Baz\ClassB;

    // PHP7新语法写法

    use FooLibrary\Bar\Baz\{ ClassA, ClassB};

    6.list修改

    不再按照相反的順序賦值

    //$arr将会是[1,2,3]而不是之前的[3,2,1]

    list($arr[], $arr[], $arr[]) = [1,2,3];

    不再支持字符串拆分功能

    // $x = null 并且 $y = null

    $str = 'xy';

    list($x, $y) = $str;

    空的list()賦值不再允許

    list() = [123];

    list()現在也適用於陣列物件

    list($a, $b) = (object)new ArrayObject([0, 1]);


7. 如何設計/優化一個訪問量比較大的部落格/論壇

    減少http請求(比如使用雪碧圖)

    優化數據庫(範式、SQL語句、索引、配置、讀寫分離)

    緩存使用(Memcache、Redis)

    負載均衡

    動態內容靜態化+CDN

    禁止外部盜鏈(refer、圖片添加水印)

    控制大文件下載

    使用集群

    

8. PHP使用Nginx實現反向代理

    1、什麼是代理伺服器

    代理伺服器,客戶機在發送請求時,不會直接發送給目的主機,而是先發送給代理伺服器,代理服務接受客戶機請求之後,再向主機發出,並接收目的主機返回的數據,存放在代理伺服器的硬盤中,再發送給客戶機。

    2、為什麼要使用代理伺服器

    1)提高訪問速度

    由於目標主機返回的數據會存放在代理伺服器的硬盤中,因此下一次客戶再訪問相同的站點數據時,會直接從代理伺服器的硬盤中讀取,起到了緩存的作用,尤其對於熱門站點能明顯提高請求速度。

    2)防火牆作用

    由於所有的客戶機請求都必須通過代理伺服器訪問遠程站點,因此可在代理伺服器上設限,過濾某些不安全信息。

    3)通過代理伺服器訪問不能訪問的目標站點

    互聯網上有許多開發的代理伺服器,客戶機在訪問受限時,可通過不受限的代理伺服器訪問目標站點,通俗說,我們使用的翻牆瀏覽器就是利用了代理伺服器,雖然不能出國,但也可直接訪問外網。

    二、反向代理VS 正向代理

    1、什麼是正向代理?什麼是反向代理?

    正向代理,架設在客戶機與目標主機之間,只用於代理內部網絡對Internet的連接請求,客戶機必須指定代理伺服器,並將本來要直接發送到Web伺服器上的http請求發送到代理伺服器中。

    反向代理伺服器架設在伺服器端,通過緩衝經常被請求的頁面來緩解伺服器的工作量,將客戶機請求轉發給內部網絡上的目標伺服器;並將從伺服器上得到的結果返回給Internet上請求連接的客戶端,此時代理伺服器與目標主機一起對外表現為一個伺服器。

    2、反向代理有哪些主要應用?

    現在許多大型web網站都用到反向代理。除了可以防止外網對內網伺服器的惡性攻擊、緩存以減少伺服器的壓力和訪問安全控制之外,還可以進行負載均衡,將用戶請求分配給多個伺服器。


9. php構建api上的CORS問題

    跨域資源共享 CORS (Cross-origin resource sharing) 是一個 W3C 標準

    這裡是常見的設定方式:

    <?php

      header("Access-Control-Allow-Origin: *");

      header("Access-Control-Allow-Methods: *");

      header("Access-Control-Allow-Headers: Origin, Methods, Content-Type");

當工程師的價值不再只是寫 Code,公司還看得見你的貢獻嗎?

 最近跟 AI、軟體開發流程轉變相關的討論越來越多。 很多人關注的是: AI 會不會取代工程師? 未來還需不需要寫 Code? 工程師應該學什麼新技能? 但有一個更現實的問題,可能很多工程師每天都正在面對: 當你的工作價值不再只是「寫多少 Code」,公司是...