TCP 的 負載均衡
這個片段描述了如何通過nginx plus進行負載均衡
在版本5中,nginx plus 能夠代理和負載均衡通過TCP路徑,TCP對於一些流行應用和服務是一個協議:LDAP、MYSQL、RTMP
stream 模塊
TCP 負載均衡被nginx的三個模塊所實現,而且這些模塊被嵌入在nginx plus中。
它們定義的命令是在stream配置塊中:
- ngx_stream_core_module :定義基本的命令來激活這個TCP通信過程
- ngx_stream_proxy_module :定義這個命令是為了進行TCP代理通信
- ngx_stream_upstream_module :定義這個命令是為了TCP的負載均衡的
先決條件
- nginx plus 版本5(具備基本功能)或者版本6(在這個文章有描述的功能)
- 一個應用、數據庫、服務進行通信都是通過TCP的方式
- 負載均衡服務中的每個服務都需要運行一個實例
配置TCP負載均衡
負載均衡涉及到了高效的分發網絡到后台服務,要配置負載均衡,需要執行下面的技術:
- 創建最高級別的stream(與http同一級別)上下文在nginx plus配置當中。
- 定義一個upstream組,由多個服務組成達到負載均衡
- 定義一個服務用來監聽TCP連接,並且把他們代理到一個upstream組中
- 配置負載均衡的方法和參數為每個server;配置些如:連接數、權重、等等
創建一個upstream組
首先創建一個server組,用來作為TCP負載均衡組。定義一個upstream塊在stream上下文中
在這個塊里面添加由server命令定義的server,指定他的IP地址和主機名(能夠被解析成多地址的主機名),和端口號。注意:你不能為每個server定義協議,因為這個stream命令建立TCP作為整個
server的協議了。下面的例子是建立一個被稱之為stream_backend組,兩個監聽12345端口的server
,一個監聽12346端口。
stream {
upstream stream_backend {
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
}
下面的片段中,你定義每個server為單獨的組中。然后你能自定義upstream組的配置,而這些
組是通過負載均衡的算法來進行分組的,或者是能健康的管理。. See
Choosing a Load Balancing Method和后續的片段.
TCP的代理通信
配置反向代理使nginx plus能夠把TCP請求從一個客戶端轉發到負載均衡組中。在每個server配置塊中
通過每個虛擬server的server的配置信息和在每個server中定義的監聽端口的配置信息和proxy_passs
命令把TCP通信發送到哪個server中去。
stream {
server {
listen 12345;
proxy_pass stream_backend;
}
}
一個另類的方式是代理TCP通信到單一的server中而不是server組中。
假如你的server的唯一標識是通過主機,而且你的主機名是可以解析成多個IP地址的話,然而nginx的負載均衡通信通過使用round-robin算法得到的IP方式。在這種情況下,你必須還要附加端口號來標識到底哪個server來處理的。
stream {
server {
listen 12345;
proxy_pass backend4.example.com:12345;
}
}
改變負載均衡的方法
默認nginx plus是通過輪詢算法來進行負載均衡的通信的。引導這個請求循環的到配置在upstream組中server端口上去。
因為他是默認的方法,這里沒有輪詢命令,只是簡單的創建一個upstream配置組在這兒stream山下文中,而且在其中添加server。
upstream backend {
server backnd1.example.com:12345 weight;
server backedn2.example.com:12345;
server backend3.example.com:12345;
}
配置不同的負載均衡的算法,囊括在upstream配置塊中。
- least-connected :對於每個請求,nginx plus選擇當前連接數最少的server來處理
upstream stream_backend {
least_conn;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
2.
least time :對於每個鏈接,nginx pluns 通過幾點來選擇server的:
- 最底平均延時:通過包含在least_time命令中指定的參數計算出來的:
- connect:連接到一個server所花的時間
- first_byte:接收到第一個字節的時間
- last_byte:全部接收完了的時間
- 最少活躍的連接數
upstream stream_backend {
least_time first_byte;
server backend1.exmaple.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
3. 普通的hash算法:nginx plus選擇這個server是通過user_defined 關鍵字,就是IP地址:$remote_addr;
upstream stream_backend {
hash $remote_addr consistent;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346;
}
這個可選的consistent參數應用這個一致性hash算法,這種方法能減少使由於server添加或者刪除導致的關鍵字映射到其他服務器上的可能性。
配置session的持久化
配置session的持久化使用hash負載均衡的方式在前面已經描述了。因為hash函數是建立在客戶端的IP地址上的,所以TCP請求從一個到同樣一個server是非常可能的,除非這個server不可用了
限制連接數
可以設置nginx plus與server所建立的連接數:server max_conns=?
upstream stream_backend {
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345;
server backend3.example.com:12346 max_conns=4;
}
不好的健康監測
假如連接一個server超市了或者導致一個錯誤,nginx plus標識這個server是無效的和阻止請求到那個server上去,在一段時間內。下面的參數是用來判斷哪些server才算是不可達的:
- fail_timeout :在這個時間段中進行了多少次連接的嘗試失敗了,那么就認為是不可達了並標記不可達
- max_fails:和上面是對應上的。
默認是在10秒鍾進行1次嘗試。在10秒進行至少一次嘗試是失敗的,那么nginx則認為這個server是不可達的
下面的例子中要求是:30s進行2次嘗試失敗認為server不可達
upstream stream_backend {
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fails=2 fail_timout=30; //當個server的不健康的監測
server backend3.example.com:12346 max_conns=4;
}
好的健康監測
當你進行健康監測的時,nginx plus平凡的進行TCPupstream的server的測試通過響應為了避免失敗。
健康監測可以配置成監測失敗類型的范圍。
how it works?
nginx plus 發送一個健康監測請求到每個TCP upstream server中去,監測響應是否滿足這個指定的條件,假如一個連接不能連接到某個server當中去,這個健康監測就會失敗,這個server將會被考慮成不監控了。nginx plus就不會代理客戶端連接到不健康的server中去,假如幾個server被監測為健康的,那么相反的server就是不健康的了
先決條件:
- 你已經定義了一組server在stream上下文中:例如:
stream {
upstream stream_backend {
server backend1.example.com:12345;
server backend2.example.com:12345;
server backend3.example.com:12345;
}
}
- 你也做好了定義一個TCP連接的代理server
server {
listen 12345;
proxy_pass stream_backend;
}
基本的配置
- 添加一個zone命令在upstream中,這個zone定義的大小是用來給worker processes存放connections和counters用的
stream {
upstream stream_backend {
zone stream_backend 64k;
server backend1.exmaple.com:12345;
..........
}
} - 添加 health_check and health_check_timeout命令到代理的server中去、
server {
listen 12345;
proxy_pass strean_backend;
health_check;
health_check_timeout 5s;
}
這個health_check命令將會激活這個健康監測功能,當又health_check_timeout 將會覆蓋掉這個proxy_timeout的值,
作為健康監測超時時間應該是顯著縮短。
fine-tuning 健康監測
默認,nginx plus試着再每5s中連接每個server在upstream server組中。假如連接不能夠被建立,nginx plus認為這個健康監測失敗,標識他為不健康。停止連接該server。
改變默認的行為,包括的參數如下:
- interval :多少秒會發送健康請求
- passses : 多少連續的響應才算被考慮為健康的
- fails :多少次連續的失敗響應才考慮為不健康的
server {
listen 12345;
proxy_pass stream_backend;
health_check insterval=10 passes=2 fails=3; //整體server檢測
}
在這個例子中這個時間周期變成了10s;三次連續無響應被考慮為不健康,假如連續兩次檢測正常可能為server正常
fine-tuning health check with the macth configuration block
定義一些測試的種類去驗證server響應從而達到server是否健康,定義這些種類在一個match的配置塊中
這個match在stream上下文中;
使用下面的參數在match塊中是需要的目的為了health_check而定制的條件
- send :發送到server的字符創
- expect :返回的數據必須匹配這個正則表達式
這些參數可以隨意的組合,但是不會超過一個send或者一個expect參數同一時間內,下面是這兩個參數的搭配:
- 既沒有send也沒有expect參數被指定。連接server的能力是測試的
- 指定了expect,然后server被期待無條件的發送一條數據過來
match pop3 {
expect ~*"\+OK";
} - send被指定,然后期待連接將會成功的建立,指定的字符串會被發送到server端
match pop_quit {
send QUIT;
} - 假如兩個都有,那么這個發送參數返回的值必須匹配這個expect指定的正則
stream {
upstream stream_backend {
zone upstream_backend 64k;
server backend1.example.com:12345;
}
match http {
send "GET / HTTP/1.0\r\nHost:localhost\r\n\r\n"
expect ~*"200 OK";
}
server {
listen 12345;
health_check match=http;
proxy_pass stream_backend;
}
}
運行時的重新配置
upstream 服務組能夠非常容易的重配在運行的時候通過一個簡單的http接口,使用這個接口,你將會能夠
看到所有的服務,某個服務的詳細信息,或者對server的增刪。
為了能夠在運行時重配,你需要如下條件:
授予訪問upstream_conf handler -a 特殊的handler權限;handler能夠檢查和重配upstream組在nginx plus中。作如上的操作需要在http 快中,使用upstream_conf命令 在一個分開的location中
對於訪問這個location需要限定。
http {
server {
location /upstream_conf {
upstream_conf;
allow 127.0.0.1; #permit access from localhost
deny all;#deny; access from everywhere else
}
}
}
在這個stream塊中,指定zone對於這個server組來說需要;這個命令將會創建一個zone大小的在共享內存當中,在里面保存了server組的配置;這樣所有的workprocesses就能夠共享同一個配置了。
stream {
...
#Configuration of an upstream server group
upstream appservers {
zone appservers 64k;
server appserv1.example.com:12345 weight=5;
server appserv2.example.com:12345 fail_timeout=5s;
server backup1.example.com:12345 backup;
server backup2.example.com:12345 backup;
}
server {
#server that proxies connections to the upstream
proxy_pass appservers;
lealth_check;
}
}
http {
...
server {
#location for configuration requests
location /upstream_conf {
upstream_conf;
allow 127.0.0.1;
deny all;
}
}
}
這里,想訪問這個location只有是本地的IP才可以,而其他的IP都被屏蔽了。想發送一個配置命令到nginx中,發送一個http請求可以帶很多配置信息。這個請求應該應該有一個適合的uri進入到包含了upstream_conf的location中,這個請求應該包括了設置server組的upstream的參數。
例如:查看所有的備份server,對於這server來說就是:http://127.0.0.1/upstream_conf?stream=&upstream=appservers&backp=
增加一個新的server到組中,發送一個請求攜帶了add和server參數:http://127.0.0.1/upstream_conf?stream=&add=&upstream=appservers&server=appserv3.example.com:12345&weight=2&max_fails=3
移除一個server,發送一個請求攜帶remove命令和server唯一標識的參數ID
去修改一個特定的server參數,發送一個請求攜帶ID和參數信息
tcp load balancing 配置例子
這個配置例子是TCP負載均衡的例子在nginx plus中的
stream {
upstream stream_backend {
least_conn;
server backend1.example.com:12345 weight=5;
server backend2.example.com:12345 max_fail=2 fail_timeout=30s;
server backend3.example.com:12346 max_conns =3;
}
server {
listen 12345;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxypass stream_backend ;
}
server {
listen 12346;
proxy_pass backend4.example.com:12346;
}
}
在這個例子中,有兩個servers 他們被定義在server塊中。所有的TCP代理相關的函數都被定義在stream塊中像http塊一樣對待http請求的處理。
這第一個server監聽12345端口而且代理所有的TCP連接到這個被命令為backend組中server。注意這個proxy_pass命令定義
這個stream模塊的上下文必須不包含協議。這兩個可選的timeout參數被指定如下含義:proxy_connect_timeout設置建立一個連接與某個server的請求的超時時間,而proxy_time是代理已經建立之后的超時時間。
這個backend組由三個運行同樣內容的,每個server命令后綴一個固定的端口號。連接被分配到每個server中去,而這種分配方式是:最少連接數。
這第二個虛擬server監聽在12346端口號上,並且代理TCP連接到backend4邏輯server上,這個server或許被解析到一個serverIP上,而且這個地址將會做輪詢的方式負載均衡。