配置AWS ELB支持Websocket和Stickiness
场景
某项目部署在AWS上,使用AWS的 ELB 以及多个EC2 instance。
- 需要支持HTTP(s) stickiness
- 项目中使用了websocket (没有stickiness需求)
- 只有ELB向外开放了访问权限
问题
AWS ELB 目前只支持HTTP(s)和TCP(SSL),并不支持websocket使用的ws(s)。HTTP(s)是Application Layer的,TCP(SSL)是Transport Layer的,而ws(s)也是Application Layer的。因为ELB不支持ws(s),如果要支持websocket,必须使用TCP(SSL)协议来支持ws(s),可以参考这篇官方论坛文章。
解决方案
我们只需要在ELB中设置两个协议,一个为HTTP(s),另一个为TCP(SSL),其中TCP的配置是为了websocket。因为不能使用同一个端口,因此在ELB上HTTP(s)端口使用80(443),而TCP(SSL)则需要使用另外一个端口。
另外,在我们的项目代码中,需要将websocket的端口改为此处设置的TCP(SSL)端口,示例中为5555。
解决开发中的问题
为了在release中支持ELB,我们项目代码中做出相应端口的修改。这给开发带来了一个小问题,开发环境中并没有用到ELB,开发人员一般用同 一个端口同时相应HTTP(s)和ws(s),因此如果直接在代码中硬编码端口,则会给开发带来麻烦。我们的解决方法是添加配置文件,然而配置文件只有在 release环境中才会启用。
应用限制
通过上述方案,基本解决了HTTP(s) stickiness和websocket在ELB中并存的问题,然而这种解决方案并不支持websocket的stickiness,因此需要在开发中 额外解决。当然,使用HTTP(s) stickiness并不见得是好的方式。
参考文章
http://stackoverflow.com/questions/15266702/proxying-websockets-with-tcp-load-balancer-without-sticky-sessions
https://medium.com/@Philmod/load-balancing-websockets-on-ec2-1da94584a5e9
http://www.raweng.com/blog/2014/11/11/websockets-on-aws-elb/
http://johan.heapsource.com/post/31047804966/the-state-of-websockets-ssl-and-sticky-sessions