Nginx調優總結-第六部分編譯優化與簡單測試

第六部分 編譯優化

Nginx可以自行編譯,所以裏面可以設置多個編譯策略. 
也可以自行修改源碼,便於比如進行ip_hash的全IP地址驗證.
也可以修改nginx的版本號等信息, 避免內發現. 

還可以按照不同的CPU類型進行優化
選擇更高級別的優化參數.
不編譯debug等的信息,便於降低內存佔用等. 

修改源碼-1

ip_hash 時修改爲全部IPV4地址段進行取hash處理

src/http/modules/ngx_http_upstream_ip_hash_module.c

把裏面的3修改成4 就可以進行全IP地址段的hash運算. 

    case AF_INET:
        sin = (struct sockaddr_in *) r->connection->sockaddr;
        iphp->addr = (u_char *) &sin->sin_addr.s_addr;
        iphp->addrlen = 3; # 修改成4 
        break;
    default:
        iphp->addr = ngx_http_upstream_ip_hash_pseudo_addr;
        iphp->addrlen = 3; # 修改成4
    }

    for ( ;; ) {

        for (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) {
            hash = (hash * 113 + iphp->addr[i]) % 6271;
        }

修改源碼-2

修改nginx的版本號
需要修改多個文件:
注意 我把 nginx修改成我我的ID. 

vim src/core/nginx.h
#define NGINX_VERSION      "1127"
#define NGINX_VER          "JNXLH/" NGINX_VERSION
#define NGINX_VAR          "JNXLH"

vim src/http/ngx_http_header_filter_module.c
static u_char ngx_http_server_string[] = "Server: JNXLH" CRLF;
static u_char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
static u_char ngx_http_server_build_string[] = "Server: " NGINX_VER_BUILD CRLF;

修改源碼-3

去除 debug信息

vim auto/cc/gcc
# debug
CFLAGS=”$CFLAGS -g”
可以將 CFLAGS進行註釋就可以. 

注意 取消了debug之後文件會出現極大的縮小. 

我用下面的編譯腳本編譯完後文件由8.3M 減小到了4.4M大小. 

編譯打包命令

./configure --prefix=/opt/nginx \
--sbin-path=/opt/nginx/nginx \
--conf-path=/opt/nginx/nginx.conf \
--pid-path=/opt/nginx/nginx.pid \
--with-http_ssl_module \
--with-pcre=../pcre2-10.42 \
--with-zlib=../zlib-1.2.13 \
--with-openssl=../openssl-1.1.1s \
--with-stream \
--with-stream_ssl_preread_module \
--with-cc-opt='-O3' \
--with-cpu-opt=core 

編譯打包命令解析

--with-pcre=../pcre2-10.42 \
--with-zlib=../zlib-1.2.13 \
--with-openssl=../openssl-1.1.1s \
這三個是使用了很新的組建, 有正則表達式, 壓縮 和openssl加解密.

--with-http_ssl_module \
增加https的支持.

--with-stream \
--with-stream_ssl_preread_module \
增加四層負載的功能. 
增加四層負載然後可以進行轉發https的功能. 

--with-cc-opt='-O3' \
編譯優化參數開到最高, 編譯時間變長,但是編譯後的性能最好. 

--with-cpu-opt=core 
官方說明裏面可以寫pentium等.但是據說如果是服務器可以寫core
所以進行驗證了. 

config的結果信息

Configuration summary
  + using PCRE2 library: ../pcre2-10.42
  + using OpenSSL library: ../openssl-1.1.1s
  + using zlib library: ../zlib-1.2.13

  nginx path prefix: "/opt/nginx"
  nginx binary file: "/opt/nginx/nginx"
  nginx modules path: "/opt/nginx/modules"
  nginx configuration prefix: "/opt/nginx"
  nginx configuration file: "/opt/nginx/nginx.conf"
  nginx pid file: "/opt/nginx/nginx.pid"
  nginx error log file: "/opt/nginx/logs/error.log"
  nginx http access log file: "/opt/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp"

編譯成功後處理響應文件

進入編譯後的文件目錄
cd /opt/nginx
執行命令
sed -i 's/nginx/JNXLH/g' html/index.html
就會修改 訪問界面, 沒有nginx的字樣了. 

然後F12看到的服務器信息爲:
Server: JNXLH/1127

使用ab進行驗證

安裝ab非常簡單:
yum -y install httpd-tools

最簡單的測試可以使用兩個參數進行:
-n	即requests,用於指定壓力測試總共的執行次數。
-c	即concurrency,用於指定的併發數。

簡單的ab測試結果

優化後的測試結果:
ab -c 10000 -n 50000 http://10.110.80.116:81/

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  244  65.2    242    1287
Processing:    71  258  85.4    253     504
Waiting:        0   32  99.2      0     381
Total:        385  503  55.8    496    1502

優化編譯前的測試結果:
ab -c 10000 -n 50000 http://10.110.80.116:82/

              min  mean[+/-sd] median   max
Connect:        0  258  84.9    252    1388
Processing:    76  271  95.5    264     541
Waiting:        0   34 105.8      0     444
Total:        426  529  74.8    506    1509

基於容器運行的測試結果

docker run --name nginx83 -d -p 83:83 -v /opt/nginx/nginx83.conf:/etc/nginx/nginx.conf nginx
使用docker0 方式 原生 nginx 無調優的容器.
掛載模式的nginx的配置文件唯一不同的是使用83端口. 
ab -c 10000 -n 50000 http://10.110.80.116:83/
              min  mean[+/-sd] median   max
Connect:        0  344 158.6    325    1344
Processing:    48  326 109.4    326     664
Waiting:        0   28 105.5      0     470
Total:        429  671 175.9    633    1829

docker run --name nginx84 -d --net=host -v /opt/nginx/nginx84.conf:/etc/nginx/nginx.conf nginx
這個命令使用 宿主機的網絡進行暴露服務. 
端口使用 84的端口. 
ab -c 10000 -n 50000 http://10.110.80.116:84/
              min  mean[+/-sd] median   max
Connect:        0  254  55.7    254     363
Processing:    53  266  88.9    263     515
Waiting:        0   33 102.2      0     373
Total:        346  520  46.6    516     678

最小化編譯的二進制的性能測試結果

編譯配置文件爲:
./configure --prefix=/opt/nginx85 \
--sbin-path=/opt/nginx85/nginx \
--conf-path=/opt/nginx85/nginx.conf \
--pid-path=/opt/nginx85/nginx.pid \
--with-cc-opt='-O3' \
--with-cpu-opt=core 

注意這樣編譯打包的文件 僅有 900k 左右. 比之前的4.4M又有了較大的縮減. 
ab -c 10000 -n 50000 http://10.110.80.116:85/
              min  mean[+/-sd] median   max
Connect:        0  242  68.6    240    1292
Processing:    53  254  86.9    250     502
Waiting:        0   31  97.9      0     356
Total:        336  496  62.6    493    1507

擴充測試

工作線程和內核綁定都是AUTO時
4路18核心 144線程的測試結果:
Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0  434 165.6    403    1359
Processing:    44  487 143.3    487     761
Waiting:        0  142  91.3    134     749
Total:        594  922 137.8    941    1921
是所有的測試結果裏面最差的. 

改成 8個工作進程.加auto綁定核心
              min  mean[+/-sd] median   max
Connect:        0  381 170.0    350    1549
Processing:    63  408 112.4    410     616
Waiting:        0  157  98.7    141     589
Total:        506  788 158.1    818    1842

也比較差. 但是比AUTO要好
說明在簡單處理情況下單線程最好. 
但是稍微複雜一點 包含反向代理的還是需要多幾個worker進程纔可以.

增加 -k 參數

具體結果不再寫了. 
但是發現增加了 keepalive
多核心的平均時間到了200ms 有了巨大的提升. 
並且在不通配置上面都有了一些提升. 
單線程優化過的編譯包 81 端口: 480毫秒(keepalive 之前 503毫秒)
單線程優化前的編譯包 82 端口: 500毫秒(keepalive 之前 520毫秒)
docker單線程docker0 83端口:  620毫秒(keepalive 之前 670毫秒)
docker單線程host網絡 84端口:  490毫秒(keepalive 之前 520+毫秒)

多線程的測試時間:86 87端口: 180-200毫秒(keepalive之前 900-780毫秒)
核心越多提升越大. 

ab的部分參數解釋-1:

-n	即requests,用於指定壓力測試總共的執行次數。
-c	即concurrency,用於指定的併發數。
-t	即timelimit,等待響應的最大時間(單位:秒)。
-b	即windowsize,TCP發送/接收的緩衝大小(單位:字節)。
-p	即postfile,發送POST請求時需要上傳的文件,此外還必須設置-T參數。
-u	即putfile,發送PUT請求時需要上傳的文件,此外還必須設置-T參數。
-T	即content-type,用於設置Content-Type請求頭信息,例如:application/x-www-form-urlencoded,默認值爲text/plain。
-v	即verbosity,指定打印幫助信息的冗餘級別。
-w	以HTML表格形式打印結果。
-i	使用HEAD請求代替GET請求。
-x	插入字符串作爲table標籤的屬性。
-y	插入字符串作爲tr標籤的屬性。
-z	插入字符串作爲td標籤的屬性。

ab的部分參數解釋-2:

-C	添加cookie信息,例如:"Apache=1234"(可以重複該參數選項以添加多個)。
-H	添加任意的請求頭,例如:"Accept-Encoding: gzip",請求頭將會添加在現有的多個請求頭之後(可以重複該參數選項以添加多個)。
-A	添加一個基本的網絡認證信息,用戶名和密碼之間用英文冒號隔開。
-P	添加一個基本的代理認證信息,用戶名和密碼之間用英文冒號隔開。
-X	指定使用的和端口號,例如:"126.10.10.3:88"。
-V	打印版本號並退出。
-k	使用HTTP的KeepAlive特性。
-d	不顯示百分比。
-S	不顯示預估和警告信息。
-g	輸出結果信息到gnuplot格式的文件中。
-e	輸出結果信息到CSV格式的文件中。
-r	指定接收到錯誤信息時不退出程序。
-h	顯示用法信息,其實就是ab -help。
原文鏈接:https://blog.csdn.net/u011415782/article/details/78501799

測試結果的簡單結論

1. 使用--net=host 應該比使用單純的 -p docker0 網絡要好很多. 
2. 進行編譯優化的二進制應該比不編譯優化的二進制要好一些. 但是不是特別明顯.
3. 增加了過多的模塊可能對性能有影響. 最簡化的編譯應該是性能最好的. 
4. 基於3的結論,重新編譯一個最小化編譯的包進行再次驗證. 發現包含的模塊越少,性能越好.
5. 多次進行ab 的壓測與驗證, 結論基本上符合這個規律.
6. 平均數較難取得.本次僅使用一個worker 進行測試驗證. 機器配置較高.
7. 開啓了keepalive 性能會有一定的提升. 所以不管是nginx作爲客戶端還是服務器端建議開啓keepalive
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章