總結高並發下Nginx性能如何優化

我們終將在,沒有黑暗的地方相見。 ~喬治《1984》

Nginx同Apache一樣都是一種WEB服務器。基於REST架構風格,以統一資源描述符(UniformResources ldentifier)URl或者統一資源定位符(Uniform Resources Locator)URL作為溝通依據,通過HTTP協議提供各種網絡服務。

Apache的發展時期很長,而且是毫無爭議的世界第一大服務器。它有著很多優點:穩定、開源、跨平臺等等。它出現的時間太長瞭,它興起的年代,互聯網產業遠遠比不上現在。所以它被設計為一個重量級的。它不支持高並發的服務器。在Apache上運行數以萬計的並發訪問,會導致服務器消耗大量內存sz操作系統對其進行進程或線程間的切換也消耗瞭大量的CPU資源,導致HTTP請求的平均響應速度降低。

這些都決定瞭Apache不可能成為高性能WEB服務器,輕量級高並發服務器Nginx就應運而生瞭。

特點

是一個高性能的HTTP和反向代理web服務器,輕量級提供瞭IMAP/POP3/SMTP服務發佈於2004年10月4日(第一個公開版本0.1.0 )Nginx的1.4.0穩定版已經於2013年4月24日發佈C語言編寫Nginx是一個跨平臺服務器Nginx有自己的函數庫,並且除瞭zlib、PCRE和OpenSSL之外,標準模塊隻使用系統C庫函數。

優勢

占有內存少(在3W並發連接中,開啟的10個nginx進程消耗內存大約150M)高並發能力強(官方測試能夠支撐5W並發連接,在實際生產環境中能到2-3W並發連接數)簡單(配置文件通俗易懂)價格(免費、開源)支持Rewriter重寫(能夠根據域名、URL的不同,將HTTP請:求分到不同的後端服務器群組)內置健康檢查(如果nginx後端有幾個服務宕機瞭,不會影響前端訪問,能自動檢測服務狀態)節省帶寬(支持GZIP壓縮,可以添加瀏覽器本地緩存的Header頭)
穩定性高,反向代理,很少宕機中國大陸使用nginx網站用戶有:百度、京東、新浪、網易、騰訊、淘寶等

功能:web服務器、輕量級;負載、均衡;緩存;高並發

應用場景:代理服務器;IP負載、靜態負載;動靜分離;限流、健康監控

安裝和命令

安裝:

sudo apt-get install nginx

查看版本

nginx -v                  
nginx version: nginx/1.18.0 (Ubuntu)

基本命令

# nginx的訪問頁面(welcome to nginx)具體所在位置
vi /usr/share/nginx/html/index.html
# 訪問IP
curl 192.168.100.111
# 關閉nginx進程
nginx -s stop
# 啟動nginx進程
/usr/sbin/nginx          # yum安裝的nginx也可以使用         servic nginx start
# 檢查配置文件是否有誤
nginx –t
# 重新加載配置文件
nginx –s reload
# 查看日志
tail -f filename #顯示文件默認10行,刷新顯示
# 例:tail -f /var/log/lvs-agent.log          tail -f /etc/nginx/nginx.conf
# 查看文件後幾行
tail -n 行數 文件名 例: tail -n 100 /var/log/aa.log
# 刪除網卡ip
ip addr del 192.168.11.5/32 dev lo (lo eth1 eth2)
# lvs清空所有集群服務
ipvsadm –C
# 獲取eth0網卡上的所掛的ip值
ip a|grep eth0|grep inet|awk ‘{print $2}'|cut -d “/” -f1
# 驗證該ip或者網址是否通 可用返回200
curl -I -m 10 -o /dev/null -s -w %{http_code} 10.110.26.10:8080
# 後臺啟動jar包
nohup java -jar /usr/sbin/項目名.jar >>/var/log/項目名.log 2>&1 &
# 查看上一個命令是否執行成功 返回0執行成功 其他不成
echo $?
# 查看nginx進程是否啟動。此命令用在代碼判斷nginx進程是否啟動,如果隻用ps aux | grep nginx 即使沒有啟動也會用內容返回,影響判斷
ps aux | grep nginx | greo –v grep

配置文件

nginx.conf

# nginx.conf
# 全局配置區
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
# 網絡事件配置區
events {
	worker_connections 768;
	# multi_accept on;
}
# HTTP模塊
http {
	##
	# HTTP 全局設置
	##
	sendfile on;
	tcp_nopush on;
	tcp_nodelay on;
	keepalive_timeout 65;
	types_hash_max_size 2048;
	# server_tokens off;
	# server_names_hash_bucket_size 64;
	# server_name_in_redirect off;
	include /etc/nginx/mime.types;
	default_type application/octet-stream;
	##
	# SSL 設置
	##
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
	ssl_prefer_server_ciphers on;
	##
	# 日志設置
	##
	access_log /var/log/nginx/access.log;
	error_log /var/log/nginx/error.log;
	##
	# 資源壓縮設置
	##
	gzip on;	# 默認開啟
	# gzip_vary on;
	# gzip_proxied any;
	# gzip_comp_level 6;
	# gzip_buffers 16 8k;
	# gzip_http_version 1.1;
	# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
	##
	# 虛擬主機配置
	##
	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

/etc/nginx/sites-enabled/*

server {	# 虛擬主機配置
	listen 80 default_server;	# 監聽端口
	listen [::]:80 default_server;
	# SSL 配置
	#
	# listen 443 ssl default_server;
	# listen [::]:443 ssl default_server;
	#
	# Note: You should disable gzip for SSL traffic.
	# See: https://bugs.debian.org/773332
	#
	# Read up on ssl_ciphers to ensure a secure configuration.
	# See: https://bugs.debian.org/765782
	#
	# Self signed certs generated by the ssl-cert package
	# Don't use them in a production server!
	#
	# include snippets/snakeoil.conf;	
	# 數據緩存位置
	root /var/www/html;
	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;	
	# 域名,可以有多個
	server_name _;	
	# 對/進行反向代理
	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		# uwsgi_pass 127.0.0.1:8000;
		# include /etc/nginx/uwsgi_params;
		try_files $uri $uri/ =404;
	}
	# pass PHP scripts to FastCGI server
	#
	#location ~ \.php$ {
	#	include snippets/fastcgi-php.conf;
	#
	#	# With php-fpm (or other unix sockets):
	#	fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
	#	# With php-cgi (or other tcp sockets):
	#	fastcgi_pass 127.0.0.1:9000;
	#}
	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	#location ~ /\.ht {
	#	deny all;
	#}
}

代理模式和配置反向代理

正向代理(forward proxy) :

是一個位於客戶端(用戶A)和原始服務器(origin server)(目標服務器)之間的服務器(代理服務器),為瞭從原始服務器取得內容,客戶端向代理服務器發送一個請求並指定目標(原始服務器),然後代理服務器向原始服務器轉交請求並將獲得的內容返回給客戶端。客戶端必須要進行一些特別的配置才能使用正向代理。一般情況下,如果沒有特別說明,代理技術默認是指正向代理技術。

相當於是一個職業中介,且客戶端和實際服務器不能溝通,客戶端知道他是中介

反向代理(reverse proxy)︰

和正向代理正好相反,對於客戶端而言它就像是原始服務器,並且客戶端不需要進行任何特別的設置。客戶端向反向代理的命名空間(name-space)中的內容發送普通請求,接著反向代理將判斷向何處(原始服務器)轉交請求,並將獲得的內容返回給客戶端,就像這些內容原本就是它自己的一樣。

相當於是一個買房和賣房的人,買房的時候相對於賣房的是一個買房的,賣房的時候相對於買房的是一個賣房的。
客戶端不知道他是一個代理服務器,服務器也認為他隻是客戶端而不是代理服務器

透明代理∶

透明代理的意思是客戶端根本不需要知道有代理服務器的存在,它改編你的requestfields(報文),並會傳送真實IP。註意,加密的透明代理則是屬於匿名代理,意思是不用設置使用代理瞭。透明代理實踐的例子就是時下很多公司使用的行為管理軟件

在這裡插入圖片描述

# 反向代理默認是關閉的
# upstream localhost是第三方模塊,均衡
upstream localhost {
	# 實際服務器
	server 192.168.136.133:8081;
	server 192.168.136.133:8081;
	server 192.168.136.133:8081;
} 
# 負載
server {
	listen 80	# 代理服務器的端口
	server_name localhost;
	location / {
		proxy_pass http://localhost;	# 將請求發送給其中一臺實際服務器
	}
}

負載均衡方法:

輪詢法(默認)

加權輪詢法(權重)

Fair

url_hash

源地址哈希法

最小連接法(least_conn)

動靜分離

Nginx動靜分離簡單來說就是把動態跟靜態請求分開,不能理解成隻是單純的把動態頁面和靜態頁面物理分離

嚴格意義上說應該是動態請求跟靜態請求分開,可以理解成使用Nginx處理靜態頁面,Tomcat處理動態頁面

動靜分離從目前實現角度來講大致分為兩種:

  • 一種是純粹把靜態文件獨立成單獨的域名,放在獨立的服務器上,也是目前主流推崇的方案
  • 一種是動態跟靜態文件混合在一起發佈,通過nginx來分開

mkdir static # 存放靜態文件

server {	# 虛擬主機配置
	listen 80 default_server;	# 監聽端口
	listen [::]:80 default_server;
	
	# 數據緩存位置
	root /var/www/html;

	# Add index.php to the list if you are using PHP
	index index.html index.htm index.nginx-debian.html;
	
	# 域名,可以有多個
	server_name _;
	
	# 對/進行反向代理
	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		# uwsgi_pass 127.0.0.1:8000;
		# include /etc/nginx/uwsgi_params;
		try_files $uri $uri/ =404;
	}
	# 如果是這些文件後綴就去這裡面找
	location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css) $ {
		root /static;
		expires 30d;	# 緩存有效期
	}
}

日志管理

日志格式

日志生成的到Nginx根目錄logs/access.log文件,默認使用“main”日志格式,也可以自定義格式默認“main”日志格式

og_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
$remote_addr:客戶端的ip地址(代理服務器,顯示代理服務ip)
$remote_user:用於記錄遠程客戶端的用戶名稱(一般為“-”)
$time_local:用於記錄訪問時間和時區
$request:用於記錄請求的url以及請求方法
$status:響應狀態碼,例如:200成功、404頁面找不到等。
$body_bytes_sent:給客戶端發送的文件主體內容字節數

日志切割

nginx的日志文件沒有rotate功能

編寫每天生成一個日志,我們可以寫一個nginx日志切割腳本來自動切割日志文件

  • 第一步就是重命名日志文件 (不用擔心重命名後nginx找不到日志文件而丟失日志。在你未重新打開原名字的日志文件前,nginx還是會向你重命名的文件寫日志,Linux是靠文件描述符而不是文件名定位文件 )
  • 第二步向nginx主進程發送USR1信號
    nginx主進程接到信號後會從配置文件中讀取日志文件名稱
    重新打開日志文件 (以配置文件中的日志名稱命名) ,並以工作進程的用戶作為日志文件的所有者
    重新打開日志文件後,nginx主進程會關閉重名的日志文件並通知
    工作進程使用新打開的日志文件工作進程立刻打開新的日志文件並關閉重名名的日志文件,然後你就可以處理舊的日志文件瞭。[或者重啟nginx服務]

nginx日志按每分鐘自動切割腳本如下 :

新建shell腳本

高並發架構分析

什麼是高並發?

高並發(High Concurrency)是互聯網分佈式系統架構設計中必須考慮的因素之一,它通常是指,通過設計保證系統能夠同時並行處理很多請求。

高並發相關常用的一些指標有響應時間(Response Time),吞吐量(Throughput),每秒查詢率QPS (Query Per Second),並發用戶數等。

  • 響應時間:系統對請求做出響應的時間
  • 吞吐量:單位時間內處理的請求數量。
  • QPS:每秒響應請求數

如何提升系統的並發能力?

互聯網分佈式架構設計,提高系統並發能力的方式,方法論上主要有兩種:垂直擴展(ScaleUp)與水平擴展(Scale Out)。

垂直擴展:提升單機處理能力。垂直擴展的方式又有兩種。

  • 增強單機硬件性能
  • 提升單機架構性能

在互聯網業務發展非常迅猛的早期,如果預算不是問題,強烈建議使用“增強單機硬件性能”的方式提升系統並發能力,因為這個階段,公司的戰略往往是發展業務搶時間,而“增強單機硬件性能”往往是最快的方法。

不管是提升單機硬件性能,還是提升單機架構性能,都有一個致命的不足:單機性能總是有極限的。所以互聯網分佈式架構設計高並發終極解決方案還是水平擴展。

水平擴展:隻要增加服務器數量,就能線性擴充系統性能。

服務器都有極限

三種方式實現

limit_conn_zone(限制連接流)

limit_req_zone(限制請求流)

ngx_http_upstream_module(後臺服務限制)

此處插上一個小工具:限制測試工具下載

yum install http-tools -y
key 含義
Document Path 測試的頁面
Document Length 頁面的大小
Concurrency Level 並發數量、並發用戶數
Time taken for tests 測試耗費總時間
Complete requests 請求總量、並發連接數
Failed requests 請求失敗的數量
Write errors 錯誤數量
Requests per second 每秒鐘的請求量吞吐率
Time per request 每次請求需要時間響應時間

限制連接流

http {
	# binary_remote_addr:IP
	# zone=one:10m;申請一塊10M的空間存放連接的IP
	limit_conn_zone $binary_remote_addr zone=one:10m;
	
	server {
		# zone區域中每次放出10個連接nginx處理
		limit_conn one 10;
	}
}

限制請求流(限速)

http {
	# rate意思是每個連接每秒能發一個連接
	limit_req_zone $binary_remote_addr zone=req_one:10m rate=1r/s;
	
	server {
		# brust:令牌,每次新增一個,120個發完後會報錯503
		limit_req zone=req_one brust=120;
	}
}

後臺服務限制

該模塊是提供瞭我們需要的後端限流功能的

該模塊有一個參數: max_conns可以對服務端進行限流,可惜在商業版nginx中才能使用

在nginx1.11.5版本以後,官方已經將該參數從商業版中脫離出來瞭,也就是說隻要我們將生產上廣泛使用的nginx1.9.12版本和1.10版本升級即可使用

server {
	# max_conns最大接收服務數量
	server 127.0.0.1:8080 max_conns=100;
}

安全配置

版本安全

http {
	server_tokens off;
}

IP安全

http {
	location / {
		allow 127.0.0.1;	# 白名單
		deny all;	# 黑名單
	}
}

文件安全

http {
	location /logs{
		autoindex on;	# 展示目錄
		root /static;
	}
	location ^/logs~*\.(log|txt)$ {
		add_header Content_Type text/plain;
		root /static;
	}
}

連接安全

http {
	# SSL settings
}

Nginx優化

調整Nginx的主配置文件,增加並發量

worker_processes 2;# 調整與CPU一致
events {
	# 每個worker最大並發數量
	worker_connection 65535;
}

Nginx長連接:HTTP1.1之後,HTTP協議支持持久連接,也就是長連接,優點在於在一個TCP連接上可以傳送多個HTTP請求和響應,

nginx長連接短連接,可以增強服務器的容災能力

減少瞭建立和關閉連接的消耗和延遲。如果我們使用瞭nginx去作為反向代理或者負載均衡,從客戶端過來的長連接請求就會被轉換成短連接發送給服務器端,為瞭支持長連接,我們需要在nginx服務器上做一些配置

使用nginx時,想要做到長連接,我們必須做到以下兩點:

  • 從client到nginx是長連接(events)
  • 從nginx到server是長連接(http)

對於客戶端而言,nginx其實扮演著server的角色,反之,之於server,nginx就是一個client

events {
	# keepalive超時時間,默認是60s,切記這個參數也不能設置過大!否則會導致許多無效的http連接占據著nginx的連接數,終nginx崩潰!
	keepalive_timeout 60;
}
http {
	keepalive_timeout 60;
}

Nginx壓縮

gzip壓縮作用:將響應報文發送至客戶端之前可以啟用壓縮功能,這能夠有效地節約帶寬,並提高響應至客戶端的速度,壓縮會消耗nginx的cpu性能。

gzip壓縮可以配置http,server和location模塊下

http {
    #gzip模塊設置
    #開啟壓縮
    gzip on;
    # 設置允許壓縮的頁面最小字節數,頁面字節數從header頭得content-length中進行獲取。
    默認值是0,不管頁面多大都壓縮。建議設置成大於2k的字節數,小於2k可能會越壓越大。
    gzip_min_length 2k;
    # 設置系統獲取幾個單位的緩存用於存儲gzip的壓縮結果數據流。 例如 4 4k 代表以4k為單
    位,按照原始數據大小以4k為單位的4倍申請內存。 4 8k 代表以8k為單位,按照原始數據大小以8k
    為單位的4倍申請內存。
    # 如果沒有設置,默認值是申請跟原始數據相同大小的內存空間去存儲gzip壓縮結果。
    gzip_buffers 4 16k;
    #壓縮級別,1-10,數字越大壓縮的越好,也越占用CPU時間
    gzip_comp_level 5;
    # 默認值: gzip_types text/html (默認不對js/css文件進行壓縮)
    # 壓縮類型,匹配MIME類型進行壓縮
    # 不能用通配符 text/*
    # (無論是否指定)text/html默認已經壓縮
    # 設置哪壓縮種文本文件可參考 conf/mime.types
    gzip_types text/plain application/xjavascript text/css application/xml;
    # 值為1.0和1.1 代表是否壓縮http協議1.0,選擇1.0則1.0和1.1都可以壓縮
    gzip_http_version 1.0
    # IE6及以下禁止壓縮
    gzip_disable "MSIE [1-6]\.";
    # 默認值:off
    # Nginx作為反向代理的時候啟用,開啟或者關閉後端服務器返回的結果,匹配的前提是後端服
    務器必須要返回包含"Via"的 header頭。
    # off - 關閉所有的代理結果數據的壓縮
    # expired - 啟用壓縮,如果header頭中包含 "Expires" 頭信息
    # no-cache - 啟用壓縮,如果header頭中包含 "Cache-Control:no-cache" 頭信息
    # no-store - 啟用壓縮,如果header頭中包含 "Cache-Control:no-store" 頭信息
    # private - 啟用壓縮,如果header頭中包含 "Cache-Control:private" 頭信息
    # no_last_modified - 啟用壓縮,如果header頭中不包含 "Last-Modified" 頭信息
    # no_etag - 啟用壓縮 ,如果header頭中不包含 "ETag" 頭信息
    # auth - 啟用壓縮 , 如果header頭中包含 "Authorization" 頭信息
    # any - 無條件啟用壓縮
        gzip_proxied expired no-cache no-store private auth;
    # 給CDN和代理服務器使用,針對相同url,可以根據頭信息返回壓縮和非壓縮副本
    gzip_vary on
}

狀態監控

server {
	location /NginxStatus {
		stub_status on;
		access_log off;
	}
}

插件安裝

./configure --prefix=... --with-http_stub_status _module

以上就是總結高並發下Nginx性能如何優化的詳細內容,更多關於高並發下Nginx性能優化的資料請關註WalkonNet其它相關文章!

推薦閱讀: