基本原理
任何的负载均衡技术都要想办法建立某种一对多的映射机制:一个请求的入口映射到多个处理请求的节点,从而实现分而治之(Divide and Conquer)。
DNS负载均衡
现在存在很多智能DNS,可以实现一些简单的调度算法,如轮训、权重等
例如 阿里DNS云解析
四层负载均衡
LVS/HaProxy
七层负载均衡
HaProxy/Nginx
DNS轮询是最简单的负载均衡方式。以域名作为访问入口,通过配置多条DNS A记录使得请求可以分配到不同的服务器。缺点是DNS生效时间略长,扩展性差。在这里不做过多讨论
获取客户端真实IP
在sn上如何获取客户端真实ip呢?以nginx为例,我们通常在转发时会加上以下头信息:
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
X-Forwarded-For(XFF)
是一个 HTTP 扩展头部,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用.
X-Forwarded-For 请求头格式非常简单
X-Forwarded-For: client, proxy1, proxy2
X-Real-IP
通常被 HTTP 代理用来表示与它产生 TCP 连接的设备 IP,这个设备可能是其他代理,也可能是真正的请求端。需要注意的是,X-Real-IP 目前并不属于任何标准,代理和 Web 应用之间可以约定用任何自定义头来传递这个信息
sn上收到的请求头如下:
X-Forwarded-For: 172.16.0.1,172.16.0.6
X-Forwarded-For: 172.16.0.6
问题
X-Forwarded-For和X-Real-IP都是自定义头,客户端可以自行提交该头,那么拿到的ip会不会是修改后的?
1.对于直连的情况,除了从TCP连接中获取的Remote Address之外,请求头中携带的IP信息都不可信。
curl http://t1.imququ.com:9009/ -H ‘X-Forwarded-For: 1.1.1.1’ -H ‘X-Real-IP: 2.2.2.2’
remoteAddress: 114.248.238.236
x-forwarded-for: 1.1.1.1
x-real-ip: 2.2.2.2
2.对于代理转发的情况(假设只有一级代理)
curl http://t1.imququ.com/ -H ‘X-Forwarded-For: 1.1.1.1’ -H ‘X-Real-IP: 2.2.2.2’
remoteAddress: 127.0.0.1
x-forwarded-for: 1.1.1.1, 114.248.238.236
x-real-ip: 114.248.238.236
相比没有修改头信息的情况,多了一级1.1.1.1
在一个代理的情况下,X-Forwarded-For 最后一节以及 X-Real-IP 整个内容无法构造,可以用于获取用户 IP。
多个代理的情况下,X-Forwarded-For 取距离客户端最近的一级。
nginx转发时配置
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数
proxy_connect_timeout 15; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 15; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 15; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 32k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 8 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传
LVS
LVS负载模式(详细信息)[http://blog.51cto.com/blief/1745134]
- NAT模式
- DR模式
- TUN模式
NAT模式
原理其实就是把从客户端发来的IP包的IP头目的地址在DR上换成其中一台REALSERVER的IP地址并发至此 REALSERVER,而REALSERVER则在处理完成后把数据经过DR主机发回给客户端,DR在这个时候再把数据包的原IP地址改为DR接口上的 IP地址即可期间,无论是进来的流量,还是出去的流量,都必须经过DR
优点:实现方便,容易理解
缺点: 进出流量都要走LVS,LVS容易成为瓶颈
DR模式
LVS-DR模式:每个Real Server上都有两个IP:VIP和RIP,但是VIP是隐藏的,就是不能提高解析等功能,只是用来做请求回复的源IP的,Director上只需要一个网卡,然后利用别名来配置两个IP:VIP和DIP,在DIR接收到客户端的请求后,DIR根据负载算法选择一台rs sever的网卡mac作为客户端请求包中的目标mac,通过arp转交给后端rs serve处理,后端再通过自己的路由网关回复给客户端
优点:性能好
缺点: DIR和RIP必须在同一局域网内
总结: DR是三种模式中性能最好的一种,比LVS-NAT模式下负载的RS serve更多,通常在100台左右,是日常应用最多的一种。
TUN模式
LVS-TUN模式:它的连接调度和管理与VS/NAT中的一样,利用ip隧道技术的原理,即在原有的客户端请求包头中再加一层IP Tunnel的包头ip首部信息,不改变原来整个请求包信息,只是新增了一层ip首部信息,再利用路由原理将请求发给RS server,不过要求的是所有的server必须支持”IPTunneling”或者”IP Encapsulation”协议
优点: 性能好
缺点: 需要所有服务器支持”ip tunneling”协议
FULLNAT模式
DR模式性能好,但是有一个问题,LVS和RS必须在同一个局域网内,这引发了两个问题:
- 同一局域网的限制导致运维不方便,跨局域网的RS无法接入
- LVS水平扩展受到制约。当RS水平扩容时,总有一天单点LVS会成为瓶颈。
FULLNAT由此而生,解决的是LVS和RS跨VLAN的问题,而跨VLAN问题解决后,LVS和RS不再存在VLAN上的从属关系,可以做到多个LVS对应多个RS,解决水平扩容的问题。
FULLNAT模式下,LB会对请求包和响应包都做SNAT+DNAT
FULLNAT的特点:
- FULLNAT下,客户端感知不到RS,RS也感知不到客户端,他们都只能看到LB,这种模式和七层负载均衡有点相似,只不过不会去解析应用层协议,而是在TCP层将消息转发
- LB和RS对组网结构没有要求。不同于DR要求LB和RS位于同一个局域网,FULLNAT对于组网没有要求,只需要保障客户端和LB、LB、RS之间网络互通即可。
三种模式比较
HaProxy
Nginx
扩展知识
A记录
: 指定域名与ip对应关系的记录CNAME
: 即别名,允许你将域名指向另一域名。
CNAME记录和A记录是什么关系?
- CNAME记录和A记录都是在DNS解析过程中的一种记录值类型。
- A记录会直接解析到某个IP,CNAME会解析到另一个域名,之后再对另一个域名继续解析,直到解析出节点。