第六部分 編譯優化
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