自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官:Nginx 和 Apache 的區(qū)別是什么?如何解決前端跨域問(wèn)題?Nginx 如何限流?Nginx 如何應(yīng)對(duì)驚群效應(yīng)?

開(kāi)發(fā) 前端
前端跨域問(wèn)題是指瀏覽器出于安全考慮,限制從一個(gè)域的網(wǎng)頁(yè)直接訪問(wèn)另一個(gè)域中的資源,從而導(dǎo)致AJAX請(qǐng)求失敗。Nginx可以通過(guò)配置HTTP響應(yīng)頭來(lái)解決前端跨域問(wèn)題。

面試官:Nginx和Apache(在性能上)的區(qū)別是什么?

Nginx和Apache在性能上的區(qū)別主要體現(xiàn)在以下幾個(gè)方面:

1. 并發(fā)連接處理能力

Nginx:

  • Nginx采用了事件驅(qū)動(dòng)的異步非阻塞架構(gòu),這種設(shè)計(jì)使得Nginx能夠高效地處理大量并發(fā)連接。
  • Nginx在處理并發(fā)連接時(shí),資源消耗較低,能夠保持較高的性能和穩(wěn)定性。

Apache:

  • Apache使用基于進(jìn)程或線程的模型來(lái)處理請(qǐng)求,每個(gè)請(qǐng)求通常會(huì)創(chuàng)建一個(gè)獨(dú)立的進(jìn)程或線程。
  • 在處理大量并發(fā)連接時(shí),Apache可能會(huì)因?yàn)閯?chuàng)建過(guò)多的進(jìn)程或線程而導(dǎo)致資源消耗增加,進(jìn)而影響性能。

2. 內(nèi)存消耗

Nginx:

  • Nginx的架構(gòu)更為輕量化,代碼量較少,因此通常比Apache消耗更少的內(nèi)存。
  • 這種低內(nèi)存消耗的特性使得Nginx在處理大量請(qǐng)求時(shí)更為高效。

Apache:

  • 相較于Nginx,Apache的內(nèi)存消耗可能會(huì)更高,尤其是在處理大量并發(fā)連接時(shí)。
  • 不過(guò),Apache的內(nèi)存消耗也取決于其配置和加載的模塊數(shù)量。

3. 靜態(tài)文件處理

Nginx:

  • Nginx在處理靜態(tài)文件時(shí)表現(xiàn)非常出色,能夠高效地提供靜態(tài)內(nèi)容。
  • Nginx的靜態(tài)文件處理能力得益于其高效的I/O處理機(jī)制和優(yōu)化的內(nèi)存管理。

Apache:

  • 雖然Apache也能處理靜態(tài)文件,但相比之下,其性能可能稍遜于Nginx。
  • Apache在處理靜態(tài)文件時(shí)可能需要更多的資源,尤其是在高并發(fā)場(chǎng)景下。

4. 動(dòng)態(tài)內(nèi)容處理

Nginx:

  • Nginx本身并不擅長(zhǎng)處理動(dòng)態(tài)內(nèi)容,但可以通過(guò)配置反向代理和負(fù)載均衡等功能,將動(dòng)態(tài)內(nèi)容處理的請(qǐng)求轉(zhuǎn)發(fā)給后端的應(yīng)用服務(wù)器。
  • Nginx也支持一些模塊來(lái)處理簡(jiǎn)單的動(dòng)態(tài)內(nèi)容,但功能相對(duì)有限。

Apache:

  • Apache在處理動(dòng)態(tài)內(nèi)容方面更具優(yōu)勢(shì),因?yàn)樗С侄喾N編程語(yǔ)言和模塊擴(kuò)展。
  • Apache可以通過(guò)加載不同的模塊來(lái)支持不同的動(dòng)態(tài)內(nèi)容處理需求,如PHP、Python等。

面試官:如何用Nginx解決前端跨域問(wèn)題?

前端跨域問(wèn)題是指瀏覽器出于安全考慮,限制從一個(gè)域的網(wǎng)頁(yè)直接訪問(wèn)另一個(gè)域中的資源,從而導(dǎo)致AJAX請(qǐng)求失敗。Nginx可以通過(guò)配置HTTP響應(yīng)頭來(lái)解決前端跨域問(wèn)題。

以下是用Nginx解決前端跨域問(wèn)題的詳細(xì)步驟:

1. 理解CORS和同源策略

CORS(Cross-Origin Resource Sharing,跨源資源共享)和同源策略是Web安全領(lǐng)域中兩個(gè)重要的概念,它們?cè)谔幚砜缬蛘?qǐng)求時(shí)起著至關(guān)重要的作用。以下是對(duì)這兩個(gè)概念的詳細(xì)解釋?zhuān)?/p>

(1) 同源策略(Same-Origin Policy)

① 定義:

同源策略是一種安全機(jī)制,用于防止不同來(lái)源的文檔或腳本相互干擾。它基于域名、協(xié)議和端口來(lái)定義一個(gè)“源”,只有當(dāng)兩個(gè)URL具有相同的協(xié)議、主機(jī)名和端口號(hào)時(shí),它們才被認(rèn)為是同源的。

② 限制:

  • DOM訪問(wèn)限制:一個(gè)頁(yè)面中的腳本不能讀取或操作另一個(gè)頁(yè)面的內(nèi)容。
  • Cookie限制:一個(gè)頁(yè)面中的腳本不能訪問(wèn)另一個(gè)頁(yè)面的Cookie。
  • AJAX請(qǐng)求限制:一個(gè)頁(yè)面中的腳本不能向另一個(gè)域名發(fā)送AJAX請(qǐng)求。

③ 目的:這種策略的目的是防止惡意網(wǎng)站竊取數(shù)據(jù),例如,防止一個(gè)網(wǎng)站通過(guò)JavaScript訪問(wèn)另一個(gè)網(wǎng)站的用戶數(shù)據(jù)。

(2) CORS(跨源資源共享)

① 定義:

CORS是一種機(jī)制,它使用額外的HTTP頭來(lái)告訴瀏覽器允許來(lái)自不同源的Web應(yīng)用訪問(wèn)該資源。通過(guò)配置CORS,服務(wù)器可以指定哪些源可以訪問(wèn)其資源,以及允許哪些類(lèi)型的請(qǐng)求方法(如GET、POST等)。

② 工作原理:

  • 預(yù)檢請(qǐng)求(Preflight Request):對(duì)于某些類(lèi)型的請(qǐng)求(如PUT、DELETE等),瀏覽器會(huì)先發(fā)送一個(gè)OPTIONS請(qǐng)求到服務(wù)器,詢(xún)問(wèn)服務(wù)器是否允許實(shí)際的請(qǐng)求。這個(gè)過(guò)程稱(chēng)為預(yù)檢請(qǐng)求。
  • 響應(yīng)頭:服務(wù)器通過(guò)設(shè)置特定的HTTP響應(yīng)頭來(lái)表明是否允許跨域請(qǐng)求。這些響應(yīng)頭包括Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers等。
  • 實(shí)際請(qǐng)求:如果預(yù)檢請(qǐng)求被批準(zhǔn),瀏覽器將發(fā)送實(shí)際的請(qǐng)求。

2. Nginx配置CORS

Nginx可以通過(guò)配置HTTP響應(yīng)頭來(lái)支持CORS。這些頭信息包括Access-Control-Allow-Origin、Access-Control-Allow-Methods、Access-Control-Allow-Headers和Access-Control-Allow-Credentials等。

(1) 找到或創(chuàng)建Nginx的配置文件:通常位于/etc/nginx/nginx.conf或/etc/nginx/conf.d/目錄中。

(2) 在需要跨域的server塊或location塊中添加CORS相關(guān)的頭部配置

以下是一個(gè)配置示例:

server {
    listen 80;
    server_name api.example.com;
    location / {
        # 設(shè)置允許跨域的域名,可以使用通配符'*'允許所有域訪問(wèn)
        add_header 'Access-Control-Allow-Origin' 'http://www.example.com';
        
        # 設(shè)置允許的HTTP方法
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE, PUT';
        
        # 設(shè)置允許的請(qǐng)求頭
        add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept, Origin, X-Requested-With';
        
        # 如果需要支持cookie,可以設(shè)置以下header
        add_header 'Access-Control-Allow-Credentials' 'true';
        
        # 如果是預(yù)檢請(qǐng)求(OPTIONS請(qǐng)求),則直接返回204狀態(tài)碼
        if ($request_method = 'OPTIONS') {
            return 204;
        }
        
        # 其他正常請(qǐng)求的處理邏輯
        proxy_pass http://backend_server;
    }
}

在上述配置中:

  • Access-Control-Allow-Origin:指定允許跨域請(qǐng)求的來(lái)源??梢栽O(shè)置為具體的域名(如http://www.example.com),或使用通配符*允許所有來(lái)源。但需要注意,使用通配符時(shí),不允許設(shè)置Access-Control-Allow-Credentials為true。
  • Access-Control-Allow-Methods:指定允許的HTTP請(qǐng)求方法,如GET、POST、OPTIONS、PUT、DELETE等。
  • Access-Control-Allow-Headers:指定允許客戶端發(fā)送的自定義HTTP頭部,如Authorization、Content-Type等。
  • Access-Control-Allow-Credentials:如果客戶端請(qǐng)求包括憑據(jù)(如Cookies),則該選項(xiàng)必須設(shè)置為true。此時(shí)Access-Control-Allow-Origin不能為*,必須為具體的域名

3. 處理預(yù)檢請(qǐng)求

預(yù)檢請(qǐng)求是CORS規(guī)范中定義的一種機(jī)制,用于在實(shí)際請(qǐng)求之前探測(cè)服務(wù)器是否允許某個(gè)跨域請(qǐng)求。瀏覽器在發(fā)送某些復(fù)雜請(qǐng)求之前,會(huì)發(fā)送一個(gè)OPTIONS請(qǐng)求進(jìn)行預(yù)檢,詢(xún)問(wèn)服務(wù)器是否允許該請(qǐng)求。Nginx可以通過(guò)簡(jiǎn)單的配置處理這種預(yù)檢請(qǐng)求,例如:

location / {
    if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
        add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Max-Age' 3600;
        return 204;
    }
    # 其余配置...
}

4. 配置通配符和動(dòng)態(tài)設(shè)置

(1) 配置通配符:在某些場(chǎng)景中,如果需要允許所有域訪問(wèn)(即不限制跨域請(qǐng)求的來(lái)源),可以將Access-Control-Allow-Origin設(shè)置為*。但如前所述,此時(shí)不能同時(shí)啟用Access-Control-Allow-Credentials。

(2) 動(dòng)態(tài)設(shè)置:如果需要根據(jù)請(qǐng)求動(dòng)態(tài)設(shè)置Access-Control-Allow-Origin,可以使用$http_origin變量來(lái)匹配請(qǐng)求來(lái)源。例如:

location / {
    if ($http_origin ~* 'https?://(www\.)?(example1\.com|example2\.com)') {
        add_header 'Access-Control-Allow-Origin' "$http_origin";
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, Accept';
    }
    if ($request_method = 'OPTIONS') {
        return 204;
    }
    proxy_pass http://backend_server;
}

這種配置可以在滿足特定條件時(shí),動(dòng)態(tài)地允許多個(gè)域名進(jìn)行跨域訪問(wèn)。

面試題:漏桶流算法和令牌桶算法知道嗎?如何使用Nginx限流?

在限流中,有兩個(gè)關(guān)鍵概念需要了解:閾值(一個(gè)單位時(shí)間內(nèi)允許的請(qǐng)求量)和拒絕策略(超過(guò)閾值的請(qǐng)求的拒絕策略,常見(jiàn)的拒絕策略有直接拒絕、排隊(duì)等待等)。

漏桶流算法和令牌桶算法是兩種常見(jiàn)的限流算法,以下是這兩種算法的具體介紹:

1. 漏桶流算法(Leaky Bucket Algorithm)

工作原理:

  • 漏桶算法可以看作是一個(gè)帶有常量服務(wù)時(shí)間的單服務(wù)器隊(duì)列。如果漏桶(包緩存)溢出,那么數(shù)據(jù)包會(huì)被丟棄。
  • 漏桶算法提供了一種機(jī)制,通過(guò)它,突發(fā)流量可以被整形以便為網(wǎng)絡(luò)提供一個(gè)穩(wěn)定的流量。漏桶強(qiáng)制一個(gè)常量的輸出速率,而不管輸入數(shù)據(jù)流的突發(fā)性。
  • 當(dāng)數(shù)據(jù)包到達(dá)漏桶時(shí),它們被放置在桶的底部。然后,數(shù)據(jù)包以固定的速率(漏出速率)從桶中漏出,注入網(wǎng)絡(luò)。如果到達(dá)速率超過(guò)漏出速率,并且桶已滿,則新的數(shù)據(jù)包將被丟棄。

優(yōu)點(diǎn):

  • 保證嚴(yán)格的延遲界限,避免一切由緩沖區(qū)溢出引起的丟失。
  • 網(wǎng)絡(luò)可以容易地驗(yàn)證通信量是否符合規(guī)范。

應(yīng)用場(chǎng)景:

  • 漏桶算法適用于需要嚴(yán)格控制輸出速率的場(chǎng)景,如網(wǎng)絡(luò)流量整形。

2. 令牌桶算法(Token Bucket Algorithm)

工作原理:

  • 令牌桶算法使用一個(gè)虛擬的桶來(lái)存放令牌,每個(gè)令牌代表一個(gè)數(shù)據(jù)包的發(fā)送權(quán)限。
  • 系統(tǒng)以固定的速率向桶中添加令牌,每當(dāng)一個(gè)數(shù)據(jù)包發(fā)送時(shí),就從桶中移除一個(gè)令牌。
  • 如果桶中沒(méi)有令牌,數(shù)據(jù)包則需要等待,直到有令牌可用。如果桶中的令牌數(shù)量超過(guò)其容量,則新生成的令牌會(huì)被丟棄。

優(yōu)點(diǎn):

  • 允許一定程度的突發(fā)傳輸,同時(shí)限制長(zhǎng)時(shí)間內(nèi)的傳輸速率。
  • 更靈活地處理流量,能夠更好地利用網(wǎng)絡(luò)資源。

應(yīng)用場(chǎng)景:

  • 令牌桶算法廣泛應(yīng)用于網(wǎng)絡(luò)流量管理、API請(qǐng)求限流等場(chǎng)景。

3. 漏桶流算法與令牌桶算法的比較


漏桶流算法

令牌桶算法

工作原理

突發(fā)流量被整形為穩(wěn)定流量,輸出速率恒定

令牌生成速率恒定,數(shù)據(jù)包發(fā)送需消耗令牌

流量特性

強(qiáng)制限制數(shù)據(jù)傳輸速率,對(duì)突發(fā)流量缺乏效率

允許突發(fā)傳輸,同時(shí)限制平均傳輸速率

資源利用

在無(wú)擁塞時(shí)不能有效利用網(wǎng)絡(luò)資源

能夠更有效地利用網(wǎng)絡(luò)資源

適用場(chǎng)景

網(wǎng)絡(luò)流量整形

網(wǎng)絡(luò)流量管理、API請(qǐng)求限流

在實(shí)際應(yīng)用中,選擇哪種限流算法取決于具體的需求和場(chǎng)景。例如,如果系統(tǒng)需要嚴(yán)格控制輸出速率并避免突發(fā)流量,則漏桶算法可能更合適。而如果系統(tǒng)需要允許一定程度的突發(fā)傳輸,并希望更靈活地處理流量,則令牌桶算法可能更合適。

在Nginx中配置限流,主要通過(guò)limit_req和limit_conn兩個(gè)模塊來(lái)實(shí)現(xiàn)。以下是具體的配置方法:

1. 使用limit_req模塊限制請(qǐng)求速率

limit_req模塊基于令牌桶算法來(lái)限制每秒的請(qǐng)求次數(shù)。配置步驟如下:

(1) 定義限流區(qū)域:

在http塊中,使用limit_req_zone指令來(lái)定義一個(gè)限流區(qū)域。這個(gè)區(qū)域會(huì)存儲(chǔ)在共享內(nèi)存中,并用于跟蹤請(qǐng)求的速率。

http {
    limit_req_zone $binary_remote_addr zone=mylimit:10m rate=1r/s;
    ...
}

這里,$binary_remote_addr是客戶端IP地址的二進(jìn)制表示,znotallow=mylimit:10m定義了一個(gè)名為mylimit的共享內(nèi)存區(qū)域,大小為10MB,rate=1r/s設(shè)置了每秒的請(qǐng)求速率限制為1個(gè)請(qǐng)求。

(2) 應(yīng)用限速規(guī)則:

在server或location塊中,使用limit_req指令來(lái)應(yīng)用限速規(guī)則。

server {
    ...
    location / {
        limit_req zone=mylimit burst=5 nodelay;
        ...
    }
    ...
}

這里,znotallow=mylimit指定了使用前面定義的mylimit區(qū)域,burst=5允許在超過(guò)速率限制后,突發(fā)處理最多5個(gè)請(qǐng)求,nodelay表示這些突發(fā)請(qǐng)求將立即處理,而不會(huì)等待新的令牌生成。

2. 使用limit_conn模塊限制并發(fā)連接數(shù)

limit_conn模塊用于限制同時(shí)連接數(shù)。配置步驟如下:

(1) 定義連接限制區(qū)域:

在http塊中,使用limit_conn_zone指令來(lái)定義一個(gè)連接限制區(qū)域。

http {
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    ...
}

這里,$binary_remote_addr是客戶端IP地址的二進(jìn)制表示,znotallow=addr:10m定義了一個(gè)名為addr的共享內(nèi)存區(qū)域,大小為10MB。

(2) 應(yīng)用連接限制規(guī)則:

在server或location塊中,使用limit_conn指令來(lái)應(yīng)用連接限制規(guī)則。

server {
    ...
    location / {
        limit_conn addr 10;
        ...
    }
    ...
}

這里,addr引用了之前定義的limit_conn_zone的名稱(chēng),10表示最大并發(fā)連接數(shù)限制為10。

3. 其他限流配置

除了上述基本的限流配置外,Nginx還支持其他限流策略,如:

  • 設(shè)置黑白名單:通過(guò)ngx_http_geo_module和ngx_http_map_module模塊,可以設(shè)置黑白名單來(lái)控制哪些客戶端IP地址可以訪問(wèn)或禁止訪問(wèn)特定的資源或整個(gè)服務(wù)器。
  • 限制數(shù)據(jù)傳輸速度:使用limit_rate和limit_rate_after指令,可以限制對(duì)特定位置(location)的響應(yīng)速度。

面試官:Nginx怎么判斷別的IP不可訪問(wèn)?

Nginx判斷別的IP不可訪問(wèn)的功能,通常是通過(guò)其內(nèi)置的ngx_http_access_module模塊來(lái)實(shí)現(xiàn)的。該模塊允許基于客戶端的IP地址來(lái)允許或拒絕對(duì)網(wǎng)站資源的訪問(wèn)。

1. 基本配置指令

  • allow:允許指定的IP地址或IP地址段訪問(wèn)服務(wù)器。
  • deny:拒絕指定的IP地址或IP地址段訪問(wèn)服務(wù)器。

2. 配置位置

這些指令可以配置在http、server、location、limit_except等上下文中,從而對(duì)整個(gè)服務(wù)器、特定虛擬主機(jī)或特定資源進(jìn)行訪問(wèn)控制。

3. 配置示例

(1) 拒絕單個(gè)IP地址

假設(shè)要拒絕IP地址為192.168.1.100的所有訪問(wèn)請(qǐng)求,可以在Nginx配置文件中使用以下配置:

server {
    listen 80;
    server_name example.com;
    location / {
        deny 192.168.1.100;
        allow all;
    }
}

在這個(gè)配置中,所有來(lái)自192.168.1.100的請(qǐng)求將被拒絕,而其他IP地址的請(qǐng)求將被允許。

(2) 拒絕多個(gè)IP地址或IP地址段

如果需要同時(shí)拒絕多個(gè)IP地址或一個(gè)IP地址段,可以使用多個(gè)deny指令或指定一個(gè)CIDR范圍。例如:

server {
    listen 80;
    server_name example.com;
    location / {
        deny 192.168.1.100;
        deny 192.168.1.101;
        deny 192.168.1.0/24; # 拒絕整個(gè)子網(wǎng)段
        allow all;
    }
}

上述配置會(huì)拒絕192.168.1.100、192.168.1.101以及192.168.1.0/24網(wǎng)段中的所有IP地址的訪問(wèn)。

(3) 允許和拒絕的優(yōu)先級(jí)

在Nginx中,allow和deny指令具有優(yōu)先級(jí)。Nginx從上到下依次讀取配置,當(dāng)有多個(gè)allow和deny指令時(shí),首先匹配到的規(guī)則會(huì)生效。通常情況下,deny指令在allow指令之前時(shí),拒絕的優(yōu)先級(jí)更高。例如:

server {
    listen 80;
    server_name example.com;
    location / {
        allow 192.168.1.0/24;
        deny all;
    }
}

在這個(gè)配置中,盡管有一個(gè)允許192.168.1.0/24網(wǎng)段訪問(wèn)的規(guī)則,但由于deny all指令在其后,所以該規(guī)則會(huì)被忽略,最終結(jié)果是拒絕所有IP地址的訪問(wèn)(這里的配置邏輯實(shí)際上是有問(wèn)題的,因?yàn)閍llow指令在deny之前會(huì)先匹配,但這里的示例是為了說(shuō)明優(yōu)先級(jí)的概念。正確的配置應(yīng)該是先deny all,然后再根據(jù)需要allow特定的IP,或者將deny指令放在allow指令之前以確保拒絕的規(guī)則優(yōu)先生效。不過(guò),由于Nginx會(huì)按順序匹配第一個(gè)滿足條件的規(guī)則,因此通常我們會(huì)將更具體的規(guī)則(如allow)放在前面,然后用一個(gè)deny all作為兜底規(guī)則來(lái)拒絕所有未明確允許的訪問(wèn))。然而,為了避免混淆,通常建議按照邏輯順序和實(shí)際需求來(lái)配置allow和deny指令,以確保配置的正確性和有效性。

4. 基于HTTP頭部的IP信息

在某些情況下,客戶端的真實(shí)IP地址可能被隱藏在HTTP頭部中,如通過(guò)反向代理服務(wù)器時(shí)。在這種情況下,需要基于HTTP頭部中的IP信息來(lái)進(jìn)行訪問(wèn)控制。常見(jiàn)的HTTP頭部字段包括X-Forwarded-For和X-Real-IP??梢酝ㄟ^(guò)$http_x_forwarded_for變量來(lái)獲取該IP信息,并結(jié)合if語(yǔ)句進(jìn)行訪問(wèn)控制。例如:

server {
    listen 80;
    server_name example.com;
    location / {
        if ($http_x_forwarded_for = "192.168.1.100") {
            return 403;
        }
        proxy_pass http://backend;
    }
}

在這個(gè)配置中,如果請(qǐng)求的X-Forwarded-For頭部中包含192.168.1.100,則Nginx會(huì)返回403禁止訪問(wèn)的狀態(tài)碼。

5. 訪問(wèn)日志

為了進(jìn)一步分析和控制IP地址的訪問(wèn)情況,可以使用Nginx的訪問(wèn)日志功能。通過(guò)日志記錄,可以跟蹤哪些IP地址頻繁訪問(wèn)服務(wù)器,從而有助于做出相應(yīng)的訪問(wèn)控制策略。在Nginx配置中,可以自定義日志格式并將客戶端IP地址記錄到日志中。

6. 其他策略

除了使用deny指令直接拒絕訪問(wèn)外,還可以通過(guò)以下方式進(jìn)一步增強(qiáng)IP訪問(wèn)的限制:

  • 使用Nginx的limit_conn和limit_req模塊,根據(jù)IP地址限制請(qǐng)求的頻率或并發(fā)連接數(shù)。
  • 使用Nginx社區(qū)提供的第三方模塊(如ngx_http_geoip_module)來(lái)基于地理位置限制IP訪問(wèn)。
  • 結(jié)合操作系統(tǒng)層面的防火墻(如iptables、firewalld)來(lái)限制IP地址的訪問(wèn)。

面試官:什么是驚群效應(yīng),驚群效應(yīng)消耗了什么,Nginx的驚群效應(yīng)是如何發(fā)生的,又是如何應(yīng)對(duì)的驚群效應(yīng)?

驚群效應(yīng)是一個(gè)在操作系統(tǒng)多線程或多進(jìn)程環(huán)境中常見(jiàn)的現(xiàn)象。當(dāng)多個(gè)線程或進(jìn)程同時(shí)阻塞等待同一個(gè)事件(例如新連接的到來(lái))時(shí),如果該事件觸發(fā),系統(tǒng)可能會(huì)喚醒所有等待的線程或進(jìn)程。然而,實(shí)際上只有一個(gè)線程或進(jìn)程能夠成功獲取資源或處理事件,而其他被喚醒的線程或進(jìn)程則會(huì)重新進(jìn)入休眠狀態(tài)。這種現(xiàn)象導(dǎo)致了資源的浪費(fèi),包括無(wú)效的上下文切換和調(diào)度,以及可能導(dǎo)致的緩存失效等問(wèn)題。

對(duì)于 Nginx 的驚群?jiǎn)栴},我們首先需要理解的是,在 Nginx 啟動(dòng)過(guò)程中,master 進(jìn)程會(huì)監(jiān)聽(tīng)配置文件中指定的各個(gè)端口,然后 master 進(jìn)程就會(huì)調(diào)用 fork() 方法創(chuàng)建各個(gè)子進(jìn)程,根據(jù)進(jìn)程的工作原理,子進(jìn)程是會(huì)繼承父進(jìn)程的全部?jī)?nèi)存數(shù)據(jù)以及監(jiān)聽(tīng)的端口的,所以 worker 進(jìn)程在啟動(dòng)之后也是會(huì)監(jiān)聽(tīng)各個(gè)端口的。

當(dāng)客戶端有新建連接的請(qǐng)求到來(lái)時(shí),就會(huì)觸發(fā)各個(gè) worker 進(jìn)程的連接建立事件,但是只有一個(gè) worker 進(jìn)程能夠正常處理該事件,而其他的 worker 進(jìn)程會(huì)發(fā)現(xiàn)事件已經(jīng)失效,從而重新循環(huán)進(jìn)入等待狀態(tài)。這種由于一個(gè)連接事件的到來(lái)而 “驚” 起了所有 worker 進(jìn)程的現(xiàn)象就是Nginx的驚群?jiǎn)栴}。

Nginx的解決方案是:每個(gè) worker 進(jìn)程被創(chuàng)建的時(shí)候,都會(huì)調(diào)用 ngx_worker_process_init() 方法初始化當(dāng)前 worker 進(jìn)程,每個(gè) worker 進(jìn)程都會(huì)調(diào)用 epoll_create() 方法為自己創(chuàng)建一個(gè)獨(dú)有的 epoll 句柄。

對(duì)于每一個(gè)需要監(jiān)聽(tīng)的端口,都有一個(gè)文件描述符與之對(duì)應(yīng),而 worker 進(jìn)程只有將該文件描述符通過(guò) epoll_ctl() 方法添加到當(dāng)前進(jìn)程的 epoll 句柄中,并且監(jiān)聽(tīng) accept 事件,此時(shí)才會(huì)被客戶端的連接建立事件觸發(fā)。

基于這個(gè)原理,nginx 就使用了一個(gè)共享鎖來(lái)控制當(dāng)前進(jìn)程是否有權(quán)限將需要監(jiān)聽(tīng)的端口添加到當(dāng)前進(jìn)程的 epoll 句柄中。通過(guò)這種方式,就保證了每次事件發(fā)生時(shí),只有一個(gè) worker 進(jìn)程會(huì)被觸發(fā)。如下圖所示為 worker 進(jìn)程工作循環(huán)的一個(gè)示意圖:

這里關(guān)于圖中的流程,需要說(shuō)明的一點(diǎn)是,每個(gè) worker 進(jìn)程在進(jìn)入循環(huán)之后就會(huì)嘗試獲取共享鎖,如果沒(méi)有獲取到,就會(huì)將所監(jiān)聽(tīng)的端口的文件描述符從當(dāng)前進(jìn)程的 epoll 句柄中移除(即使并不存在也會(huì)移除),這么做的主要目的是防止丟失客戶端連接事件,即使這可能造成少量的驚群?jiǎn)栴},但是并不嚴(yán)重。

面試題:Nginx如何實(shí)現(xiàn)后端服務(wù)的健康檢查?

Nginx本身不直接提供內(nèi)置的后端服務(wù)健康檢查功能,但可以通過(guò)一些模塊和配置實(shí)現(xiàn)類(lèi)似的效果。以下是一些常見(jiàn)的方法:

1. 使用 ngx_http_upstream_check_module 模塊

ngx_http_upstream_check_module 是一個(gè)第三方模塊,用于對(duì)后端服務(wù)進(jìn)行健康檢查。它需要在編譯 Nginx 時(shí)包含這個(gè)模塊。

安裝和配置示例:

(1) 編譯 Nginx 并包含 ngx_http_upstream_check_module:

下載 Nginx 源代碼并編譯:

wget http://nginx.org/download/nginx-<version>.tar.gz
tar -zxvf nginx-<version>.tar.gz
cd nginx-<version>/
# 添加 --add-module 參數(shù)來(lái)包含第三方模塊
./configure --add-module=/path/to/ngx_http_upstream_check_module --prefix=/usr/local/nginx
make
sudo make install

(2) 配置 Nginx:

在 Nginx 配置文件中(通常是 /usr/local/nginx/conf/nginx.conf),添加健康檢查配置:

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
}
server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
    # 健康檢查配置
    location /check {
        check interval=3000 rise=2 fall=3 timeout=2000 type=http;
        check_http_send "HEAD / HTTP/1.0\r\n\r\n";
        check_http_expect_status 200-299;
    }
}

Nginx會(huì)根據(jù)/check location塊中的配置,定期(每3000毫秒)向backend1.example.com和backend2.example.com發(fā)送HTTP HEAD請(qǐng)求進(jìn)行健康檢查。

如果backend1.example.com連續(xù)失敗3次(fall=3)健康檢查(每次檢查超時(shí)時(shí)間為2000毫秒,且期望的HTTP狀態(tài)碼為200-299),則Nginx會(huì)將backend1.example.com標(biāo)記為不健康。

相反,如果backend1.example.com在標(biāo)記為不健康后連續(xù)成功2次(rise=2)健康檢查,則它會(huì)被重新標(biāo)記為健康。

如果backend1.example.com被標(biāo)記為不健康,Nginx將只會(huì)將請(qǐng)求代理到backend2.example.com(假設(shè)它是健康的)。

如果backend2.example.com也變?yōu)椴唤】?,那么Nginx將無(wú)法代理任何新的請(qǐng)求到該上游組,除非有服務(wù)器恢復(fù)健康或您添加了更多的服務(wù)器到上游組中。

2. 使用 proxy_next_upstream 和 proxy_connect_timeout 配置

雖然這種方法不是真正的健康檢查,但可以通過(guò)配置 Nginx 的代理行為來(lái)間接實(shí)現(xiàn)后端服務(wù)的故障轉(zhuǎn)移。

配置示例:

upstream backend {
    server backend1.example.com;
    server backend2.example.com;
}
server {
    listen 80;
    location / {
        proxy_pass http://backend;
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
        proxy_connect_timeout 5s;
        proxy_read_timeout 30s;
        proxy_send_timeout 30s;
    }
}

在這個(gè)配置中,如果后端服務(wù)返回錯(cuò)誤碼(如 500, 502, 503, 504),或者連接超時(shí),Nginx 會(huì)嘗試將請(qǐng)求轉(zhuǎn)發(fā)到下一個(gè)后端服務(wù)器。

責(zé)任編輯:趙寧寧 來(lái)源: 程序員阿沛
相關(guān)推薦

2024-09-11 16:56:39

2021-06-06 13:05:15

前端跨域CORS

2022-09-07 07:05:25

跨域問(wèn)題安全架構(gòu)

2010-03-24 09:25:36

Nginx配置

2023-02-15 07:03:41

跨域問(wèn)題面試安全

2022-04-01 12:38:32

cookie代碼面試

2024-10-29 16:41:24

SpringBoot跨域Java

2023-11-20 10:09:59

2020-09-07 06:28:37

Nginx靜態(tài)負(fù)載均衡動(dòng)態(tài)負(fù)載均衡

2020-09-18 15:10:51

Web前端技術(shù)

2024-12-25 15:44:15

2024-02-27 08:14:51

Nginx跨域服務(wù)

2024-03-13 13:41:18

前端CPU負(fù)載

2024-02-04 10:08:34

2022-03-11 10:01:47

開(kāi)發(fā)跨域技術(shù)

2024-04-16 08:15:07

CHAR數(shù)據(jù)字符串

2010-03-24 18:19:42

Nginx php

2020-09-14 06:57:30

緩存穿透雪崩

2024-07-11 08:36:47

Nginx端口服務(wù)器

2019-09-02 07:42:50

nginx服務(wù)器跨域
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)