高性能 Nginx+Keepalived 2019版

本文目的

通過(guò)使用 2019年主流的軟件技術(shù)帝牡,配置高可靠高性能的Nginx舰攒。線上運(yùn)行的8核8G的單臺(tái)虛擬機(jī)穩(wěn)定支持 200Mb/s 持續(xù)流量沒(méi)有出現(xiàn)服務(wù)間斷令哟、CPU飆高等情況。
本文不涉及到重新編譯內(nèi)核唠摹、不依賴(lài)特定硬件設(shè)備绵估、不依賴(lài)特定網(wǎng)絡(luò)架構(gòu)炎疆、不需要使用物理機(jī)。

適用范圍

本文不求標(biāo)新立異国裳,使用的是通用而有效的優(yōu)化方法形入,適用于主流的操作系統(tǒng):

  • CentOS 6.7+ (已經(jīng)測(cè)試和驗(yàn)證)
  • CentOS 7.0+ (已經(jīng)測(cè)試和驗(yàn)證)
  • Ubuntu 14.04 (支持,未測(cè)試)
  • Ubuntu 16.04 (已經(jīng)測(cè)試和驗(yàn)證)
  • Ubuntu 18.04 (已經(jīng)測(cè)試和驗(yàn)證)
  • Debian 8, 9, 10 (支持缝左,未測(cè)試)

Nginx + Keepalived 一句話 介紹

常見(jiàn)的組合亿遂,常用來(lái)實(shí)現(xiàn)高可靠的4層和7層的代理服務(wù)器。

Nginx 版本推薦

  • Tengine 3.x
    基于 nginx 1.17 , 阿里出品渺杉,高性能蛇数,內(nèi)置官方的Stream模塊可直接支持TCP代理。
    目前缺少 stream 模塊的 upstream 的健康檢測(cè)功能是越。

  • OpenResty 最新版
    Nginx 的 "集成打包版"耳舅,基于較新的 Nginx ,luajit 生態(tài)的擴(kuò)展版倚评。
    推薦安裝額外的插件 vts ngx_healthcheck_module

  • Nginx 最新版
    官方開(kāi)源版本浦徊。

以上三個(gè)版本各有千秋,目前我們線上用的是 Tengine 天梧。

優(yōu)化因素(風(fēng)險(xiǎn)由低到高)

  • 操作系統(tǒng)
  • ulimit 參數(shù)
  • ip_vs 參數(shù)
  • 網(wǎng)卡參數(shù)
  • irq 軟中斷
  • CPU 親緣
  • nginx 參數(shù)優(yōu)化
  • 內(nèi)核啟動(dòng)參數(shù)
  • 內(nèi)核sysctl參數(shù)
  • 內(nèi)核版本

操作系統(tǒng)

推薦使用 Ubuntu 18.04盔性、16.04 或是 CentOS 7.7+ 操作系統(tǒng)。
如果現(xiàn)在還是要堅(jiān)持使用CentOS 6呢岗,總有一天也會(huì)因?yàn)閮?nèi)核版本老冕香、軟件版本老蛹尝、不支持Docker、不支持 Systemd 等原因而主動(dòng)或被動(dòng)升級(jí)暂筝。再升級(jí)早享受箩言。
irqbalance 服務(wù)可以自動(dòng)綁定 cpu 負(fù)載軟中斷硬贯,需要內(nèi)核高于 2.4 的版本焕襟。

ulimit 參數(shù)

推薦設(shè)置為 1048576

ip_vs 參數(shù)

很多文章提到,通過(guò)修改內(nèi)核參數(shù)配置饭豹,重新編譯內(nèi)核實(shí)現(xiàn) ip_vs 模塊的參數(shù)優(yōu)化鸵赖。事實(shí)上較新的系統(tǒng)(包括 CentOS 6.7 及以上)完全沒(méi)必要重新編譯內(nèi)核,僅需要配置加載參數(shù) options ip_vs conn_tab_bits=20 即可實(shí)現(xiàn)拄衰。

網(wǎng)卡參數(shù)

關(guān)閉 gso gro tso

irq 軟中斷

開(kāi)啟 irqbalance 服務(wù)能顯著減低軟中斷 ksoftirqd 引起的cpu負(fù)載它褪。(內(nèi)核須高于2.4版本)
nginx 流量高于 300Mb/s 時(shí),如果發(fā)現(xiàn) ksoftirqd 的 cpu 負(fù)載很高翘悉, 而且網(wǎng)絡(luò)延遲加大茫打,可以檢查 irqbalance 服務(wù)是否開(kāi)啟。

CPU 親緣

nginx 配置中妖混,進(jìn)行如下設(shè)置: worker_processes auto; worker_cpu_affinity auto;

nginx 參數(shù)優(yōu)化

http 參數(shù)各種常用設(shè)定老赤。

內(nèi)核啟動(dòng)參數(shù)

主要是 nohz=off transparent_hugepage=never numa=off

內(nèi)核sysctl參數(shù)


## NAT,GATEWAY:1
## net.ipv4.ip_forward = 0
## net.ipv4.ip_forward = 1
## NAT,GATEWAY:0 
## net.ipv4.tcp_tw_recycle = 0
## net.ipv4.tcp_tw_recycle = 1

fs.aio-max-nr = 16777216
fs.file-max   = 16777216
fs.nr_open    = 16777216
kernel.core_pipe_limit = 0
kernel.core_uses_pid = 1
kernel.exec-shield = 1
kernel.randomize_va_space = 1
kernel.msgmax = 65536
kernel.msgmnb = 65536
kernel.sem = 250 32000 100 128
kernel.shmall = 4294967296
kernel.shmmax = 68719476736
kernel.sysrq = 0
kernel.pid_max = 4194303
net.bridge.bridge-nf-call-arptables = 0
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.core.netdev_max_backlog = 524288
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.somaxconn=65535
net.core.wmem_default = 8388608
net.core.wmem_max = 16777216
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.all.arp_announce = 2
net.ipv4.conf.all.arp_notify = 1
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 30
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_max_tw_buckets = 16777216
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_no_metrics_save = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_sack = 1
net.ipv4.tcp_slow_start_after_idle = 1
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 2
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_wmem = 4096 65536 4194304
net.nf_conntrack_max = 25000000
net.netfilter.nf_conntrack_max=25000000
net.netfilter.nf_conntrack_generic_timeout = 120
net.netfilter.nf_conntrack_tcp_timeout_close = 10
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_established = 180
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_last_ack = 30
net.netfilter.nf_conntrack_tcp_timeout_max_retrans = 300
net.netfilter.nf_conntrack_tcp_timeout_syn_recv = 60
net.netfilter.nf_conntrack_tcp_timeout_syn_sent = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_unacknowledged = 300
vm.overcommit_memory=1
vm.swappiness = 0
###vm.min_free_kbytes=65536
net.ipv4.tcp_fastopen = 3
net.ipv4.ip_local_port_range = 10000 65535
net.ipv4.ip_local_reserved_ports =10050,11215,18000-18099,27017,60000-60099
kernel.printk_ratelimit = 30
kernel.printk_ratelimit_burst = 200
vm.max_map_count=262144
# recommended for hosts with jumbo frames enabled
#net.ipv4.tcp_mtu_probing=1
fs.inotify.max_user_watches = 30000000
#bbr
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

內(nèi)核版本

內(nèi)核的版本對(duì)性能和功能有顯著的影響,4.9 版本加入了 BBR 功能制市,對(duì)性能有顯著的提升抬旺。
** 升級(jí)內(nèi)核版本風(fēng)險(xiǎn)較高,操作需要慎重祥楣。**
CentOS 7 內(nèi)核版本為 3.10开财,可以使用 centos-release-xen 倉(cāng)庫(kù),安裝 4.9 的內(nèi)核误褪。

Ubuntu 16.04.3 HWE 內(nèi)核版本的為 4.13责鳍。 如果你的內(nèi)核還是默認(rèn)的4.4.0,可以安裝 linux-image-generic-hwe-16.04 升級(jí)到 4.13 版本兽间。

Ubuntu 18.04 使用 4.15 版本的內(nèi)核历葛。
內(nèi)核 4.9 和 4.14 為 LTS 版本,維護(hù)期一般至少為 2至 3年渡八。
Ubuntu LTS 支持時(shí)間一般為5年啃洋,大版本之間可以平滑升級(jí)。

附升級(jí)內(nèi)核版本的操作

Ubuntu :

apt-get update
apt-get dist-upgrade -y

# 安裝制定版本的內(nèi)核
apt-get install linux-image-4.13.0-32-generic

# 自動(dòng)選擇最新穩(wěn)定的內(nèi)核
apt-get install -y linux-image-generic-hwe

CentOS 7 方法一 :


yum install -y centos-release-xen && yum install -y kernel  

CentOS 7 方法二:
安裝 ELRepo屎鳍,可以升級(jí) kernel 版本宏娄,滾動(dòng)升級(jí)最新的版本,后續(xù)如果內(nèi)核安全補(bǔ)丁升級(jí)逮壁,使用穩(wěn)定的版本存在安全隱患孵坚。

使用新內(nèi)核

test -f /usr/sbin/update-grub && sudo update-grub
test -f /usr/sbin/grub2-mkconfig && sudo grub2-mkconfig -o /boot/grub2/grub.cfg

安全相關(guān)

1.1 配置跳轉(zhuǎn)使用 $request_uri 獲取用戶的請(qǐng)求路徑,而不是 $uri$document_uri

location / {
    return 302 https://$host$request_uri;
}

1.2 location 和 alias 配置的時(shí)候,結(jié)尾有沒(méi)有斜杠保持一致卖宠。

location /files/ {
    alias /home/;
}

1.3 注意子模塊如果設(shè)置 add_header巍杈,會(huì)覆蓋上級(jí)模塊的全部add_header設(shè)置的信息

自動(dòng)重試

自動(dòng)重試機(jī)制雖然能盡量保障請(qǐng)求盡量得到執(zhí)行。不過(guò)在并發(fā)壓力大的情況下扛伍,后端服務(wù)抗不住壓力筷畦,再加上自動(dòng)重試,會(huì)造成系統(tǒng)負(fù)載更高刺洒,從而引起雪崩效應(yīng)鳖宾。建議關(guān)閉自動(dòng)重試機(jī)制。

  • 關(guān)閉自動(dòng)重試
    proxy_next_upstream off;

  • 允許重試一次
    proxy_next_upstream_tries 1;

cms系統(tǒng)大文章保存逆航,文件上傳鼎文,報(bào)錯(cuò) 502 或是 408

http 字段,增加 __ client_body_buffer_size 8192k; __ 如果沒(méi)有解決因俐,可以再適當(dāng)增加這個(gè)值拇惋。

瀏覽器報(bào)錯(cuò) ERR_INCOMPLETE_CHUNKED_ENCODING

原因:后端服務(wù)(比如 netty )只支持 http 1.1,nginx 默認(rèn)使用 http 1.0 去請(qǐng)求后端服務(wù)抹剩。
解決辦法撑帖,location 增加如下配置,讓 nginx 使用 http 1.1 協(xié)議去請(qǐng)求后端服務(wù)吧兔。
另外磷仰,啟用這兩個(gè)參數(shù)可以使用 keepalived 等功能,減少對(duì)后端的 tcp 并發(fā)連接數(shù)境蔼,我們線上已經(jīng)默認(rèn)啟用這兩個(gè)參數(shù)灶平。

proxy_http_version 1.1;
proxy_set_header Connection "";

Chacha20-Poly1305 + X25519 ,需要 openssl 1.1.0 + nginx-1.12.1+/1.13.3+

ssl_ciphers EECDH+AES:EECDH+CHACHA20:!SHA;
ssl_prefer_server_ciphers on;
ssl_ecdh_curve X25519;

反向代理下載報(bào)錯(cuò) transfer closed with bytes remaining to read

proxy_buffering off;

日志

不同用途的日志格式保持一致箍土,如果不需要打印某些變量逢享,就用 - 來(lái)代替。
例如吴藻,main 格式里面不打印 $request_body瞒爬, spider 格式不打印 $upstream_addr.


log_format  main  '[$time_iso8601] $http_x_forwarded_for $remote_addr '
    '$request_method $status $server_protocol '
    '$scheme://$http_host$request_uri '
    '"$http_referer" "$http_user_agent" - $request_time '  
    '$body_bytes_sent $upstream_addr $upstream_response_time ';

log_format  debug  '[$time_iso8601] $http_x_forwarded_for $remote_addr '
    '$request_method $status $server_protocol '
    '$scheme://$http_host$request_uri '
    '"$http_referer" "$http_user_agent" $request_body $request_time ' 
    '$body_bytes_sent $upstream_addr $upstream_response_time ';

log_format  spider '[$time_iso8601] $http_x_forwarded_for $remote_addr '
    '$request_method $status $server_protocol '
    '$scheme://$http_host$request_uri '
    '"$http_referer" "$http_user_agent" $request_body $request_time ' 
    '$body_bytes_sent - $upstream_response_time ';

decode $request_body

python2>
line = '{\x22id\x22:\x22user id\x22}'
line.decode('unicode_escape')
>> u'{"id":"user id"}'
python3>
line='{\x22....}'
bytes(line, 'utf-8').decode('unicode_escape')
ruby irb>
require 'yaml'
line = '{\x22id\x22:\x22user id\x22}'
YAML.load(%Q(---\n"#{line}"\n))
=> "{\"id\":\"user id\"}"

參考來(lái)源:
https://www.leavesongs.com/PENETRATION/nginx-insecure-configuration.html
https://stackoverflow.com/questions/30361486/nginx-logging-request-body-as-hexadecimal

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市沟堡,隨后出現(xiàn)的幾起案子侧但,更是在濱河造成了極大的恐慌,老刑警劉巖航罗,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件禀横,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡粥血,警方通過(guò)查閱死者的電腦和手機(jī)柏锄,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)酿箭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人趾娃,你說(shuō)我怎么就攤上這事缭嫡。” “怎么了抬闷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵妇蛀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我饶氏,道長(zhǎng)讥耗,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任疹启,我火速辦了婚禮,結(jié)果婚禮上蔼卡,老公的妹妹穿的比我還像新娘喊崖。我一直安慰自己,他們只是感情好雇逞,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布荤懂。 她就那樣靜靜地躺著,像睡著了一般塘砸。 火紅的嫁衣襯著肌膚如雪节仿。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天掉蔬,我揣著相機(jī)與錄音廊宪,去河邊找鬼。 笑死女轿,一個(gè)胖子當(dāng)著我的面吹牛箭启,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蛉迹,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼傅寡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了北救?” 一聲冷哼從身側(cè)響起荐操,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎珍策,沒(méi)想到半個(gè)月后托启,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膛壹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年驾中,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了唉堪。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡肩民,死狀恐怖唠亚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情持痰,我是刑警寧澤灶搜,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站工窍,受9級(jí)特大地震影響割卖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜患雏,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一鹏溯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧淹仑,春花似錦丙挽、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至吓肋,卻和暖如春凳怨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背是鬼。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工肤舞, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屑咳。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓萨赁,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親兆龙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子杖爽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 第一章 Nginx簡(jiǎn)介 Nginx是什么 沒(méi)有聽(tīng)過(guò)Nginx?那么一定聽(tīng)過(guò)它的“同行”Apache吧紫皇!Ngi...
    JokerW閱讀 32,642評(píng)論 24 1,002
  • 1. Nginx的模塊與工作原理 Nginx由內(nèi)核和模塊組成慰安,其中,內(nèi)核的設(shè)計(jì)非常微小和簡(jiǎn)潔聪铺,完成的工作也非常簡(jiǎn)單...
    rosekissyou閱讀 10,196評(píng)論 5 124
  • Page 1:nginx 服務(wù)器安裝及配置文件詳解 CentOS 6.2 x86_64 安裝 nginx 1.1 ...
    xiaojianxu閱讀 8,527評(píng)論 1 41
  • Nginx入門(mén)-在Linux上安裝Nginx 介紹 簡(jiǎn)而言之化焕,Nginx(發(fā)音為“engine x”)是一個(gè)小型、...
    呵呵噠1991閱讀 699評(píng)論 0 1
  • 介紹 簡(jiǎn)而言之铃剔,Nginx(發(fā)音為“engine x”)是一個(gè)小型撒桨、功能強(qiáng)大并且可擴(kuò)展的 web/proxy 服務(wù)...
    重度恐高癥閱讀 8,531評(píng)論 1 17