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
欢迎关注微信公众号,留言交流。

相关文章:

翻译: