nginx: [emerg] could not build server_names_hash問題

最近查找測試環境nginx的時候,遇到了個不那麼常見的nginx錯誤,如下所示:

[root@test conf]# nginx -t
nginx: [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 64
nginx: configuration file /usr/local/openresty/nginx/nginx/conf/nginx.conf test failed

nginx在啓動或者重新讀取配置的時候,爲了加快處理一些靜態數據集(比如server name, MIME types等,配置nginx的時候你應該遇到過),這東西放在一個緩存塊裏面(緩存在存儲機構中,介於內存和cpu寄存器間,離cpu比較近,現代cpu封裝再cpu裏面,L1,L2,L3什麼的,特點就是快,快過內存,慢於寄存器),這個緩存塊的大小由server_names_hash_bucket_size這個參數控制,物理cpu不一樣,默認大小不一樣,通常是2的次方,增加大小的時候,按照等級調整數值。

1. 錯誤原因一(大部分人遇到的):

Root cause one: your server_name realy too loog

你域名的確很長,超過了默認值,此時你只能調大數值:

http {
        server_names_hash_bucket_size 64;
        .....
    }

2. 錯誤原因二(工作不苦,命苦的人遇到的):

Root cause two: config mistake

有時候,由於錯誤配置,域名實際沒有那麼長,只是各種配置語法弄混了。比如,本該空格分割的多個域名,你給整成了逗號分割,不巧996低血糖,看半天不一定能發現問題在哪裏,如下所示,也會同樣報錯的。別問我爲什麼知道,因爲我遇到了,一個老舊測試服務器上面的廢棄域名就是這麼寫的......

server {
    server_name www.test1.com,www.test2.com,www.test3.com,www.test4.com;
}

這個時候,輪不到要更改server_names_hash_bucket_size的值,修復配置錯誤即可。

3. 測試樣本(Try it by yourself)

➜  ~ sudo cat /etc/nginx/conf.d/test.com.conf 
server {
    listen 80;
    # just for test
    #server_name www.1111.2222.3333.4444.5555.6666.7777.8888.com;          # too long server_name test, fail
    #server_name www.1111.2222.3333.4444.5555.com;                         # not so long, ok
    #server_name www.test1.com wwww.test2.com www.test3.com www.test4.com; # multi server_name, ok
    #server_name www.test1.com,wwww.test2.com,www.test3.com,www.test4.com; # mistake config, comma separated, multi server_name, fail
}

如上所示,不同情況簡單測試下,會加深印象。

4. 背景基礎知識

server_names_hash_bucket_size 是什麼?nginx官方文檔:

Syntax:	server_names_hash_bucket_size size;
Default: server_names_hash_bucket_size 32|64|128;
Context: http
Sets the bucket size for the server names hash tables. The default value depends on the size of the processor’s cache line. The details of setting up hash tables are provided in a separate document.

什麼是the processor’s cache line?

It could be left up to the programmer or compiler to determine what data should be placed in the cache memories, but this would be complicated since different processors have different numbers of caches and different cache sizes. It would also be hard to determine how much of the cache memory to allocate to each program when several programs are running on the same processor.

Instead the allocation of space in the cache is managed by the processor. When the processor accesses a part of memory that is not already in the cache it loads a chunk of the memory around the accessed address into the cache, hoping that it will soon be used again.

The chunks of memory handled by the cache are called cache lines. The size of these chunks is called the cache line size. Common cache line sizes are 32, 64 and 128 bytes.

A cache can only hold a limited number of lines, determined by the cache size. For example, a 64 kilobyte cache with 64-byte lines has 1024 cache lines.

nginx hashes 相關說明:

To quickly process static sets of data such as server names, map directive’s values, MIME types, names of request header strings, nginx uses hash tables. During the start and each re-configuration nginx selects the minimum possible sizes of hash tables such that the bucket size that stores keys with identical hash values does not exceed the configured parameter (hash bucket size). The size of a table is expressed in buckets. The adjustment is continued until the table size exceeds the hash max size parameter. Most hashes have the corresponding directives that allow changing these parameters, for example, for the server names hash they are server_names_hash_max_size and server_names_hash_bucket_size.

The hash bucket size parameter is aligned to the size that is a multiple of the processor’s cache line size. This speeds up key search in a hash on modern processors by reducing the number of memory accesses. If hash bucket size is equal to one processor’s cache line size then the number of memory accesses during the key search will be two in the worst case — first to compute the bucket address, and second during the key search inside the bucket. Therefore, if nginx emits the message requesting to increase either hash max size or hash bucket size then the first parameter should first be increased.

維基百科cache:

A CPU cache is a hardware cache used by the central processing unit (CPU) of a computer to reduce the average cost (time or energy) to access data from the main memory.[1] A cache is a smaller, faster memory, located closer to a processor core, which stores copies of the data from frequently used main memory locations. Most CPUs have a hierarchy of multiple cache levels (L1, L2, often L3, and rarely even L4), with different instruction-specific and data-specific caches at level 1.

Data is transferred between memory and cache in blocks of fixed size, called cache lines or cache blocks. When a cache line is copied from memory into the cache, a cache entry is created. The cache entry will include the copied data as well as the requested memory location (called a tag).

存儲層次(memory hierarchy):

computer memory hierarchy

最後修改於: Monday, August 28, 2023

相關文章:

翻譯: