Socket.io部署在k8s时,出现ws建立失败的问题
症状
当我们将基于Socket.io的程序放到生产环境运行时,往往不止部署一个节点,或者是一个节点不止部署一份副本,这个时候,本来正常运行的程序,却在与客户端建立链接时出现了问题:1
2Http状态码为400,body为:
{"code":1,"message":"Session ID unknown"}
原因
建立链接时,报出了Session ID unknown
,联想下socket.io的工作方式,它并不是无状态的Http接口,websocket间的会话是通过session id来标识,当一个请求过来后,原来是与Pod A打交道,这次被路由到了Pod B去,Pod B并没有该id的记录(因为在Pod A中),所以就出现了这样的报错。
解决方案(Traefik)
原因我们已经知道了,就是session会话请求去到了不该去的地方,我们可以让相同的请求去到同样的节点上。
对应traefik,我们可以在service配置annotation:1
2
3
4"annotations": {
"traefik.backend.loadbalancer.stickiness": "true",
"traefik.backend.loadbalancer.stickiness.cookieName": "socket"
}
第一个配置traefik.backend.loadbalancer.stickiness
是指开启sticky session。
第二个配置traefik.backend.loadbalancer.stickiness.cookieName
,可以自定义cookie的字段名。
配置完之后,再查看客户端,问题已经解决了。
Traefik的实现方式
当我们配置好sticky session后,traefik会在连接里面保存一个cookie值,值的内容实际上指向了具体服务的Pod的k8s ip,也就是说,当请求过来后,traefik会直接将请求发送给该ip的Pod,从而实现粘性会话。
参考
using-multiple-nodes
sticky-sessions
socketio-multiple-nodes-in-kubernetes
- 本文链接:https://keepmoving.ren/nodejs/socketio-with-k8s/
- 版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 CN 许可协议。转载请注明出处!