個人專題目錄
ngx_stream_core_module
該ngx_stream_core_module模塊自1.9.0版開始提供。默認情況下不構建此模塊,應使用--with-stream 配置參數(shù)啟用它。
官網:http://nginx.org/en/docs/stream/ngx_stream_core_module.html
示例配置
worker_processes auto; error_log /var/log/nginx/error.log info; #事件 events { worker_connections 1024; } #流模塊 stream { #上游后端 upstream backend { hash $remote_addr consistent; server backend1.example.com:12345 weight = 5; server 127.0.0.1:12345 max_fails = 3 fail_timeout = 30s; server unix:/ tmp / backend3; } #上游后端 upstream dns { server 192.168.0.1:53535; server dns.example.com:53; } server { listen 12345; proxy_connect_timeout 1s; proxy_timeout 3s; proxy_pass backend; } server { listen 127.0.0.1:53 udp reuseport; proxy_timeout 20s; proxy_pass dns; } server { listen [::1]:12345; proxy_pass unix:/tmp/stream.socket; } }
指令
listen address:port [ssl] [udp] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];設置服務器將接受連接的套接字
address和port。可以僅指定端口。地址也可以是主機名,例如:
listen 127.0.0.1:12345; listen *:12345; listen 12345; # same as *:12345 listen localhost:12345;
IPv6地址在方括號中指定:
listen [::1]:12345; listen [::]:12345;
UNIX域套接字使用“ unix:”前綴指定:
listen unix:/var/run/nginx.sock;
該ssl參數(shù)允許指定此端口上接受的所有連接都應在SSL模式下工作。
該udp參數(shù)配置一個偵聽套接字以處理數(shù)據報(1.9.13)。
的proxy_protocol參數(shù)(1.11.4)允許指定這個端口上接受的所有連接應使用 代理服務器協(xié)議。
自版本1.13.11起支持PROXY協(xié)議版本2。
該listen指令可以有幾個特定于與套接字相關的系統(tǒng)調用的附加參數(shù)。
-
backlog=number設置調用中的
backlog參數(shù),該參數(shù)listen()限制掛起連接隊列的最大長度(1.9.2)。默認情況下,backlog在FreeBSD,DragonFly BSD和macOS上設置為-1,在其他平臺上設置為511。 -
rcvbuf=size設置
SO_RCVBUF偵聽套接字的接收緩沖區(qū)大?。ㄟx項)(1.11.13)。 -
sndbuf=size設置
SO_SNDBUF偵聽套接字的發(fā)送緩沖區(qū)大小(選項)(1.11.13)。 -
bind此參數(shù)指示對
bind()給定地址進行單獨調用address:port。事實是,如果有多個listen指令具有相同的端口但地址不同,并且其中一個listen指令偵聽給定端口(*:port)的所有地址,則nginx將bind()僅執(zhí)行*:port。應該注意,getsockname()在這種情況下將進行系統(tǒng)調用以確定接受連接的地址。如果使用ipv6only或so_keepalive參數(shù),那么對于給定的address:port對bind()將始終進行單獨的調用。 -
ipv6only=on|off此參數(shù)確定(通過
IPV6_V6ONLY套接字選項)偵聽通配符地址的IPv6套接字是[::]僅接受IPv6連接還是僅接受IPv6和IPv4連接。默認情況下,此參數(shù)處于啟用狀態(tài)。它只能在開始時設置一次。 -
reuseport此參數(shù)(1.9.1)指示為每個工作進程創(chuàng)建一個單獨的偵聽套接字(使用
SO_REUSEPORTLinux 3.9+和DragonFly BSD上的 套接字選項,或者SO_REUSEPORT_LB在FreeBSD 12+上),允許內核在工作進程之間分配傳入連接。目前僅適用于Linux 3.9 +,DragonFly BSD和FreeBSD 12+(1.15.1)。不恰當?shù)厥褂么诉x項可能會產生安全 隱患。 -
so_keepalive=on|off| [keepidle]:[keepintvl]:[keepcnt]此參數(shù)配置偵聽套接字的“TCP keepalive”行為。如果省略此參數(shù),則操作系統(tǒng)的設置將對套接字有效。如果將其設置為值“
on”,SO_KEEPALIVE則為套接字打開選項。如果將其設置為值“off”,SO_KEEPALIVE則為套接字關閉該選項。在每個插槽的基礎使用的TCP?;顓?shù)某些操作系統(tǒng)支持設置TCP_KEEPIDLE,TCP_KEEPINTVL和TCP_KEEPCNT套接字選項。在這樣的系統(tǒng)(目前,Linux的2.4 +,NetBSD的5+和FreeBSD 9.0-STABLE),它們可以使用配置的keepidle,keepintvl和keepcnt參數(shù)??梢允÷砸粋€或兩個參數(shù),在這種情況下,相應套接字選項的系統(tǒng)默認設置將生效。例如,SO_KEEPALIVE =30m::10將idle timeout(TCP_KEEPIDLE)設置為30分鐘,將探測間隔(TCP_KEEPINTVL)保留為系統(tǒng)默認值,并將探測count(TCP_KEEPCNT)設置為10個探測器。
不同的服務器必須監(jiān)聽不同的 address:port對。
語法
| Syntax | Default | Context | Description |
|---|---|---|---|
preread_buffer_size size
|
16k | stream,server | 指定size了的 預讀緩沖區(qū)。 |
preread_timeout timeout
|
30s | stream,server | 指定timeout了的 預讀階段。 |
proxy_protocol_timeout timeout
|
30s | stream,server | 指定timeout用于讀取PROXY協(xié)議標頭以完成。如果在此時間內未傳輸整個標頭,則關閉連接。 |
resolver address ... [valid=time][ipv6=on
|
off |
- | stream,server 將用于解析上游服務器名稱的名稱服務器配置到地址中,例如:resolver 127.0.0.1 [:: 1]:5353; |
resolver_timeout time
|
30s | stream,server | 設置名稱解析的超時 |
| server { ... } | - | stream | 設置服務器的配置 |
| stream { ... } | - | main | 提供指定流服務器指令的配置文件上下文 |
| tcp_nodelay on | off | on | stream,server | 啟用或禁用該TCP_NODELAY選項的使用。為客戶端和代理服務器連接啟用該選項 |
variables_hash_bucket_size size
|
64 | stream | 設置變量哈希表的桶大小。設置哈希表的詳細信息在單獨的文檔中提供 。 |
variables_hash_max_size size
|
1024 | stream | 設置size變量哈希表的最大值。設置哈希表的詳細信息在單獨的文檔中提供。 |
可以將地址指定為域名或IP地址,以及可選端口。如果未指定端口,則使用端口53。以循環(huán)方式查詢名稱服務器。
默認情況下,nginx將在解析時查找IPv4和IPv6地址。如果不需要查找IPv6地址,則ipv6=off可以指定參數(shù)。
默認情況下,nginx使用響應的TTL值緩存答案。可選valid參數(shù)允許覆蓋它:
resolver 127.0.0.1 [::1]:5353 valid=30s;
嵌入式變量
該ngx_stream_core_module模塊支持自1.11.2以來的變量。
-
$binary_remote_addr客戶端地址采用二進制形式,值的長度始終為IPv4地址的4個字節(jié)或IPv6地址的16個字節(jié)
-
$bytes_received從客戶端收到的字節(jié)數(shù)(1.11.4)
-
$bytes_sent發(fā)送到客戶端的字節(jié)數(shù)
-
$connection連接序列號
-
$hostname主機名
-
$msec以毫秒為單位的當前時間(以毫秒為單位)
-
$nginx_versionnginx版本
-
$pid工作進程的PID
-
$protocol用于與客戶端溝通的協(xié)議:
TCP或UDP(1.11.4) -
$proxy_protocol_addr來自PROXY協(xié)議頭的客戶端地址,否則為空字符串(1.11.4)必須先通過
proxy_protocol在listen指令中設置參數(shù)來啟用PROXY協(xié)議 。 -
$proxy_protocol_port來自PROXY協(xié)議頭的客戶端端口,否則為空字符串(1.11.4)必須先通過
proxy_protocol在listen指令中設置參數(shù)來啟用PROXY協(xié)議 。 -
$remote_addr客戶端地址
-
$remote_port客戶端端口
-
$server_addr接受連接的服務器的地址計算此變量的值通常需要一次系統(tǒng)調用。為避免系統(tǒng)調用,listen指令必須指定地址并使用該
bind參數(shù)。 -
$server_port接受連接的服務器的端口
-
$session_time會話持續(xù)時間(以秒為單位),分辨率為毫秒(1.11.4);
-
$status會話狀態(tài)(1.11.4),可以是以下之一:
200會話成功完成400無法解析客戶端數(shù)據,例如PROXY協(xié)議頭403例如,當某些客戶端地址的訪問受限時,禁止訪問500內部服務器錯誤502壞網關,例如,如果無法選擇或到達上游服務器。503服務不可用,例如,當訪問受連接數(shù)限制時 -
$time_iso8601當?shù)貢r間采用ISO 8601標準格式
-
$time_local通用日志格式的本地時間
測試nginx代理TCP協(xié)議的配置
realserver : 10.111.17.89:8080
nginx :10.111.16.75
客戶端:10.100.34.198
TCP監(jiān)聽端口:2018
配置nginx
nginx1.90對TCP協(xié)議的代理并不是默認開啟的,需要在編譯的時候配置 --with-stream 參數(shù):
./configure --add-module=/root/nginx_upstream_check_module-master --with-stream
make && make install
nginx.config文件參照官網:
stream {
upstream tcpend {
hash $remote_addr consistent;
server 10.111.17.89:8080 weight=5 max_fails=3 fail_timeout=30s;
}
server {
listen 2018;
proxy_connect_timeout 1s;
proxy_timeout 180s;
proxy_pass tcpend;
}
}
啟動nginx,發(fā)現(xiàn)nginx已經開始監(jiān)聽2018端口了
cd usr/local/nginx/sbin
#啟動
./nginx
#重啟
./nginx -s reload
#判斷配置文件是否正確
./nginx -t
netstat -anp|grep :2018
[root@vm10-111-16-75 ~]# netstat -anp|grep :2018
tcp 0 0 0.0.0.0:2018 0.0.0.0:* LISTEN 18457/nginx
測試客戶端連realserver
在客戶端通過telnet連接realserver的2018端口:
telnet
open 10.111.17.89 8080
[root@vm10-65-140-249 ~]# telnet
telnet> open 10.111.17.89 8080
Trying 10.111.17.89...
Connected to 10.111.17.89.
Escape character is '^]'.
Connection closed by foreign host.
[root@vm10-65-140-249 ~]# telnet
telnet> open 10.111.17.89 8080
Trying 10.111.17.89...
Connected to 10.111.17.89.
Escape character is '^]'
在realserver上查看網絡連接:
netstat -anpl|grep :8080
[root@vm10-111-17-89 ~]# netstat -anpl|grep :8080
tcp 0 0 :::8080 :::* LISTEN 5182/java
tcp 0 0 ::ffff:10.111.17.89:8080 ::ffff:10.100.34.198:14470 ESTABLISHED 5182/java
可以正常連接
測試客戶端連接nginx
在客戶端通過telnet連接nginx所在服務器的2018端口
telnet
open 10.111.16.75 2018
[root@vm10-65-140-249 ~]# telnet
telnet> open 10.111.16.75 2018
Trying 10.111.16.75...
Connected to 10.111.16.75.
Escape character is '^]'.
在nginx機器上查看網絡連接
[root@vm10-111-16-75 ~]# netstat -anp|grep :2018
tcp 0 0 0.0.0.0:2018 0.0.0.0:* LISTEN 18457/nginx
tcp 0 0 10.111.16.75:2018 10.100.34.198:51539 ESTABLISHED 18458/nginx
在realserver上查看網絡連接
[root@vm10-111-17-89 ~]# netstat -anpl|grep :8080
tcp 0 0 :::8080 :::* LISTEN 5182/java
tcp 0 0 ::ffff:10.111.17.89:8080 ::ffff:10.111.16.75:40794 ESTABLISHED 5182/java
nginx是給做了一個TCP連接的中轉。
client和nginx有一個tcp長連接,nginx和realserver有一個tcp長連接,但是client和realserver之間并沒有tcp長連接,僅由nginx服務器負責數(shù)據中轉。
四層七層負載的區(qū)別
1. 什么是負載均衡
負載均衡 建立在現(xiàn)有網絡結構之上,它提供了一種廉價有效透明的方法擴展網絡設備和服務器的帶寬、增加吞吐量、加強網絡數(shù)據處理能力、提高網絡的靈活性和可用性。
2. 負載均衡分類
負載均衡根據所采用的設備對象(軟/硬件負載均衡),應用的OSI網絡層次(網絡層次上的負載均衡),及應用的地理結構(本地/全局負載均衡)等來分類。根據應用的 OSI 網絡層次來分類的兩個負載均衡類型。
網絡模型圖,包含了 OSI 模型及 TCP/IP 模型,兩個模型雖然有一點點區(qū)別,但主要的目的是一樣的,模型圖描述了通信是怎么進行的。它解決了實現(xiàn)有效通信所需要的所有過程,并將這些過程劃分為邏輯上的層。層可以簡單地理解成數(shù)據通信需要的步驟。

根據負載均衡所作用在 OSI 模型的位置不同,負載均衡可以大概分為以下幾類:
-
二層負載均衡(mac)
根據OSI模型分的二層負載,一般是用虛擬mac地址方式,外部對虛擬MAC地址請求,負載均衡接收后分配后端實際的MAC地址響應。
-
三層負載均衡(ip)
一般采用虛擬IP地址方式,外部對虛擬的ip地址請求,負載均衡接收后分配后端實際的IP地址響應。
-
四層負載均衡(tcp)
在三層負載均衡的基礎上,用ip+port接收請求,再轉發(fā)到對應的機器。
-
七層負載均衡(http)
根據虛擬的url或IP,主機名接收請求,再轉向相應的處理服務器。
在實際應用中,比較常見的就是四層負載及七層負載。這里也重點說下這兩種負載。
3. 四層負載均衡(基于IP+端口的負載均衡)
所謂四層負載均衡,也就是主要通過報文中的目標地址和端口,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。

- 在三層負載均衡的基礎上,通過發(fā)布三層的IP地址(VIP),然后加四層的端口號,來決定哪些流量需要做負載均衡,對需要處理的流量進行NAT處理,轉發(fā)至后臺服務器,并記錄下這個TCP或者UDP的流量是由哪臺服務器處理的,后續(xù)這個連接的所有流量都同樣轉發(fā)到同一臺服務器處理。
- 以常見的TCP為例,負載均衡設備在接收到第一個來自客戶端的SYN 請求時,即通過上述方式選擇一個最佳的服務器,并對報文中目標IP地址進行修改(改為后端服務器IP),直接轉發(fā)給該服務器。TCP的連接建立,即三次握手是客戶端和服務器直接建立的,負載均衡設備只是起到一個類似路由器的轉發(fā)動作。在某些部署情況下,為保證服務器回包可以正確返回給負載均衡設備,在轉發(fā)報文的同時可能還會對報文原來的源地址進行修改。
- 對應的負載均衡器稱為四層交換機(L4 switch),主要分析IP層及TCP/UDP層,實現(xiàn)四層負載均衡。此種負載均衡器不理解應用協(xié)議(如HTTP/FTP/MySQL等等)
要處理的流量進行NAT處理,轉發(fā)至后臺服務器,并記錄下這個TCP或者UDP的流量是由哪臺服務器處理的,后續(xù)這個連接的所有流量都同樣轉發(fā)到同一臺服務器處理。 - 實現(xiàn)四層負載均衡的軟件有:
- F5:硬件負載均衡器,功能很好,但是成本很高。
- lvs:重量級的四層負載軟件
- nginx:輕量級的四層負載軟件,帶緩存功能,正則表達式較靈活
- haproxy:模擬四層轉發(fā),較靈活
4. 七層的負載均衡(基于虛擬的URL或主機IP的負載均衡)
所謂七層負載均衡,也稱為“內容交換”,也就是主要通過報文中的真正有意義的應用層內容,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。

- 在四層負載均衡的基礎上(沒有四層是絕對不可能有七層的),再考慮應用層的特征,比如同一個Web服務器的負載均衡,除了根據VIP加80端口辨別是否需要處理的流量,還可根據七層的URL、瀏覽器類別、語言來決定是否要進行負載均衡。舉個例子,如果你的Web服務器分成兩組,一組是中文語言的,一組是英文語言的,那么七層負載均衡就可以當用戶來訪問你的域名時,自動辨別用戶語言,然后選擇對應的語言服務器組進行負載均衡處理。
- 以常見的TCP為例,負載均衡設備如果要根據真正的應用層內容再選擇服務器,只能先代理最終的服務器和客戶端建立連接(三次握手)后,才可能接受到客戶端發(fā)送的真正應用層內容的報文,然后再根據該報文中的特定字段,再加上負載均衡設備設置的服務器選擇方式,決定最終選擇的內部服務器。負載均衡設備在這種情況下,更類似于一個代理服務器。負載均衡和前端的客戶端以及后端的服務器會分別建立TCP連接。所以從這個技術原理上來看,七層負載均衡明顯的對負載均衡設備的要求更高,處理七層的能力也必然會低于四層模式的部署方式。
- 對應的負載均衡器稱為七層交換機(L7 switch),除了支持四層負載均衡以外,還有分析應用層的信息,如HTTP協(xié)議URI或Cookie信息,實現(xiàn)七層負載均衡。此種負載均衡器能理解應用協(xié)議。
- 實現(xiàn)七層負載均衡的軟件有:
- haproxy:天生負載均衡技能,全面支持七層代理,會話保持,標記,路徑轉移;
- nginx:只在http協(xié)議和mail協(xié)議上功能比較好,性能與haproxy差不多;
- apache:功能較差
- Mysql proxy:功能尚可。
5. 區(qū)別
| 區(qū)別 | 四層負載均衡(layer 4) | 七層負載均衡(layer 7) |
|---|---|---|
| 基于 | 基于IP+Port的 | 基于虛擬的URL或主機IP等。 |
| 類似于 | 路由器 | 代理服務器 |
| 握手次數(shù) | 1 次 | 2次 |
| 復雜度 | 低 | 高 |
| 性能 | 高;無需解析內容 | 中;需要算法識別 URL,Cookie 和 HTTP head 等信息 |
| 安全性 | 低,無法識別 DDoS等攻擊 | 高, 可以防御SYN cookie以SYN flood等 |
| 額外功能 | 無 | 會話保持,圖片壓縮,防盜鏈等 |