NGINX 官方給的十個常見的設定錯誤

也是在 Hacker News 上看到的,NGINX 官方給的 10 個設定上的常見錯誤:「Avoiding the Top 10 NGINX Configuration Mistakes」,對應的討論串在「Avoiding the top Nginx configuration mistakes (nginx.com)」這邊,看了一下裡面還蠻多蠻實用的?(雖然有些算是官方自己的偏見,或是官方自己在搞事...)

第一個是 worker_connections 設定與 fd 的上限沒有對應,因為每個連線會吃掉兩個 fd,所以要給夠才有辦法讓 connection 衝上去:

The common configuration mistake is not increasing the limit on FDs to at least twice the value of worker_connections. The fix is to set that value with the worker_rlimit_nofile directive in the main configuration context.

另外就是要檢查系統的 limit 設定,像是 /etc/security/limit.conf 這類的設定。

第二個是 error_log off 這個設法,在 NGINX 裡面是有 access_log off,但沒有 error_log off 這個設法,如果你這樣設的話會寫到 error 這個檔名內。所以如果真的要丟掉的話要丟到 /dev/null,像是官方給的範例這樣:

error_log /dev/null emerg;

第三個是 NGINX 對 upstream (backend) 沒有設定 keepalive,這會導致在量很大的時候會產生不少 overhead。

第四個是違反直覺的繼承設定,官方用這樣的範例來表達:

http {
    add_header X-HTTP-LEVEL-HEADER 1;
    add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

    server {
        listen 8080;
        location / {
            return 200 "OK";
        } 
    }

    server {
        listen 8081;
        add_header X-SERVER-LEVEL-HEADER 1;

        location / {
            return 200 "OK";
        }

        location /test {
            add_header X-LOCATION-LEVEL-HEADER 1;
            return 200 "OK";
        }

        location /correct {
            add_header X-HTTP-LEVEL-HEADER 1;
            add_header X-ANOTHER-HTTP-LEVEL-HEADER 1;

            add_header X-SERVER-LEVEL-HEADER 1;
            add_header X-LOCATION-LEVEL-HEADER 1;
            return 200 "OK";
        } 
    }
}

而你會發現 add_header 會蓋掉先前繼承的項目,但同一個 block 之間會疊加而不是蓋掉...

所以打 localhost:8081/test 的時候只會有 X-LOCATION-LEVEL-HEADER: 1;打 localhost:8081/correct 會有四個 HTTP headers...

第五個算是官方自己的偏見,我們一般都會希望壓低 TTFB (Time To First Byte),把 proxy_buffering 關閉算是常態了。

第六個是官方雖然實做了 if 但很不希望你拿來用。

第七個是 health check 的正確設法,避免多個 block 都有 health check,造成無用的功夫。

第八個是保護內部的資訊,這邊給的範例是 stub_status

第九個是個地雷,ip_hash 這個演算法可以依據 client 的 IP address 來打散流量到後端的伺服器上,對於 IPv6 他會拿整個 IPv6 當作 key (128 bits),但對 IPv4 他只會拿前面三碼 (24 bits) 當作 key:

The ip_hash algorithm load balances traffic across the servers in an upstream{} block, based on a hash of the client IP address. The hashing key is the first three octets of an IPv4 address or the entire IPv6 address. The method establishes session persistence, which means that requests from a client are always passed to the same server except when the server is unavailable.

這完全就是官方自己在搞... 而 workaround 是自己指定 key:

The fix is to use the hash algorithm instead with the $binary_remote_addr variable as the hash key.

第十個是沒有使用 upstream,大多數的情況就是測試發現會動,就直接上 production 的關係 XDDD

Leave a Reply

Your email address will not be published. Required fields are marked *