一、redis搭建哨兵原理和集群實現(xiàn)
1、redis哨兵模式
1.1搭建哨兵的原理
sentinel的中文含義是哨兵、守衛(wèi)。也就是說既然主從模式中,當master節(jié)點掛了以后,slave節(jié)點不能主動選舉一個master節(jié)點出來,那么我就安排一個或多個sentinel來做這件事,當sentinel發(fā)現(xiàn)master節(jié)點掛了以后,sentinel就會從slave中重新選舉一個master。
對哨兵模式的理解
①sentinel模式是建立在主從模式的基礎(chǔ)上,如果只有一個Redis節(jié)點,sentinel就沒有任何意義。
②當master節(jié)點掛了以后,sentinel會在slave中選擇一個做為master,并修改它們的配置文件,其他slave的配置文件也會被修改,比如slaveof屬性會指向新的master。
③當master節(jié)點重新啟動后,它將不再是master,而是作為slave接收新的master節(jié)點的同步數(shù)據(jù)
④sentinel因為也是一個進程有掛掉的可能,所以sentinel也會啟動多個形成一個sentinel集群。
⑤當主從模式配置密碼時,sentinel也會同步將配置信息修改到配置文件中,不需要擔心。
⑥一個sentinel或sentinel集群可以管理多個主從Redis。
⑦sentinel最好不要和Redis部署在同一臺機器,不然Redis的服務(wù)器掛了以后,sentinel也掛了。
⑧sentinel監(jiān)控的Redis集群都會定義一個master名字,這個名字代表Redis集群的master Redis。
當使用sentinel模式的時候,客戶端就不要直接連接Redis,而是連接sentinel的ip和port,由sentinel來提供具體的可提供服務(wù)的Redis實現(xiàn),這樣當master節(jié)點掛掉以后,sentinel就會感知并將新的master節(jié)點提供給使用者。
Sentinel本身也支持集群,只使用單個sentinel進程來監(jiān)控redis集群是不可靠的,當sentinel進程宕掉后,sentinel本身也有單點問題。所以有必要將sentinel集群,這樣有幾個好處:
- 如果只有一個sentinel進程,如果這個進程運行出錯,或者是網(wǎng)絡(luò)堵塞,那么將無法實現(xiàn)redis集群的主備切換(單點問題)。
- 如果有多個sentinel,redis的客戶端可以隨意地連接任意一個sentinel來獲得關(guān)于redis集群中的信息。
- sentinel集群自身也需要多數(shù)機制,也就是2個sentinel進程時,掛掉一個另一個就不可用了。
注意:Redis Sentinel中的Sentinel節(jié)點個數(shù)應(yīng)該為大于等于3且最好為奇數(shù)
1.2搭建哨兵模式
實驗環(huán)境(測試環(huán)境將sentinel和redis上放一起以減少機器運行,生產(chǎn)環(huán)境不放一起)
192.168.217.135 主服務(wù)器和sentinel
192.168.217.134 從服務(wù)器1和sentinel
192.168.217.133 從服務(wù)器2和sentinel
1.2.1配置節(jié)點文件
#在所有節(jié)點執(zhí)行
[root@redis-master/slave ~]#vim /etc/redis.conf
bind 0.0.0.0
masterauth "123456"
requirepass "123456"
#在所有從節(jié)點執(zhí)行
[root@redis-slave]#echo "replicaof 192.168.217.135 6379" >> /etc/redis.conf
#修改所有節(jié)點的哨兵配置
[root@redis-slave1 ~]#cp /usr/local/src/redis-6.2.5/sentinel.conf /apps/redis/etc/sentinel.conf
[root@redis-slave1 ~]#chown -R redis.redis /apps/redis/etc/sentinel.conf
[root@redis-slave1 ~]#vim /apps/redis/etc/sentinel.conf
port 26379
daemonize no
pidfile "redis-sentinel.pid"
logfile "sentinel_26379.log"
dir "/apps/redis/log"
sentinel monitor mymaster 192.168.217.135 6379
sentinel auth-pass mymaster 123456
sentinel down-after-milliseconds mymaster 3000
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
[root@redis-slave1 ~]# grep "^[a-Z]" /apps/redis/etc/sentinel.conf
bind 0.0.0.0
port 26379
daemonize yes
pidfile "redis-sentinel.pid"
logfile "sentinel_26379.log"
dir "/apps/redis/log"
sentinel monitor mymaster 192.168.217.135 6379
sentinel down-after-milliseconds mymaster 30000
sentinel auth-pass mymaster 123456
sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 180000
sentinel deny-scripts-reconfig yes
[root@redis-slave1 ~]#scp /apps/redis/etc/sentinel.conf 192.168.217.135:/apps/redis/etc/
[root@redis-slave1 ~]#scp /apps/redis/etc/sentinel.conf 192.168.217.133:/apps/redis/etc/
1.2.2啟動哨兵
[root@redis-master/slave ~]#/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --sentinel
正常啟動日志
[root@redis-slave1 ~]#tail -f /apps/redis/log/sentinel_26379.log
6112:X 03 Nov 2022 04:49:15.391 # Configuration loaded
6112:X 03 Nov 2022 04:49:15.391 * Increased maximum number of open files to 10032 (it was originally set to 1024).
6112:X 03 Nov 2022 04:49:15.391 * monotonic clock: POSIX clock_gettime
6112:X 03 Nov 2022 04:49:15.391 * Running mode=sentinel, port=26379.
6112:X 03 Nov 2022 04:49:15.392 # Sentinel ID is e0cfac02ac91ffb0f8295802e75bd4feb5f92e15
6112:X 03 Nov 2022 04:49:15.392 # +monitor master mymaster 192.168.217.135 6379 quorum 2
6112:X 03 Nov 2022 04:49:15.393 * +slave slave 192.168.217.134:6379 192.168.217.134 6379 @ mymaster 192.168.217.135 6379
6112:X 03 Nov 2022 04:49:15.394 * +slave slave 192.168.217.133:6379 192.168.217.133 6379 @ mymaster 192.168.217.135 6379
6112:X 03 Nov 2022 04:49:17.276 * +sentinel sentinel 45a593894e173d503d5793659326c287e7e5a8db 192.168.217.135 26379 @ mymaster 192.168.217.135 6379
6112:X 03 Nov 2022 04:49:24.170 * +sentinel sentinel 8b7bdf988967d4ec0be32e33230a91c9d57d3ed6 192.168.217.133 26379 @ mymaster 192.168.217.135 6379
1.2.3模擬主服務(wù)器down
[root@redis-master ~]#systemctl stop redis.service
日志變化
[root@redis-slave2 ~]#tail -f /apps/redis/log/sentinel_26379.log
***
6251:X 03 Nov 2022 04:55:01.298 # +sdown master mymaster 192.168.217.135 6379
6251:X 03 Nov 2022 04:55:01.378 # +new-epoch 1
6251:X 03 Nov 2022 04:55:01.379 # +vote-for-leader 45a593894e173d503d5793659326c287e7e5a8db 1
6251:X 03 Nov 2022 04:55:02.176 # +config-update-from sentinel 45a593894e173d503d5793659326c287e7e5a8db 192.168.217.135 26379 @ mymaster 192.168.217.135 6379
6251:X 03 Nov 2022 04:55:02.176 # +switch-master mymaster 192.168.217.135 6379 192.168.217.133 6379
6251:X 03 Nov 2022 04:55:02.176 * +slave slave 192.168.217.134:6379 192.168.217.134 6379 @ mymaster 192.168.217.133 6379
6251:X 03 Nov 2022 04:55:02.176 * +slave slave 192.168.217.135:6379 192.168.217.135 6379 @ mymaster 192.168.217.133 6379
2、搭建集群
2.1集群架構(gòu)

注意:①每個Redis 節(jié)點采用相同的相同的Redis版本、相同的密碼、硬件配置
②所有Redis服務(wù)器必須沒有任何數(shù)據(jù)
實驗環(huán)境(測試環(huán)境采用多實例方法)
三臺機器(開放6379,6380端口實現(xiàn)多實例)
192.168.217.135 node1:6379/6380
192.168.217.134 node2:6379/6380
192.168.217.133 node3:6379/6380
2.2啟用redis cluster配置
[root@redis-node1 ~]#vim /apps/redis/etc/redis.conf
[root@redis-node1 ~]# grep "^[a-Z]" /apps/redis/etc/redis.conf
bind 0.0.0.0 -::1
protected-mode yes
port 6379
daemonize no
pidfile /apps/redis/run/redis_6379.pid
logfile /apps/redis/log/redis-6379.log
dbfilename dump6379.rdbs
dir /apps/redis/data/
masterauth 123456
requirepass 123456
appendonly yes
appendfilename "appendonly.aof"
cluster-enabled yes
cluster-config-file nodes-6379.conf
#實現(xiàn)多實例,在同一節(jié)點生成6379和6380的conf和service服務(wù)
[root@redis-node1 ~]#cp -p /apps/redis/etc/redis.conf /apps/redis/etc/redis6380.conf
[root@redis-node1 ~]#sed -i -e 's/6379/6380/' -e 's/dbfilename dump6379\.rdb/dbfilename dump6380.rdb/' -e 's/appendfilename "appendonly6379\.aof"/appendfilename "appendonly6380.aof"/' /apps/redis/etc/redis6380.conf
[root@redis-node1 ~]#cp /lib/systemd/system/redis.service /lib/systemd/system/redis6380.service
[root@redis-node1 ~]#sed -i -e 's/redis.conf/redis6380.conf/' /lib/systemd/system/redis6380.service
[root@redis-node1 ~]#systemctl daemon-reload
[root@redis-node1 ~]#systemctl enable --now redis6380.service redis.service
#準備redis-trib.rb工具
root@redis-node1 ~]#find / -name redis-trib.rb
/usr/local/src/redis-6.2.5/src/redis-trib.rb
[root@redis-node1 ~]#cp /usr/local/src/redis-6.2.5/src/redis-trib.rb /usr/bin/
[root@redis-node1 ~]#redis-trib.rb #依賴ruby
/usr/bin/env: ‘ruby’: No such file or directory
[root@redis-node1 ~]#yum install rubygems -y
#將生成的多實例文件復(fù)制到node2和node3
[root@redis-node1 ~]#scp /apps/redis/etc/redis.conf 192.168.217.134:/apps/redis/etc/redis.conf
[root@redis-node1 ~]#scp /apps/redis/etc/redis6380.conf 192.168.217.134:/apps/redis/etc/redis6380.conf
[root@redis-node1 ~]#scp /lib/systemd/system/redis6380.service 192.168.217.134:/lib/systemd/system/redis6380.service
[root@redis-node1 ~]#scp /apps/redis/etc/redis.conf 192.168.217.133:/apps/redis/etc/redis.conf
[root@redis-node1 ~]#scp /apps/redis/etc/redis6380.conf 192.168.217.133:/apps/redis/etc/redis6380.conf
[root@redis-node1 ~]#scp /lib/systemd/system/redis6380.service 192.168.217.133:/lib/systemd/system/redis6380.service
2.3創(chuàng)建集群
[root@redis-node1 ~]#redis-cli --cluster create 192.168.217.135:6379 192.168.217.134:6379 192.168.217.133:6379 192.168.217.135:6380 192.168.217.134:6380 192.168.217.133:6380 -a 123456 --cluster-replicas 1
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.217.134:6380 to 192.168.217.135:6379
Adding replica 192.168.217.133:6380 to 192.168.217.134:6379
Adding replica 192.168.217.135:6380 to 192.168.217.133:6379
M: 0220317b886f2fd4b761fc623caada4ca7396989 192.168.217.135:6379
slots:[0-5460] (5461 slots) master
M: 89718ba22faef64b365299a3c412ba837fe74947 192.168.217.134:6379
slots:[5461-10922] (5462 slots) master
M: d847d2418416622767fb22b548492b9d5dc1b615 192.168.217.133:6379
slots:[10923-16383] (5461 slots) master
S: e221a42fe139d8466a1707e77331dd2aa1da26dd 192.168.217.135:6380
replicates d847d2418416622767fb22b548492b9d5dc1b615
S: 419a959943eae2373f6a7d95afed86cb6796cdfa 192.168.217.134:6380
replicates 0220317b886f2fd4b761fc623caada4ca7396989
S: e145eb7842622d1b535521883ee39fb0689901c7 192.168.217.133:6380
replicates 89718ba22faef64b365299a3c412ba837fe74947
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
>>> Performing Cluster Check (using node 192.168.217.135:6379)
M: 0220317b886f2fd4b761fc623caada4ca7396989 192.168.217.135:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
M: d847d2418416622767fb22b548492b9d5dc1b615 192.168.217.133:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: 419a959943eae2373f6a7d95afed86cb6796cdfa 192.168.217.134:6380
slots: (0 slots) slave
replicates 0220317b886f2fd4b761fc623caada4ca7396989
M: 89718ba22faef64b365299a3c412ba837fe74947 192.168.217.134:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: e221a42fe139d8466a1707e77331dd2aa1da26dd 192.168.217.135:6380
slots: (0 slots) slave
replicates d847d2418416622767fb22b548492b9d5dc1b615
S: e145eb7842622d1b535521883ee39fb0689901c7 192.168.217.133:6380
slots: (0 slots) slave
replicates 89718ba22faef64b365299a3c412ba837fe74947
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
redis-cluster使用的局限性
集群的優(yōu)點:
- 多個master讀寫,解決了單點故障,寫性能得到比較好的提升
- 有從節(jié)點作為備份
集群的缺點:
- 成本高,機器多,維護比較麻煩
- 不支持讀寫分離,因為從節(jié)點不提供讀功能,從節(jié)點只能同步主節(jié)點的數(shù)據(jù)
- 客戶端鏈接的時候,還是得找一下槽位,導(dǎo)致響應(yīng)可能會慢
- 有些命令例如mget,keys *等遍歷所有庫的,不方便
- 集群cluster會和sentinel哨兵沖突,建議選擇一個即可,一般來說哨兵+主從足以,一個項目一套,不要混用redis即可
像磐石系統(tǒng):直接使用的哨兵來實現(xiàn),1主2從,加上哨兵做高可用即可
二、LVS常用模型工作原理,負載策略
1、負載均衡LVS基本介紹
LB集群的架構(gòu)和原理很簡單,就是當用戶的請求過來時,會直接分發(fā)到Director Server上,然后它把用戶的請求根據(jù)設(shè)置好的調(diào)度算法,智能均衡地分發(fā)到后端真正服務(wù)器(real server)上。為了避免不同機器上用戶請求得到的數(shù)據(jù)不一樣,需要用到了共享存儲,這樣保證所有用戶請求的數(shù)據(jù)是一樣的。
LVS是 Linux Virtual Server 的簡稱,也就是Linux虛擬服務(wù)器。這是一個由章文嵩博士發(fā)起的一個開源項目,它的官方網(wǎng)是 http://www.linuxvirtualserver.org 現(xiàn)在 LVS 已經(jīng)是 Linux 內(nèi)核標準的一部分。使用 LVS 可以達到的技術(shù)目標是:通過 LVS 達到的負載均衡技術(shù)和 Linux 操作系統(tǒng)實現(xiàn)一個高性能高可用的 Linux 服務(wù)器集群,它具有良好的可靠性、可擴展性和可操作性。從而以低廉的成本實現(xiàn)最優(yōu)的性能。LVS 是一個實現(xiàn)負載均衡集群的開源軟件項目,LVS架構(gòu)從邏輯上可分為調(diào)度層、Server集群層和共享存儲。
2、LVS的基本工作原理

當用戶向負載均衡調(diào)度器(Director Server)發(fā)起請求,調(diào)度器將請求發(fā)往至內(nèi)核空間
PREROUTING鏈首先會接收到用戶請求,判斷目標IP確定是本機IP,將數(shù)據(jù)包發(fā)往INPUT鏈
IPVS是工作在INPUT鏈上的,當用戶請求到達INPUT時,IPVS會將用戶請求和自己已定義好的集群服務(wù)進行比對,如果用戶請求的就是定義的集群服務(wù),那么此時IPVS會強行修改數(shù)據(jù)包里的目標IP地址及端口,并將新的數(shù)據(jù)包發(fā)往POSTROUTING鏈
POSTROUTING鏈接收數(shù)據(jù)包后發(fā)現(xiàn)目標IP地址剛好是自己的后端服務(wù)器,那么此時通過選路,將數(shù)據(jù)包最終發(fā)送給后端的服務(wù)器
3、LVS的組成
LVS 由2部分程序組成,包括 ipvs 和 ipvsadm。
ipvs(ip virtual server):一段代碼工作在內(nèi)核空間,叫ipvs,是真正生效實現(xiàn)調(diào)度的代碼。
ipvsadm:另外一段是工作在用戶空間,叫ipvsadm,負責(zé)為ipvs內(nèi)核框架編寫規(guī)則,定義誰是集群服務(wù),而誰是后端真實的服務(wù)器(Real Server)
4、LVS相關(guān)術(shù)語
名稱 定義
DS Director Server 指的是前端負載均衡器節(jié)點
RS Real Server。后端真實的工作服務(wù)器
VIP Virtual IP 向外部直接面向用戶請求,作為用戶請求的目標的IP地址
DIP Director Server IP,主要用于和內(nèi)部主機通訊的IP地址
RIP Real Server IP,后端服務(wù)器的IP地址
CIP Client IP,訪問客戶端的IP地址
5、LVS/NAT原理和特點

5.1 重點理解NAT方式的實現(xiàn)原理和數(shù)據(jù)包的改變
(a). 當用戶請求到達Director Server,此時請求的數(shù)據(jù)報文會先到內(nèi)核空間的PREROUTING鏈。 此時報文的源IP為CIP,目標IP為VIP
(b). PREROUTING檢查發(fā)現(xiàn)數(shù)據(jù)包的目標IP是本機,將數(shù)據(jù)包送至INPUT鏈
(c). IPVS比對數(shù)據(jù)包請求的服務(wù)是否為集群服務(wù),若是,修改數(shù)據(jù)包的目標IP地址為后端服務(wù)器IP,然后將數(shù)據(jù)包發(fā)至POSTROUTING鏈。 此時報文的源IP為CIP,目標IP為RIP
(d). POSTROUTING鏈通過選路,將數(shù)據(jù)包發(fā)送給Real Server
(e). Real Server比對發(fā)現(xiàn)目標為自己的IP,開始構(gòu)建響應(yīng)報文發(fā)回給Director Server。 此時報文的源IP為RIP,目標IP為CIP
(f). Director Server在響應(yīng)客戶端前,此時會將源IP地址修改為自己的VIP地址,然后響應(yīng)給客戶端。 此時報文的源IP為VIP,目標IP為CIP
5.2 LVS-NAT模型的特性
RS應(yīng)該使用私有地址,RS的網(wǎng)關(guān)必須指向DIP
DIP和RIP必須在同一個網(wǎng)段內(nèi)
請求和響應(yīng)報文都需要經(jīng)過Director Server,高負載場景中,Director Server易成為性能瓶頸
支持端口映射
RS可以使用任意操作系統(tǒng)
缺陷:對Director Server壓力會比較大,請求和響應(yīng)都需經(jīng)過director server
6、LVS/DR原理和特點

6.1重點將請求報文的目標MAC地址設(shè)定為挑選出的RS的MAC地址
(a) 當用戶請求到達Director Server,此時請求的數(shù)據(jù)報文會先到內(nèi)核空間的PREROUTING鏈。 此時報文的源IP為CIP,目標IP為VIP
(b) PREROUTING檢查發(fā)現(xiàn)數(shù)據(jù)包的目標IP是本機,將數(shù)據(jù)包送至INPUT鏈
(c) IPVS比對數(shù)據(jù)包請求的服務(wù)是否為集群服務(wù),若是,將請求報文中的源MAC地址修改為DIP的MAC地址,將目標MAC地址修改RIP的MAC地址,然后將數(shù)據(jù)包發(fā)至POSTROUTING鏈。 此時的源IP和目的IP均未修改,僅修改了源MAC地址為DIP的MAC地址,目標MAC地址為RIP的MAC地址
(d) 由于DS和RS在同一個網(wǎng)絡(luò)中,所以是通過二層來傳輸。POSTROUTING鏈檢查目標MAC地址為RIP的MAC地址,那么此時數(shù)據(jù)包將會發(fā)至Real Server。
(e) RS發(fā)現(xiàn)請求報文的MAC地址是自己的MAC地址,就接收此報文。處理完成之后,將響應(yīng)報文通過lo接口傳送給eth0網(wǎng)卡然后向外發(fā)出。 此時的源IP地址為VIP,目標IP為CIP
(f) 響應(yīng)報文最終送達至客戶端
6.2 LVS-DR模型的特性
特點1:保證前端路由將目標地址為VIP報文統(tǒng)統(tǒng)發(fā)給Director Server,而不是RS
RS可以使用私有地址;也可以是公網(wǎng)地址,如果使用公網(wǎng)地址,此時可以通過互聯(lián)網(wǎng)對RIP進行直接訪問
RS跟Director Server必須在同一個物理網(wǎng)絡(luò)中
所有的請求報文經(jīng)由Director Server,但響應(yīng)報文必須不能進過Director Server
不支持地址轉(zhuǎn)換,也不支持端口映射
RS可以是大多數(shù)常見的操作系統(tǒng)
RS的網(wǎng)關(guān)絕不允許指向DIP(因為我們不允許他經(jīng)過director)
RS上的lo接口配置VIP的IP地址
缺陷:RS和DS必須在同一機房中
6.3 特點1的解決方案:
在前端路由器做靜態(tài)地址路由綁定,將對于VIP的地址僅路由到Director Server
存在問題:用戶未必有路由操作權(quán)限,因為有可能是運營商提供的,所以這個方法未必實用
arptables:在arp的層次上實現(xiàn)在ARP解析時做防火墻規(guī)則,過濾RS響應(yīng)ARP請求。這是由iptables提供的
修改RS上內(nèi)核參數(shù)(arp_ignore和arp_announce)將RS上的VIP配置在lo接口的別名上,并限制其不能響應(yīng)對VIP地址解析請求。
7、LVS/Tun原理和特點

7.1 在原有的IP報文外再次封裝多一層IP首部,內(nèi)部IP首部(源地址為CIP,目標IIP為VIP),外層IP首部(源地址為DIP,目標IP為RIP)
(a) 當用戶請求到達Director Server,此時請求的數(shù)據(jù)報文會先到內(nèi)核空間的PREROUTING鏈。 此時報文的源IP為CIP,目標IP為VIP 。
(b) PREROUTING檢查發(fā)現(xiàn)數(shù)據(jù)包的目標IP是本機,將數(shù)據(jù)包送至INPUT鏈
? IPVS比對數(shù)據(jù)包請求的服務(wù)是否為集群服務(wù),若是,在請求報文的首部再次封裝一層IP報文,封裝源IP為為DIP,目標IP為RIP。然后發(fā)至POSTROUTING鏈。 此時源IP為DIP,目標IP為RIP
(d) POSTROUTING鏈根據(jù)最新封裝的IP報文,將數(shù)據(jù)包發(fā)至RS(因為在外層封裝多了一層IP首部,所以可以理解為此時通過隧道傳輸)。 此時源IP為DIP,目標IP為RIP
(e) RS接收到報文后發(fā)現(xiàn)是自己的IP地址,就將報文接收下來,拆除掉最外層的IP后,會發(fā)現(xiàn)里面還有一層IP首部,而且目標是自己的lo接口VIP,那么此時RS開始處理此請求,處理完成之后,通過lo接口送給eth0網(wǎng)卡,然后向外傳遞。 此時的源IP地址為VIP,目標IP為CIP
(f) 響應(yīng)報文最終送達至客戶端
7.2 LVS-Tun模型特性
RIP、VIP、DIP全是公網(wǎng)地址
RS的網(wǎng)關(guān)不會也不可能指向DIP
所有的請求報文經(jīng)由Director Server,但響應(yīng)報文必須不能進過Director Server
不支持端口映射
RS的系統(tǒng)必須支持隧道
其實企業(yè)中最常用的是 DR 實現(xiàn)方式,而 NAT 配置上比較簡單和方便。
8、LVS的十種調(diào)度算法:
靜態(tài)(fixed):
rr:round robin 輪調(diào)
wrr: weight rr 加權(quán)的輪調(diào)
sh: source hash 源地址哈希,對客戶端IP地址做哈希,director會維護一個session hash table,結(jié)果就是來自同一個客戶端的請求都會被調(diào)度到一臺后端服務(wù)器。
dh: destination hash 目標url等hash,適用于有cache server場景,對于同一請求發(fā)送到同一cache server.
動態(tài)(Dynamic):
-
lc: least connection 最少連接
overhead = active(活動連接數(shù))*256 + inactive 選最小的
-
wlc: weight lc 加權(quán)的最小連接
Overhead= (active*256 + inactive) / weight 選最小的
-
sed: shortest expected delay 最小期望延遲
overhead = (active + 1)*256 / weight
nq: never queue 永不排隊,開始就先一人發(fā)一個,然后再按sed算法調(diào)度
-
lblc: locality based least connection基于本地的最小連接
動態(tài)的dh,大概相當于dh + lc
-
lblcr : lblc with replication 帶復(fù)制的lblc
director維護一個proxy server table,請求進來時選擇活動連接最少的
三、通過LVS DR任意實現(xiàn)1-2種場景
1、LVS-DR模式單網(wǎng)段案例
實驗環(huán)境(五臺機器)
-Client : eth0主機模式:192.168.36.100 GW:192.168.36.200
-ROUTER : eth0主機模式:192.168.36.200 / eth1 NAT:192.168.217.134
-LVS : eth0主機模式:192.168.36.200 / eth1 NAT:192.168.217.134
-RS1 : eth0 NAT: 192.168.217.133 GW:192.168.217.134
-RS2 : eth0 NAT: 192.168.217.132 GW:192.168.217.134
1.1、路由器設(shè)置
#設(shè)置轉(zhuǎn)發(fā)權(quán)限
[root@Router ~]#echo 'net.ipv4.ip_forward=1' >>/etc/sysctl.conf
[root@Router ~]#sysctl -p
1.2、后端RealSever設(shè)置
#RS1開啟vip
[root@RS1 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@RS1 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@RS1 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@RS1 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
#此為臨時生效,想永久生效可將其寫入/etc/sysctl.conf文件里
net.ipv4.conf.all.arp_ignore=1
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.lo.arp_ignore=1
net.ipv4.conf.lo.arp_announce=2
#注意:必須先設(shè)置,然后才能添加VIP
#限制響應(yīng)級別:arp_ignore
0:默認值,表示可使用本地任意接口上配置的任意地址進行響應(yīng)
1:僅在請求的目標IP配置在本地主機的接收到請求報文的接口上時,才給予響應(yīng)
#限制通告級別:arp_announce
0:默認值,把本機所有接口的所有信息向每個接口的網(wǎng)絡(luò)進行通告
1:盡量避免將接口信息向非直接連接網(wǎng)絡(luò)進行通告
2:必須避免將接口信息向非本網(wǎng)絡(luò)進行通告
[root@RS1 ~]#ifconfig lo:1 192.168.217.100/32 # 添加回環(huán)ip
#RS2設(shè)置
[root@RS2 ~]#echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
[root@RS2 ~]#echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce
[root@RS2 ~]#echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore
[root@RS2 ~]#echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce
[root@RS2 ~]#ifconfig lo:1 192.168.217.100/32
1.3、LVS設(shè)置
#設(shè)置路由規(guī)則,實現(xiàn)LVS 規(guī)則
[root@LVS-server ~]#yum -y install ipvsadm
[root@LVS-server ~]#ifconfig lo:1 192.168.217.100/32 # 添加回環(huán)ip
[root@LVS-server ~]#ipvsadm -A -t 192.168.217.100:80 -s rr
[root@LVS-server ~]#ipvsadm -a -t 192.168.217.100:80 -r 192.168.217.133:80 -g
[root@LVS-server ~]#ipvsadm -a -t 192.168.217.100:80 -r 192.168.217.132:80 -g
[root@LVS-server ~]#ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.217.100:80 rr
-> 192.168.217.132:80 Route 1 0 0
-> 192.168.217.133:80 Route 1 0 0
1.4、測試訪問
[root@client ~]#curl 192.168.217.100
This is RS2
[root@client ~]#curl 192.168.217.100
This is RS1
[root@client ~]#curl 192.168.217.100
This is RS2
[root@client ~]#curl 192.168.217.100
This is RS1
四、web http協(xié)議通信過程,相關(guān)技術(shù)術(shù)語總結(jié)
1、http協(xié)議通信過程

2、相關(guān)技術(shù)術(shù)語總結(jié)
2.1、WEB開發(fā)語言
http:Hyper Text Transfer Protocol 應(yīng)用層協(xié)議,默認端口: 80/tcp
①html:Hyper Text Markup Language 超文本標記語言,編程語言,主要負責(zé)實現(xiàn)頁面的結(jié)構(gòu)
②CSS:Cascading Style Sheet 層疊樣式表, 定義了如何顯示(裝扮) HTML 元素,比如:字體大小和顏色屬性等。樣式通常保存在外部的 .css 文件中,用于存放一些HTML文件的公共屬性,從而通過僅編輯一個簡單的 CSS 文檔,可以同時改變站點中所有頁面的布局和外觀。
③Js:javascript,實現(xiàn)網(wǎng)頁的動畫效果,但實屬于靜態(tài)資源
2.2、MIME
MIME : Multipurpose Internet Mail Extensions 多用途互聯(lián)網(wǎng)郵件擴展
文件 /etc/mime.types ,來自于mailcap包
MIME格式:type/subtype txt html jpg bmp
2.3、URI和URL
URI: Uniform Resource Identifier 統(tǒng)一資源標識,分為URL 和 URN
URN:Uniform Resource Naming,統(tǒng)一資源命名
示例: P2P下載使用的磁力鏈接是URN的一種實現(xiàn) magnet:?xt=urn:btih:660557A6890EF888666
URL:Uniform Resorce Locator,統(tǒng)一資源定位符,用于描述某服務(wù)器某特定資源位置
兩者區(qū)別:URN如同一個人的名稱,而URL代表一個人的住址。換言之,URN定義某事物的身份,而
URL提供查找該事物的方法。URN僅用于命名,而不指定地址。
URL組成

scheme:方案,訪問服務(wù)器以獲取資源時要使用哪種協(xié)議
user:用戶,某些方案訪問資源時需要的用戶名
password:密碼,用戶對應(yīng)的密碼,中間用:分隔
Host:主機,資源宿主服務(wù)器的主機名或IP地址
port:端口,資源宿主服務(wù)器正在監(jiān)聽的端口號,很多方案有默認端口號
path:路徑,服務(wù)器資源的本地名,由一個/將其與前面的URL組件分隔
params:參數(shù),指定輸入的參數(shù),參數(shù)為名/值對,多個參數(shù),用;分隔
query:查詢,傳遞參數(shù)給程序,如數(shù)據(jù)庫,用?分隔,多個查詢用&分隔
frag:片段,一小片或一部分資源的名字,此組件在客戶端使用,用#分隔
五、總結(jié)網(wǎng)絡(luò)IO模型和nginx架構(gòu)
1、網(wǎng)絡(luò)IO模型
阻塞型、非阻塞型、復(fù)用型、信號驅(qū)動型、異步
1.1、阻塞型I/O模型(blocking IO)

①阻塞IO模型是最簡單的I/O模型,用戶線程在內(nèi)核進行IO操作時被阻塞
②用戶線程通過系統(tǒng)調(diào)用read發(fā)起I/O讀操作,由用戶空間轉(zhuǎn)到內(nèi)核空間。內(nèi)核等到數(shù)據(jù)包到達后,然后將
接收的數(shù)據(jù)拷貝到用戶空間,完成read操作
③用戶需要等待read將數(shù)據(jù)讀取到buffer后,才繼續(xù)處理接收的數(shù)據(jù)。整個I/O請求的過程中,用戶線程是
被阻塞的,這導(dǎo)致用戶在發(fā)起IO請求時,不能做任何事情,對CPU的資源利用率不夠
優(yōu)點:程序簡單,在阻塞等待數(shù)據(jù)期間進程/線程掛起,基本不會占用 CPU 資源
缺點:每個連接需要獨立的進程/線程單獨處理,當并發(fā)請求量大時為了維護程序,內(nèi)存、線程切換開銷
較大,apache 的prefork使用的是這種模式。
1.2、非阻塞型I/O模型(nonblocking IO)

用戶線程發(fā)起IO請求時立即返回。但并未讀取到任何數(shù)據(jù),用戶線程需要不斷地發(fā)起IO請求,直到數(shù)據(jù)
到達后,才真正讀取到數(shù)據(jù),繼續(xù)執(zhí)行。即 “輪詢”機制存在兩個問題:如果有大量文件描述符都要等,
那么就得一個一個的read。這會帶來大量的Context Switch(read是系統(tǒng)調(diào)用,每調(diào)用一次就得在用戶
態(tài)和核心態(tài)切換一次)。輪詢的時間不好把握。這里是要猜多久之后數(shù)據(jù)才能到。等待時間設(shè)的太長,
程序響應(yīng)延遲就過大;設(shè)的太短,就會造成過于頻繁的重試,干耗CPU而已,是比較浪費CPU的方式,一
般很少直接使用這種模型,而是在其他IO模型中使用非阻塞IO這一特性。
1.3、I/O多路復(fù)用型(I/O multiplexing)

①多路復(fù)用IO指一個線程可以同時(實際是交替實現(xiàn),即并發(fā)完成)監(jiān)控和處理多個文件描述符對應(yīng)各自
的IO,即復(fù)用同一個線程
②一個線程之所以能實現(xiàn)同時處理多個IO,是因為這個線程調(diào)用了內(nèi)核中的SELECT,POLL或EPOLL等系統(tǒng)
調(diào)用,從而實現(xiàn)多路復(fù)用IO
③它的基本原理就是select/poll/epoll這個function會不斷的輪詢所負責(zé)的所有socket,當某個socket有數(shù)
據(jù)到達了,就通知用戶進程。
④當用戶進程調(diào)用了select,那么整個進程會被block,而同時,kernel會“監(jiān)視”所有select負責(zé)的socket,
當任何一個socket中的數(shù)據(jù)準備好了,select就會返回。這個時候用戶進程再調(diào)用read操作,將數(shù)據(jù)從
kernel拷貝到用戶進程。
優(yōu)點:可以基于一個阻塞對象,同時在多個描述符上等待就緒,而不是使用多個線程(每個文件描述
符一個線程),這樣可以大大節(jié)省系統(tǒng)資源
缺點:當連接數(shù)較少時效率相比多線程+阻塞 I/O 模型效率較低,可能延遲更大,因為單個連接處
理需要 2 次系統(tǒng)調(diào)用,占用時間會有增加
IO多路復(fù)用適用如下場合:
當客戶端處理多個描述符時(一般是交互式輸入和網(wǎng)絡(luò)套接口),必須使用I/O復(fù)用
當一個客戶端同時處理多個套接字時,此情況可能的但很少出現(xiàn)
當一個服務(wù)器既要處理監(jiān)聽套接字,又要處理已連接套接字,一般也要用到I/O復(fù)用
當一個服務(wù)器即要處理TCP,又要處理UDP,一般要使用I/O復(fù)用
當一個服務(wù)器要處理多個服務(wù)或多個協(xié)議,一般要使用I/O復(fù)用
1.4、信號驅(qū)動式I/O模型(signal-driven IO)

信號驅(qū)動I/O的意思就是進程現(xiàn)在不用傻等著,也不用去輪詢。而是讓內(nèi)核在數(shù)據(jù)就緒時,發(fā)送信號通知
進程。
調(diào)用的步驟:通過系統(tǒng)調(diào)用 sigaction ,并注冊一個信號處理的回調(diào)函數(shù),該調(diào)用會立即返回,然后
主程序可以繼續(xù)向下執(zhí)行,當有I/O操作準備就緒,即內(nèi)核數(shù)據(jù)就緒時,內(nèi)核會為該進程產(chǎn)生一個 SIGIO
信號,并回調(diào)注冊的信號回調(diào)函數(shù),這樣就可以在信號回調(diào)函數(shù)中系統(tǒng)調(diào)用 recvfrom 獲取數(shù)據(jù),將用戶
進程所需要的數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間
此模型的優(yōu)勢在于等待數(shù)據(jù)報到達期間進程不被阻塞。用戶主程序可以繼續(xù)執(zhí)行,只要等待來自信號處
理函數(shù)的通知。
在信號驅(qū)動式 I/O 模型中,應(yīng)用程序使用套接口進行信號驅(qū)動 I/O,并安裝一個信號處理函數(shù),進程繼
續(xù)運行并不阻塞
當數(shù)據(jù)準備好時,進程會收到一個 SIGIO 信號,可以在信號處理函數(shù)中調(diào)用 I/O 操作函數(shù)處理數(shù)據(jù)。
優(yōu)點:線程并沒有在等待數(shù)據(jù)時被阻塞,內(nèi)核直接返回調(diào)用接收信號,不影響進程繼續(xù)處理其他請求因此
可以提高資源的利用率
缺點:信號 I/O 在大量 IO 操作時可能會因為信號隊列溢出導(dǎo)致沒法通知
1.5、異步I/O模型(asynchronous IO)

執(zhí)行過程:用戶進程進行aio_read系統(tǒng)調(diào)用之后,無論內(nèi)核數(shù)據(jù)是否準備好,都會直接返回給用戶進程,然后用戶態(tài)進程可以去做別的事情。等到socket數(shù)據(jù)準備好了,內(nèi)核直接復(fù)制數(shù)據(jù)給進程,然后從內(nèi)核向進程發(fā)送通知。IO兩個階段,進程都是非阻塞的。
信號驅(qū)動IO當內(nèi)核通知觸發(fā)信號處理程序時,信號處理程序還需要阻塞在從內(nèi)核空間緩沖區(qū)拷貝數(shù)據(jù)到
用戶空間緩沖區(qū)這個階段,而異步IO直接是在第二個階段完成后,內(nèi)核直接通知用戶線程可以進行后續(xù)
操作了
優(yōu)點:異步 I/O 能夠充分利用 DMA 特性,讓 I/O 操作與計算重疊
缺點:要實現(xiàn)真正的異步 I/O,操作系統(tǒng)需要做大量的工作。目前 Windows 下通過 IOCP 實現(xiàn)了真正的
異步 I/O,在 Linux 系統(tǒng)下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下實現(xiàn)高并發(fā)網(wǎng)絡(luò)編
程時以 IO 復(fù)用模型模式+多線程任務(wù)的架構(gòu)基本可以滿足需求
六、nginx總結(jié)核心配置和優(yōu)化
1、Nginx的配置文件的組成部分
①主配置文件:nginx.conf
②子配置文件: include conf.d/*.conf
③fastcgi, uwsgi,scgi 等協(xié)議相關(guān)的配置文件
④mime.types:支持的mime類型,MIME(Multipurpose Internet Mail Extensions)多用途互聯(lián)網(wǎng)郵件擴展類型,MIME消息能包含文本、圖像、音頻、視頻以及其他應(yīng)用程序?qū)S玫臄?shù)據(jù),是設(shè)定某種擴展名的文件用一種應(yīng)用程序來打開的方式類型,當該擴展名文件被訪問的時候,瀏覽器會自動使用指定應(yīng)用程序來打開。多用于指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。
MIME參考文檔:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_Types
2、nginx 配置文件格式說明
配置文件由指令與指令塊構(gòu)成
每條指令以;分號結(jié)尾,指令與值之間以空格符號分隔
可以將多條指令放在同一行,用分號分隔即可,但可讀性差,不推薦
指令塊以{ }大括號將多條指令組織在一起,且可以嵌套指令塊
include語句允許組合多個配置文件以提升可維護性
使用#符號添加注釋,提高可讀性
使用$符號使用變量
部分指令的參數(shù)支持正則表達式
3、主配置文件結(jié)構(gòu):四部分
directive value [value2 ...];
注意
(1) 指令必須以分號結(jié)尾
(2) 支持使用配置變量
內(nèi)建變量:由Nginx模塊引入,可直接引用
自定義變量:由用戶使用set命令定義,格式: set variable_name value;
引用變量:$variable_name
主配置文件結(jié)構(gòu):四部分
main block:主配置段,即全局配置段,對http,mail都有效
#事件驅(qū)動相關(guān)的配置
event {
...
}
#http/https 協(xié)議相關(guān)配置段
http {
...
}
#默認配置文件不包括下面兩個塊
#mail 協(xié)議相關(guān)配置段
mail {
...
}
#stream 服務(wù)器相關(guān)配置段
stream {
...
}
4、全局配置中的必備配置和優(yōu)化
user nginx nginx; #啟動Nginx工作進程的用戶和組
worker_processes [number | auto]; #啟動Nginx工作進程的數(shù)量,一般設(shè)為和CPU核心數(shù)相同
worker_cpu_affinity 00000001 00000010 00000100 00001000 | auto ; #將Nginx工作進程綁定到指定的CPU核心,默認Nginx是不進行進程綁定的,綁定并不是意味著當前nginx進程獨占以一核心CPU,但是可以保證此進程不會運行在其他核心上,這就極大減少了nginx的工作進程在不同的cpu核心上的來回跳轉(zhuǎn),減少了CPU對進程的資源分配與回收以及內(nèi)存管理等,因此可以有效的提升nginx服務(wù)器的性能。
CPU MASK: 00000001:0號CPU
00000010:1號CPU
10000000:7號CPU
#示例:
worker_cpu_affinity 0001 0010 0100 1000;第0號---第3號CPU
worker_cpu_affinity 0101 1010;
#錯誤日志記錄配置,語法:error_log file [debug | info | notice | warn | error | crit | alert | emerg]
#error_log logs/error.log;
#error_log logs/error.log notice;
error_log /apps/nginx/logs/error.log error;
#pid文件保存路徑
pid /apps/nginx/logs/nginx.pid;
worker_priority 0; #工作進程優(yōu)先級,-20~20(19)
worker_rlimit_nofile 65536; #所有worker進程能打開的文件數(shù)量上限,包括:Nginx的所有連接(例如與代理服務(wù)器的連接等),而不僅僅是與客戶端的連接,另一個考慮因素是實際的并發(fā)連接數(shù)不能超過系統(tǒng)級別的最大打開文件數(shù)的限制.最好與ulimit -n 或者limits.conf的值保持一致,
daemon off; #前臺運行Nginx服務(wù)用于測試、或者以容器運行時,需要設(shè)為off
master_process off|on; #是否開啟Nginx的master-worker工作模式,僅用于開發(fā)調(diào)試場景,默認為on
events {
worker_connections 65536; #設(shè)置單個工作進程的最大并發(fā)連接數(shù)
use epoll; #使用epoll事件驅(qū)動,Nginx支持眾多的事件驅(qū)動,比如:select、poll、epoll,只能設(shè)置在events模塊中設(shè)置。
accept_mutex on; #on為同一時刻一個請求輪流由worker進程處理,而防止被同時喚醒所有worker,避免多個睡眠進程被喚醒的設(shè)置,默認為off,新請求會喚醒所有worker進程,此過程也稱為"驚 群",因此nginx剛安裝完以后要進行適當?shù)膬?yōu)化。建議設(shè)置為on
multi_accept on; #on時Nginx服務(wù)器的每個工作進程可以同時接受多個新的網(wǎng)絡(luò)連接,此指令默認為off,即默認為一個工作進程只能一次接受一個新的網(wǎng)絡(luò)連接,打開后幾個同時接受多個。建議設(shè)置為on
}
5、http 協(xié)議配置中的必備配置和優(yōu)化
http {
include mime.types; #導(dǎo)入支持的文件類型,是相對于/apps/nginx/conf的目錄
default_type application/octet-stream; #除mime.types中文件類型外,設(shè)置其它文件默認類型,訪問其它類型時會提示下載不匹配的類型文件
#日志配置部分
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
#自定義優(yōu)化參數(shù)
sendfile on;
#tcp_nopush on; #在開啟了sendfile的情況下,合并請求后統(tǒng)一發(fā)送給客戶端,必須開啟sendfile
#tcp_nodelay off; #在開啟了keepalived模式下的連接是否啟用TCP_NODELAY選項,當為off時,延遲0.2s發(fā)送,默認On時,不延遲發(fā)送,立即發(fā)送用戶響應(yīng)報文。
#keepalive_timeout 0;
keepalive_timeout 65 65; #設(shè)置會話保持時間,第二個值為響應(yīng)首部:keep?Alived:timeout=65,可以和第一個值不同
#gzip on; #開啟文件壓縮
server {
listen 80; #設(shè)置監(jiān)聽地址和端口
server_name localhost; #設(shè)置server name,可以以空格隔開寫多個并支持正則表達式,如:*.magedu.com www.magedu.* ~^www\d+\.magedu\.com$ default_server
#charset koi8-r; #設(shè)置編碼格式,默認是俄語格式,建議改為utf-8
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html; #定義錯誤頁面
location = /50x.html {
root html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ { #以http的方式轉(zhuǎn)發(fā)php請求到指定web服務(wù)器
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ { #以fastcgi的方式轉(zhuǎn)發(fā)php請求到php處理
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht { #拒絕web形式訪問指定文件,如很多的網(wǎng)站都是通過.htaccess文件來改變自己的重定向等功能。
# deny all;
#}
location ~ /passwd.html {
deny all;
}
}
# another virtual host using mix of IP-, name-, and port-based configuration
#
#server { #自定義虛擬server
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;
# location / {
# root html;
# index index.html index.htm; #指定默認網(wǎng)頁文件,此指令由
ngx_http_index_module模塊提供
# }
#}
# HTTPS server
#
#server { #https服務(wù)器配置
# listen 443 ssl;
# server_name localhost;
# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
# location / {
# root html;
# index index.html index.htm;
# }
#}
七、使用腳本完成一鍵編譯安裝nginx任意版本
#!/bin/bash
SRC_DIR=/usr/local/src
NGINX_URL=http://nginx.org/download/
NGINX_FILE=nginx-1.20.2
TAR=.tar.gz
NGINX_INSTALL_DIR=/apps/nginx
CPUS=`lscpu |awk '/^CPU\(s\)/{print $2}'`
. /etc/os-release
os_type () {
awk -F'[ "]' '/^NAME/{print $2}' /etc/os-release
}
os_version () {
awk -F'"' '/^VERSION_ID/{print $2}' /etc/os-release
}
check () {
[ -e ${NGINX_INSTALL_DIR} ] && { color "nginx 已安裝,請卸載后再安裝" 1; exit; }
cd ${SRC_DIR}
if [ -e ${NGINX_FILE}${TAR} ];then
color "相關(guān)文件已準備好" 0
else
color '開始下載 nginx 源碼包' 0
wget ${NGINX_URL}${NGINX_FILE}${TAR}
[ $? -ne 0 ] && { color "下載 ${NGINX_FILE}${TAR}文件失敗" 1; exit; }
fi
}
install () {
color "開始安裝 nginx" 0
if id nginx &> /dev/null;then
color "nginx 用戶已存在" 1
else
useradd -s /sbin/nologin -r nginx
color "創(chuàng)建 nginx 用戶" 0
fi
color "開始安裝 nginx 依賴包" 0
if [ $ID == "centos" ] ;then
if [[ $VERSION_ID =~ ^7 ]];then
yum -y -q install make gcc pcre-devel openssl-devel zlib-devel perl-ExtUtils-Embed
elif [[ $VERSION_ID =~ ^8 ]];then
yum -y -q install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
color '不支持此系統(tǒng)!' 1
exit
fi
elif [ $ID == "rocky" ];then
yum -y -q install make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed
else
apt update &> /dev/null
apt -y install make gcc libpcre3 libpcre3-dev openssl libssl-dev zlib1g-dev &> /dev/null
fi
cd $SRC_DIR
tar xf ${NGINX_FILE}${TAR}
NGINX_DIR=`echo ${NGINX_FILE}${TAR}| sed -nr 's/^(.*[0-9]).*/\1/p'`
cd ${NGINX_DIR}
./configure --prefix=${NGINX_INSTALL_DIR} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
make -j $CPUS && make install
[ $? -eq 0 ] && color "nginx 編譯安裝成功" 0 || { color "nginx 編譯安裝失敗,退出!" 1 ;exit; }
echo "PATH=${NGINX_INSTALL_DIR}/sbin:${PATH}" > /etc/profile.d/nginx.sh
cat > /lib/systemd/system/nginx.service <<EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=/bin/rm -f ${NGINX_INSTALL_DIR}/logs/nginx.pid
ExecStartPre=${NGINX_INSTALL_DIR}/sbin/nginx -t
ExecStart=${NGINX_INSTALL_DIR}/sbin/nginx
ExecReload=/bin/kill -s HUP \$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nginx &> /dev/null
systemctl is-active nginx &> /dev/null || { color "nginx 啟動失敗,退出!" 1 ; exit; }
color "nginx 安裝完成" 0
}
check
install
八、任意編譯一個第3方nginx模塊,并使用
nginx-module-vts模塊實現(xiàn)流量監(jiān)控
nginx-module-vts模塊Github文檔鏈接

[root@Rocky ~]#cd /usr/local/src
[root@Rocky src]#wget https://github.com/vozlt/nginx-module-vts/archive/refs/tags/v0.2.1.tar.gz
[root@Rocky src]#tar xf v0.2.1.tar.gz
[root@Rocky src]#ls
nginx-1.22.1 nginx-1.22.1.tar.gz nginx-module-vts-0.2.1 v0.2.1.tar.gz
[root@Rocky src]#cd nginx-1.22.1/
[root@Rocky nginx-1.22.1]#nginx -V #查看Nginx已安裝的模塊
nginx version: nginx/1.23.2
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module
#添加新模塊--add-module=/usr/local/src/nginx-module-vts-0.2.1
[root@Rocky nginx-1.22.1]#./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --add-module=/usr/local/src/nginx-module-vts-0.2.1
[root@Rocky nginx-1.22.1]#make -j 2 && make install
http {
......
vhost_traffic_status_zone; #添加此行
......
server {
......
location /status {
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
}
......
}
}
:wq
[root@Rocky nginx-1.20.2]#systemctl restart nginx
添加監(jiān)控模塊前

添加監(jiān)控模塊后

