Nginx 性能優化


Nginx 性能優化

NGINX

當我需要進行性能優化時,說明我們服務器無法滿足日益增長的業務。性能優化是一個比較大的課題,需要從以下幾個方面進行探討

  • 當前系統結構瓶頸
  • 瞭解業務模式
  • 性能與安全

1、當前系統結構瓶頸

首先需要了解的是當前系統瓶頸,用的是什麼,跑的是什麼業務。裡面的服務是什麼樣子,每個服務最大支持多少併發。比如針對nginx而言,我們處理靜態資源效率最高的瓶頸是多大?能支持多少qps訪問請求?怎麼得出系統當前的結構瓶頸?

可以通過查看當前cpu負荷,內存使用率,進程使用率來做簡單判斷。還可以通過操作系統的一些工具來判斷當前系統性能瓶頸,如分析對應的日誌,查看請求數量。也可以通過nginx http_stub_status_module模塊來查看對應的連接數,總握手次數,總請求數。也可以對線上進行壓力測試,來了解當前的系統能性能,併發數,做好性能評估。

2、瞭解業務模式

雖然我們是在做性能優化,但還是要熟悉業務,最終目的都是為業務服務的。我們要了解每一個接口業務類型是什麼樣的業務,比如電子商務搶購模式,這種情況平時流量會很小,但是到了搶購時間,流量一下子就會猛漲。也要了解系統層級結構,每一層在中間層做的是代理還是動靜分離,還是後臺進行直接服務。需要我們對業務接入層和系統層次要有一個梳理

3、性能與安全

性能與安全也是一個需要考慮的因素,往往大家注重性能忽略安全或注重安全又忽略性能。比如說我們在設計防火牆時,如果規則過於全面肯定會對性能方面有影響。如果對性能過於注重在安全方面肯定會留下很大隱患。所以大家要評估好兩者的關係,把握好兩者的孰重孰輕,以及整體的相關性。權衡好對應的點。

4、系統與nginx性能優化

大家對相關的系統瓶頸及現狀有了一定的瞭解之後,就可以根據影響性能方面做一個全體的評估和優化。

  • 網絡(網絡流量、是否有丟包,網絡的穩定性都會影響用戶請求)
  • 系統(系統負載、飽和、內存使用率、系統的穩定性、硬件磁盤是否有損壞)
  • 服務(連接優化、內核性能優化、http服務請求優化都可以在nginx中根據業務來進行設置)
  • 程序(接口性能、處理請求速度、每個程序的執行效率)
  • 數據庫、底層服務

上面列舉出來每一級都會有關聯,也會影響整體性能,這裡主要關注的是nginx服務這一層。

1、文件句柄

在linux/unix操作系統中一切皆文件,我們的設備是文件,文件是文件,文件夾也是文件。當我們用戶每發起一次請求,就會產生一個文件句柄。文件句柄可以簡單的理解為文件句柄就是一個索引。文件句柄就會隨著請求量的增多,進程調用頻繁增加,那麼產生的文件句柄也就會越多。

系統默認對文件句柄是有限制的,不可能會讓一個進程無限制的調用句柄。因為系統資源是有限的,所以我們需要限制每一個服務能夠使用多大的文件句柄。操作系統默認使用的文件句柄是1024個句柄。

2、設置方式
  • 系統全局性修改
  • 用戶局部性修改
  • 進程局部性修改
3、系統全局性修改和用戶局部性修改
<code>[root@server ~]#vim /etc/security/limits.conf/<code>

在文件最下面找到

<code>#*               soft    core            0
#*               hard   rss             10000
#@student       hard   nproc           20
#@faculty       soft   nproc           20
#@faculty       hard   nproc           50
#ftp             hard   nproc           0
#@student       -       maxlogins       4

#root只是針對root這個用戶來限制,soft只是發提醒,操作系統不會強制限制,一般的站點設置為一萬左右就ok了
root soft nofile 65535
root hard nofile 65535
# *代表通配符 所有的用戶
*   soft nofile 25535
*   hard nofile 25535/<code>

可以看到root和*,root代表是root用戶,*代表的是所有用戶,後面的數字就是文件句柄大小。大家可以根據個人業務來進行設置。

4、進程局部性修改
<code>[root@server ~]#vim /etc/nginx/nginx.conf
user nginx;
worker_processes  1;  

error_log /var/log/nginx/error.log warn;
pid       /var/run/nginx.pid;

worker_rlimit_nofile 65535; #進程限制

events {
  worker_connections  1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type application/octet-stream;

  log_format main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for" '
                     '"$args" "$request_uri"';

  access_log /var/log/nginx/access.log main;

  sendfile       on;
   #tcp_nopush     on;

  keepalive_timeout  65;

   #gzip on;

  include /etc/nginx/conf.d/*.conf;
}/<code>

worker_rlimit_nofile 是在進程上面進行限制。

5、cpu的親和配置

cpu的親和能夠使nginx對於不同的work工作進程綁定到不同的cpu上面去。就能夠減少在work間不斷切換cpu,把進程通常不會在處理器之間頻繁遷移,進程遷移的頻率小,來減少性能損耗。nginx 親和配置

查看物理cpu

<code>[root@server ~]#cat /proc/cpuinfo|grep "physical id"|sort |uniq|wc -l/<code>

查看cpu核心數

<code>[root@server ~]#cat /proc/cpuinfo|grep "cpu cores"|uniq/<code>

查看cpu使用率

<code>[root@server ~]#top  回車後按 1/<code>
6、配置worker_processes
<code>[root@server ~]#vim /etc/nginx/nginx.conf/<code>

將剛才查看到自己cpu * cpu核心就是worker_processes

<code>worker_processes 2; #根據自己cpu核心數配置/<code>
7、cpu親和配置

假如小菜的配置是2cpu,每個cpu是8核。配置如下

<code>worker_processes 16;
worker_cpu_affinity 1010101010101010 0101010101010101;/<code>

配置完成後可以通過下面命令查看nginx進程配置在哪個核上

<code>[root@server ~]#ps -eo pid,args,psr |grep [n]ginx/<code>

在nginx 1.9版本之後,就幫我們自動綁定了cpu;

<code>worker_cpu_affinity auto;/<code>

5、nginx通用配置優化

<code>[root@server ~]#vim /etc/nginx/nginx.conf
#將nginx進程設置為普通用戶,為了安全考慮

user nginx;

#當前啟動的worker進程,官方建議是與系統核心數一直
worker_processes 2;
#方式一, 第一個work進程綁定第一個cpu核心,第二個work進程綁定到第二個cpu核心,依次內推 直到弟16個
#wokrer_cpu_affinity 0000000000000000 0000000000000001 0000000000000010 0000000000000100 ... 1000000000000000

#方式二,當 worker_processes 2 時,表明 第一work進程可以綁定第 2 4 6 8 10 12 14 16 核心,那麼第二work進程就綁定 奇數核心
#worker_cpu_affinity 1010101010101010 0101010101010101;

#方式三,就是自動分配綁定
worker_cpu_affinity auto;

#日誌配置成warn
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

#針對 nginx 句柄的文件限制
worker_rlimit_nofile 35535;
#事件模型
events {
   #使用epoll內核模型
  user epoll;
   #每一個進程可以處理多少個連接,如果是多核可以將連接數調高 worker_processes * 1024
  worker_connections 10240;
}

http {
  include       /etc/nginx/mime.types;
  default_type application/octet-stream;

  charset utf-8;  #設置字符集

   #設置日誌輸出格式,根據自己的情況設置

  log_format main  '$http_user_agent' '$remote_addr - $remote_user [$time_local] "$request" '
                     '$status $body_bytes_sent "$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for" '
                     '"$args" "$request_uri"';

  access_log /var/log/nginx/access.log main;

  sendfile       on;   #對靜態資源的處理比較有效
   #tcp_nopush     on;   #如果做靜態資源服務器可以打開
   #tcp_nodeny     on;   #當nginx做動態的服務時可以選擇打開

  keepalive_timeout  65;

   ########
   #Gzip module
  gzip on;    #文件壓縮默認可以打開
  gzip_disable "MSIE [1-6]\\."; #對於有些瀏覽器不能識別壓縮,需要過濾如ie6
  gzip_http_version 1.1;

  include /etc/nginx/conf.d/*.conf;
}/<code>
<code>#查看 核心綁定的nginx work進程
[root@server ~]#ps -eo pid,args,psr | grep [n]ginx/<code>

6、ab接口壓力測試工具

ab是Apache超文本傳輸協議(HTTP)的性能測試工具。其設計意圖是描繪當前所安裝的Apache的執行性能,主要是顯示你安裝的Apache每秒可以處理多少個請求。

<code># 安裝工具
[root@server ~]#yum install httpd-tools

# 使用
[root@server ~]#ab -n 2000 -c 2 http://127.0.0.1/index.html
-n 總的請求數

-c 併發數
-k 是否開啟長連接/<code>
1、參數選項
<code>-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標籤的屬性
-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/<code>
2、內容解釋
<code>Server Software:        nginx/1.10.2 (服務器軟件名稱及版本信息)
Server Hostname:       192.168.1.106(服務器主機名)
Server Port:           80 (服務器端口)
Document Path:         /index1.html. (供測試的URL路徑)
Document Length:       3721 bytes (供測試的URL返回的文檔大小)
Concurrency Level:     1000 (併發數)
Time taken for tests:   2.327 seconds (壓力測試消耗的總時間)
Complete requests:     5000 (的總次數)
Failed requests:       688 (失敗的請求數)
Write errors:           0 (網絡連接寫入錯誤數)
Total transferred:     17402975 bytes (傳輸的總數據量)
HTML transferred:       16275725 bytes (HTML文檔的總數據量)
Requests per second:   2148.98 [#/sec] (mean) (平均每秒的請求數) 這個是非常重要的參數數值,服務器的吞吐量

Time per request:       465.338 [ms] (mean) (所有併發用戶(這裡是1000)都請求一次的平均時間)
Time request:       0.247 [ms] (mean, across all concurrent requests) (單個用戶請求一次的平均時間)
Transfer rate:         7304.41 [Kbytes/sec] received 每秒獲取的數據長度 (傳輸速率,單位:KB/s)
...
Percentage of the requests served within a certain time (ms)
50%   347 ## 50%的請求在347ms內返回
66%   401 ## 60%的請求在401ms內返回
75%   431
80%   516
90%   600
95%   846
98%   1571
99%   1593
100%   1619 (longest request)/<code>
3、示例演示
<code>[root@server ~]#ab -n 50 -c 20 http://walidream.com/sub_module/<code>

輸出內容

<code>Server Software:        nginx/1.14.1
Server Hostname:       walidream.com
Server Port:           80

Document Path:         /sub_module
Document Length:       169 bytes

Concurrency Level:     20
Time taken for tests:   0.005 seconds
Complete requests:     50
Failed requests:       0
Write errors:           0
Non-2xx responses:     50
Total transferred:     14900 bytes
HTML transferred:       8450 bytes
Requests per second:   9746.59 [#/sec] (mean)
Time per request:       2.052 [ms] (mean)
Time per request:       0.103 [ms] (mean, across all concurrent requests)
Transfer rate:         2836.41 [Kbytes/sec] received

Connection Times (ms)
            min mean[+/-sd] median   max

Connect:       0   0   0.1     0       1
Processing:     1   1   0.3     1       2
Waiting:       0   1   0.2     1       1
Total:         1   2   0.3     2       2

Percentage of the requests served within a certain time (ms)
50%     2
66%     2
75%     2
80%     2
90%     2
95%     2
98%     2
99%     2
100%     2 (longest request)/<code>
5、注意事項

● 測試機與被測試機要分開

● 不要對線上的服務器做壓力測試

● 觀察測試工具ab所在機器,以及被測試的前端機的CPU、內存、網絡等都不超過最高限度的75%

6、ab性能指標
1、吞吐率(Requests per second)

服務器併發處理能力的量化描述,單位是reqs/s,指的是在某個併發用戶數下單位時間內處理的請求數。某個併發用戶數下單位時間內能處理的最大請求數,稱之為最大吞吐率。記住:吞吐率是基於併發用戶數的。這句話代表了兩個含義:

<code>● 吞吐率和併發用戶數相關 


● 不同的併發用戶數下,吞吐率一般是不同的/<code>

計算公式:總請求數/處理完成這些請求數所花費的時間,即

<code>Request per second=Complete requests/Time taken for tests/<code>

必須要說明的是,這個數值表示當前機器的整體性能,值越大越好

2、併發連接數(The number of concurrent connections)

併發連接數指的是某個時刻服務器所接受的請求數目,簡單的講,就是一個會話。

3、併發用戶數(Concurrency Level)

要注意區分這個概念和併發連接數之間的區別,一個用戶可能同時會產生多個會話,也即連接數。在HTTP/1.1下,IE7支持兩個併發連接,IE8支持6個併發連接,FireFox3支持4個併發連接,所以相應的,我們的併發用戶數就得除以這個基數。

4.用戶平均請求等待時間(Time per request)

計算公式:處理完成所有請求數所花費的時間/(總請求數/併發用戶數),即:

<code>Time per request=Time taken for tests/(Complete requests/Concurrency Level)/<code>
5.服務器平均請求等待時間(Time per request:across all concurrent requests)

計算公式:處理完成所有請求數所花費的時間/總請求數,即:

<code>Time taken for/testsComplete requests/<code>

可以看到,它是吞吐率的倒數。同時,它也等於用戶平均請求等待時間/併發用戶數,即


<code>Time per request/Concurrency Level/<code>


分享到:


相關文章: