Nginx在1.9.0的时候,增加了一个 stream 模块,用来实现四层协议(网络层和传输层)的转发、代理、负载均衡等。stream模块的用法跟http的用法类似,允许我们配置一组TCP或者UDP等协议的监听,然后通过proxy_pass来转发我们的请求,通过upstream添加多个后端服务,实现负载均衡,下面我们从基础网络模型讲起:
1.网络模型
在前面的章节中,我们知道,网络的七层协议是这样的,详细的内容可以参考文章:《网络七层协议,四层协议,五层协议?》:
OSI中的层 | 功能 | TCP/IP协议族 |
应用层 | 文件传输、电子邮件、文件服务、虚拟终端 | TFTP、HTTP、SNMP、FTP、SMTP、DNS、RIP、Telnet |
表示层 | 数据格式化、代码转换、数据加密 | 没有协议 |
会话层 | 接触或建立与别的节点联系 | 没有协议 |
传输层 | 提供端对端的接口 | TCP、UDP |
网络层 | 为数据包选择路由 | IP、ICMP、OSPF、BGP、IGMP、ARP、RARP |
数据链路层 | 传输有地址的帧以及错误检测功能 | SLIP、CSLIP、PPP、MTU、ARP、RARP |
物理层 | 以二进制数据形式在物理媒体上传输数据 | ISO2110、IEEE802、IEEE802.2 |
说到网络协议,很容易就会抛出一个问题,这些网络服务通过什么机制去实现的?
答:Socket
- Socket就是为网络服务提供的一种机制。
- 通讯的两端都有Sokcet
- 网络通讯其实就是Sokcet间的通讯
- 数据在两个Sokcet间通过IO传输。
既然端对端的网络通讯是通过Socket IO传输的,那么它们是通过什么传输的呢?没错就是通过TCP或者UDP传输的:
UDP:
- 是面向无连接, 将数据及源的封装成数据包中,不需要建立连接。
- 每个数据报的大小在限制64k内。
- 因无连接,是不可靠协议。
- 不需要建立连接,速度快。
TCP:
- 建议连接,形成传输数据的通道。
- 在连接中进行大数据量传输,以字节流方式。
- 通过三次握手完成连接,是可靠协议。
- 必须建立连接效率会稍低。
从网络的七层协议中,可以看到TCP和UDP使用用于传输层的,而HTTP是用于应用层的。可以看出HTTP协议是基于TCP协议封装成超文本传输协议,HTTP分为请求和响应,HTTP协议分为请求参数和方法类型、请求头、请求体,响应分为 响应状态、响应头、响应体等。(HTTP我们常用到,此处就不再详细讲解了)。
到这里,要回归到本文的主题了,本文主要讲解的是如何基于Nginx1.9实现四层负载均衡。
先理解两个概念"四层负载均衡"和"七层负载均衡":
四层负载均衡: 在网络模型中的传输层中,基于主要是基于tcp协议报文实现负载均衡(比如LVS
、haproxy
就是四层负载均衡器),使用改写报文的源地址和目的地址。
七层负载均衡: 在网络模型中应用层中,基于URL或者HTTP协议实现负载均衡,Web服务器。
2.环境安装
1.下载Nginx( 作用:实现反向代理、负载负载库)
wget http://nginx.org/download/nginx-1.9.10.tar.gz
2.下载nginx_tcp_proxy_module 插件 (nginx 支持TCP转发和负载均衡的支持)
wget https://github.com/yaoweibin/nginx_tcp_proxy_module/tarball/master
3.解压Nginx
tar -zxvf nginx-1.9.10.tar.gz
4.解压nginx_tcp_proxy_module 插件
tar -zxvf master
5.进入Nginx解压目录,下载tcp.patch最新补丁
cd nginx-1.9.10 patch -p1 < ../yaoweibin-nginx_tcp_proxy_module-b8a3028/tcp.patch
如果报错:"-bash: patch: 未找到命令" 执行:
yum -y install patch
5.配置Nginx
./configure --add-module=../yaoweibin-nginx_tcp_proxy_module-b8a3028
6.编译Nginx
make && make install
如果报错:
In file included from …/nginx_tcp_proxy_module-master/ngx_tcp.h:32,
from …/nginx_tcp_proxy_module-master/ngx_tcp.c:5:
…/nginx_tcp_proxy_module-master/ngx_tcp_upstream.h:144: error: expected specifier-qualifier-list before ‘ngx_resolver_addr_t’
make[1]: *** [objs/addon/nginx_tcp_proxy_module-master/ngx_tcp.o] Error 1
make[1]: Leaving directory `/opt/apps_install/nginx-1.9.9’
make: *** [build] Error 2
修改第三方模块包里的头文件,ngx_tcp_upstream.h 144 行将ngx_resolver_addr_t 改为 ngx_addr_t
cd /usr/local/yaoweibin-nginx_tcp_proxy_module-b8a3028 vi ngx_tcp_upstream.h
7.继续 make && make install
这里的tcp_proxy_module好像出问题了,问题还没解决,如果解决了的小伙伴可以私信我 ! 为了不影响整体思路,直接看下一步:
8.修改nginx.conf配置文件
worker_processes 1; events { worker_connections 1024; } ### 修改为TCP模块 tcp { ### 定义多个上游服务器 upstream xxx{ ### 定义TCP模块上游服务器 server 192.168.5.165:80001; server 192.168.5.165:80002; } server { listen 9999; server_name 192.168.212.137; ### 反向代理upstream proxy_pass xxx; } }
3.测试
1.启动Nginx服务器
./nginx
2.使用TCP/UDP测试工具(网上搜,这里使用的是myfiles_TCPUDPDebug102_Setup.exe
)新增两个服务端,分别为192.168.5.165:80001和192.168.5.165:80002:
3.Ngxin连接反向代理TCP服务器
效果:
- 连接Nginx服务器 192.168.212.138:9999,会立刻反向代理给192.168.5.165:8001,8001会自动连接连接的时候进行反向代理。
- 断开连接后,连接Nginx服务器 192.168.212.138:9999,会立刻反向代理给192.168.5.165:8002
- 断开连接192.168.212.138:9999轮流操作,8001和8002也会轮流连接(轮询算法)
自动连接到192.168.5.165:8002:
连接成功后就可以相互的发送消息了。
总结