最近用websokcet写了一套简单的内部聊天服务,我选择了简单易用的haproxy实现负载均衡。
How does websocket work ?
通常,一个websocket请求的HTTP头如下所示:
1 | GET ws://ws.im.yangguo.info/ws HTTP/1.1 |
这里最核心的部分就是Connection: Upgrade
头,它让client端知道server端会改变协议,变成如Upgrade: websocket
header中所述的协议。
如果server端有提供websocket协议的能力,那么它就会返回如下的内容:
1 | General: |
Status code 101表示协议切换成功(from http to websocket)。
HAProxy and Websockets
如上所示,websockets嵌入了两种协议:
- HTTP:在websocket启动时
- TCP:websocket数据交换
任何时候HAProxy必须在一条没有被打断的TCP链路上支持websockets中的两种协议,这里有两件事情需要注意:
- 能够从HTTP切换到TCP并且链路不能断开。
- 同时支持两种协议的超时管理器
幸运的是,HAProxy能够完美的解决上面的两个要求,并且支持多种的websockets负载均衡模式。它不但可以将流量转发到不到的后端机器,并且还可以执行健康检查(仅限链路建立阶段)。
下图详细说明了每个阶段发生了什么和每个阶段的涉及到的timeout:
在链路建立阶段,HAProxy以HTTP模式运行,处理七层的的信息。它会自动检测连接:升级交换,并准备好切换到隧道模式如果升级协商成功。在这个阶段会涉及到3个timeout:
- client timeout:client端不活跃的时间
- connect timeout:允许TCP链接建立的时间
- server timeout:允许server端处理请求的时间
如果一切顺利,websocket建立成功,然后HAProxy故障转义到tunnel模式,此时HTTP层面在没有任何数据传输。因此该阶段只涉及到一个timeout
- tunnel timeout:优先于client和server端超时
connect timeout将不再使用,因为TCP链路已经建立完成。
调度模式
Haproxy,负载均衡调度模式有如下几种:
- roundrobin,表示简单的轮询,这个不多说,这个是负载均衡基本都具备的;
- static-rr,表示根据权重;
- leastconn,表示最少连接者先处理;
- source,表示根据请求源IP;
- uri,表示根据请求的URI;
- url_param,表示根据请求的URl参数’balance url_param’ requires an URL parameter name
- hdr(name),表示根据HTTP请求头来锁定每一次HTTP请求;
- rdp-cookie(name),表示根据据cookie(name)来锁定并哈希每一次TCP请求。
整体配置
1 | global |