nginx做TCP轉發TCP代理轉發(以及應用層反向代理) 四層或七層負載均衡
20180626 Chenxin
場景:
- 大陸通過專線到日本,加快大陸用戶體驗感.需要搭建大陸和日本的代理轉發(客戶端->上海轉發服->日本轉發服->日本aws).
2.因歐洲,東南亞訪問北美游戲服延時較大.希望通過法蘭克福和新加坡的代理機轉發玩家請求給北美游戲服,降低延時.這樣公網直接走aws骨干鏈路,而不用通過internet的路由.
yum安裝失敗原因
yum版本nginx version: nginx/1.12.1失敗:
yum install nginx
yum安裝的,在配置stream的時候,啟動會報錯:
unknown directive "stream" in /etc/nginx/nginx.conf
也就是無stream模塊,故需要編譯安裝.
我們這里需要使用ngx_stream_core_module模塊(用於1.9及其以后版本)
注意事項:TCP代理,代理機會使用自己的端口跟后端機建立連接,應該會存在端口耗盡的問題,也就是最多只能有65535個鏈接保持.如果超過,需要想其他辦法.比如通過增加網卡接口的IP數量.
https://blog.csdn.net/libaineu2004/article/details/79104830 這里講解的比較深入.包括nginx代理轉發TCP.以及haproxy,https://blog.csdn.net/libaineu2004/article/details/79129684
編譯安裝
編譯環境准備
yum -y install gcc gcc-c++ autoconf automake
yum -y install zlib zlib-devel openssl openssl-devel pcre-devel
安裝 pcre庫是為了使 nginx 支持具備 URI 重寫功能的 rewrite 模塊,如果不安裝 pcre 庫,則 nginx 無法使用 rewrite 模塊功能。
nginx 在使用HTTPS服務的時候要用到此模塊,如果不安裝 openssl 相關包,安裝 nginx 的過程中會報錯。openssl 系統默認已經安裝,只需要安裝 openssl-devel 即可。
編譯,添加tcp支持
說明:參照官方說明,編譯參數中添加--with-steam即可,只有在configure時使用了--with-stream參數,編譯出來的nginx程序才支持stream方式實現TCP代理.
cd /opt
wget http://nginx.org/download/nginx-1.12.2.tar.gz
tar xzvf nginx-1.12.2.tar.gz
cd nginx-1.12.2
./configure --prefix=/usr/local/nginx --with-stream --with-http_stub_status_module
make
make install
配置文件
/usr/local/nginx/conf/nginx.conf
在末尾添加一個stream模塊(它和http等同級),這個模塊,類似於http和mail模塊,允許我們配置一組監聽TCP連接的服務。允許你配置多個服務的TCP連接,通過在upstream的server組中配置proxy_pass指令。
cat /usr/local/nginx/conf/nginx.conf
支持行后注釋
worker_processes auto;
worker_cpu_affinity auto;
error_log logs/error.log error;
pid logs/nginx.pid;
worker_rlimit_nofile 653600;
events {
worker_connections 653600; #(1)worker_connections 指定最大可以同時接收的連接數量,這里一定要注意,最大連接數量是和worker processes共同決定的。
multi_accept on; #(2)multi_accept 配置指定nginx在收到一個新連接通知后盡可能多的接受更多的連接
use epoll; #(3)use epoll 配置指定了線程輪詢的方法,如果是linux2.6+,使用epoll,如果是BSD如Mac請使用Kqueue
}
stream { #這里的stream為4層.如果是http則為7層的
upstream server80 {
hash $remote_addr consistent; # 保持與客戶端的對應關系
server ec2-107-23-101-62.compute-1.amazonaws.com:80 weight=1 max_fails=3 fail_timeout=10s; #weight 默認為1.weight越大,被分配到的概率就越大.這里也支持域名方式.
#server 172.16.1.22:80 weight=1 max_fails=3 fail_timeout=10s;
}
server {
listen 80; #(1)listen指定Nginx將在tcp 1884端口上監聽
proxy_connect_timeout 1s; #(2)proxy_connect_timeout指定Nginx與被代理的主機之間建立連接的超時時間。
proxy_timeout 30s; #(3)proxy_timeout指定Nginx與客戶端,以及Nginx與被代理的主機之間在兩個相鄰的讀或寫數據的操作之間的最大時間間隔。超過此時間間隔而沒有數據讀或寫操作發生,則斷開連接。--firecat個人建議時間設置長一點,否則tcp連接會斷開.這里默認是10分鍾.
proxy_pass server80; #(4)proxy_pass指定了被代理的主機的地址和端口號
}
upstream server8099 {
hash $remote_addr consistent;
server 52.53.76.253:8099 weight=1 max_fails=3 fail_timeout=10s;
}
server {
listen 8099;
proxy_connect_timeout 1s;
proxy_timeout 30s;
proxy_pass server8099;
}
}
檢查
編譯參數
/usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.12.2
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
configure arguments: --prefix=/usr/local/nginx --with-stream --with-http_stub_status_module
配置文件語法
/usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
:
管理
啟動
/usr/local/nginx/sbin/nginx
或者指定配置文件
/usr/local/nginx-02/sbin/nginx -c /usr/local/nginx-02/conf/nginx.conf
重啟
/usr/local/nginx/sbin/nginx -s reload
停止
/usr/local/nginx/sbin/nginx -s stop
/usr/local/nginx-02/sbin/nginx -s stop
或killall nginx
四層反向代理到此結束.
能否根據不同目錄分配到不同IP:PORT去
https://segmentfault.com/q/1010000004021226/a-1020000004021315
https://blog.csdn.net/rumengjian/article/details/80451711
開啟訪問日志
stream {
log_format main '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
access_log logs/access.log main;
upstream server9989 {
hash $remote_addr consistent;
server 192.168.1.16:9989 weight=1 max_fails=3 fail_timeout=10s;
}
server {
listen 9989;
proxy_connect_timeout 1s;
proxy_timeout 30s;
proxy_pass server9989;
}
}
session保持(七層) 或 始終連接后端固定某服務器(四層) (可以不看)
緣由:
根據客戶端所處位置,自動分配對應地理位置的戰斗服給它.
七層方式
參考: https://www.oschina.net/question/12_24613
這里只適用於HTTP模塊(ip_hash要配置在http塊里),不適用於stream模塊,會報[emerg] "ip_hash" directive is not allowed here
ip_hash(訪問ip)
每個請求按訪問ip的hash結果分配,這樣每個訪客固定訪問一個后端服務器,可以解決session的問題。
upstream favresin{
ip_hash;
server 10.0.0.10:8080;
server 10.0.0.11:8080;
}
其他說明
七層http有三種hash方式。
consistent_hash $remote_addr:可以根據客戶端ip映射
consistent_hash $request_uri: 根據客戶端請求的uri映射
consistent_hash $args:根據客戶端攜帶的參數進行映射.
四層方式(TCP代理 socket轉發)
可以通過stream方式,啟動多個端口來解決.
需要客戶端指定不同的端口.
stream {
log_format main '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
access_log logs/access.log main;
#第一套server
upstream server9989 {
hash $remote_addr consistent; #保持客戶端訪問后端固定某台服務器
server 18.182.73.153:9989 weight=1 max_fails=3 fail_timeout=10s;
}
server {
listen 9989;
proxy_connect_timeout 1s;
proxy_timeout 30s;
proxy_pass server9989;
}
#第二套server
upstream server9990 {
hash $remote_addr consistent;
server 18.182.73.153:9989 weight=1 max_fails=3 fail_timeout=10s;
}
server {
listen 9990;
proxy_connect_timeout 1s;
proxy_timeout 30s;
proxy_pass server9990;
}
}
配置示例(不用看)
2019/02/12
上海,日本 轉發服
上海
cat nginx.conf
worker_processes auto;
worker_cpu_affinity auto;
error_log logs/error.log error;
pid logs/nginx.pid;
worker_rlimit_nofile 653600;
events {
worker_connections 653600; #(1)worker_connections 指定最大可以同時接收的連接數量,這里一定要注意,最大連接數量是和worker processes共同決定的。
multi_accept on; #(2)multi_accept 配置指定nginx在收到一個新連接通知后盡可能多的接受更多的連接
use epoll; #(3)use epoll 配置指定了線程輪詢的方法,如果是linux2.6+,使用epoll,如果是BSD如Mac請使用Kqueue
}
stream {
log_format main '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
#access_log logs/access.log main;
#fight-match server-01
upstream server9989 {
hash $remote_addr consistent;
server 192.168.1.59:9989 weight=100 max_fails=3 fail_timeout=10s;
}
server {
listen 9989;
proxy_connect_timeout 1s;
proxy_timeout 30s;
proxy_pass server9989;
}
#fight-match server-02
#upstream server9990 {
# hash $remote_addr consistent;
# server 192.168.1.16:9990 weight=1 max_fails=3 fail_timeout=10s;
#}
#server {
# listen 9990;
# proxy_connect_timeout 1s;
# proxy_timeout 30s;
# proxy_pass server9990;
#}
#gateway
#upstream server9979 {
# hash $remote_addr consistent;
# server 192.168.1.59:9979 weight=100 max_fails=3 fail_timeout=10s;
#}
#server {
# listen 9979;
# proxy_connect_timeout 1s;
# proxy_timeout 30s;
# proxy_pass server9979;
#}
}
日本
cat nginx.conf
worker_processes auto;
worker_cpu_affinity auto;
error_log logs/error.log error;
pid logs/nginx.pid;
worker_rlimit_nofile 653600;
events {
worker_connections 653600; #(1)worker_connections 指定最大可以同時接收的連接數量,這里一定要注意,最大連接數量是和worker processes共同決定的。
multi_accept on; #(2)multi_accept 配置指定nginx在收到一個新連接通知后盡可能多的接受更多的連接
use epoll; #(3)use epoll 配置指定了線程輪詢的方法,如果是linux2.6+,使用epoll,如果是BSD如Mac請使用Kqueue
}
stream {
log_format main '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
#access_log logs/access.log main;
#fight-match server-01
upstream server9989 {
hash $remote_addr consistent;
#xinjiapo 這里不行,客戶端拿到A,而gameCenter可能分配的是B,會報1002
#server 13.229.15.29:9989 weight=1 max_fails=3 fail_timeout=10s;
#server 18.136.38.137:9989 weight=1 max_fails=3 fail_timeout=10s;
#riben
server 18.182.73.153:9989 weight=1 max_fails=3 fail_timeout=10s;
}
server {
listen 9989;
proxy_connect_timeout 1s;
proxy_timeout 30s;
proxy_pass server9989;
}
#fight-match server-02
#upstream server9990 {
# hash $remote_addr consistent;
# server 18.182.73.153:9989 weight=1 max_fails=3 fail_timeout=10s;
#}
#server {
# listen 9990;
# proxy_connect_timeout 1s;
# proxy_timeout 30s;
# proxy_pass server9990;
#}
#gateway
#upstream server9979 {
# hash $remote_addr consistent;
# server xbzj-taihe-bei-vpc-01-nlb-01-c7535ce71d33ace2.elb.us-east-1.amazonaws.com:9979 weight=100 max_fails=3 fail_timeout=10s;
#}
#server {
# listen 9979;
# proxy_connect_timeout 1s;
# proxy_timeout 30s;
# proxy_pass server9979;
#}
}