node.js 如何让 Amazon 的 ELB 与 HTTPS/SSL 与 Web Sockets 一起工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9184895/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you get Amazon's ELB with HTTPS/SSL to work with Web Sockets?
提问by Art
This doesn't seem to be working right now. I'm using Faye with NodeJS behind an Amazon ELB. When I switch on HTTPS the connections can no longer be brokered. I found a question here unanswered: https://forums.aws.amazon.com/message.jspa?messageID=283293. Anyone able to get this working? Are there any work around outside of running my own instance of HAProxy?
这现在似乎不起作用。我在 Amazon ELB 后面使用 Faye 和 NodeJS。当我打开 HTTPS 时,无法再代理连接。我在这里发现了一个未回答的问题:https: //forums.aws.amazon.com/message.jspa?messageID =283293。任何人都能够得到这个工作?除了运行我自己的 HAProxy 实例之外,还有其他解决方法吗?
回答by Alessandro Alinone
I confirm, based on our own tests, that configuring ELB on TCP/SSL, instead oh HTTP/HTTPS, makes the trick with WebSockets. The drawbacks are two:
我确认,根据我们自己的测试,在 TCP/SSL 上配置 ELB,而不是 HTTP/HTTPS,可以使用 WebSockets。缺点有两个:
1) As already pointed by arturnt, you cannot get stickyness.
1)正如arturnt已经指出的那样,你不能获得粘性。
2) You will lose the ability to retrieve the identity of the clients. The originating IP seen by your WebSocket server will be always the ELB one and, differently from the HTTP/HTTPS configuration, no X-Forwarded-For header will be added to the requests.
2) 您将失去检索客户身份的能力。您的 WebSocket 服务器看到的原始 IP 将始终是 ELB 之一,并且与 HTTP/HTTPS 配置不同,不会将 X-Forwarded-For 标头添加到请求中。
UPDATE July 2013: Amazon has just added support for Proxy Protocol, which solves drawback number 2 above. With the Proxy Protocol, a header containing the client's originating IP is added even when ELB works at TCP level, rather than HTTP. Full details: http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html
2013 年 7 月更新:亚马逊刚刚添加了对Proxy Protocol 的支持,解决了上述第 2 个问题。使用代理协议,即使 ELB 在 TCP 级别而不是 HTTP 级别工作,也会添加包含客户端原始 IP 的标头。完整详情:http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/enable-proxy-protocol.html
UPDATE August 2016: Amazon has just announced new AWS Application Load Balancer, which supports WebSocket at Layer 7 (as well as HTTP/2.0 and content-based routing). See https://aws.amazon.com/it/blogs/aws/new-aws-application-load-balancer/
2016 年 8 月更新:亚马逊刚刚宣布了新的AWS Application Load Balancer,它支持第 7 层的 WebSocket(以及 HTTP/2.0 和基于内容的路由)。请参阅https://aws.amazon.com/it/blogs/aws/new-aws-application-load-balancer/
回答by James Little
It won't work, the ELB's HTTP(S) proxy does not understand websocket requests, for now at least, and I don't know when/if it's planned.
它不起作用,ELB 的 HTTP(S) 代理至少目前无法理解 websocket 请求,而且我不知道何时/是否计划这样做。
I'm not sure HAProxy is completely necessary though. It should be possible to put an SSL terminator, e.g. stud/stunnel, on the same instance as your nodejs servers and pass through that way. You can then keep the ELB, but put it in TCP mode.
不过,我不确定 HAProxy 是否完全必要。应该可以将 SSL 终结器(例如,stud/stunnel)与您的 nodejs 服务器放在同一个实例上并通过这种方式传递。然后您可以保留 ELB,但将其置于 TCP 模式。
Obviously there's the SSL overhead on each instance, but in the long run that probably scales better than offloading the SSL to ELB (particularly based on users' comments on ELB's SSL performance).
显然,每个实例都有 SSL 开销,但从长远来看,这可能比将 SSL 卸载到 ELB 的扩展性更好(特别是基于用户对 ELB SSL 性能的评论)。
回答by Art
After James' answer I did a little bit more research and ended up going to the TCP route, not sure there are any disadvantages of that over using the HTTP tunneling of ELB (considering I don't need stickiness). The good thing is that you don't need to do stud/stunnel since ELB provides that for you. So final ELB setup where NodeJS/Faye are listening on port 8000:
在 James 的回答之后,我做了更多的研究并最终转到了 TCP 路由,不确定使用 ELB 的 HTTP 隧道有什么缺点(考虑到我不需要粘性)。好消息是你不需要做螺柱/隧道,因为 ELB 为你提供了。因此,NodeJS/Faye 正在侦听端口 8000 的最终 ELB 设置:
Secure TCP Forward (443) -> Local (8000)
TCP Forward 80 -> Local(8000)
回答by Freman Zhang
You could use Application LB to support websocket well. I just implemented this idea on our latest project after implemented some tricks on ALB:
您可以使用 Application LB 来很好地支持 websocket。在 ALB 上实现了一些技巧后,我刚刚在我们最新的项目中实现了这个想法:
- open 80 port on all related SGs
- make NodeJS running on 80
- enable NodeJS responding http-80 request (NodeJS will upgrade http request to websocket in the backend)
- make ALB target group check http-80 & correct ping path
- create listeners on ALB:
http80->http80, https443->http80 - create listener rules on ALB:
http80->target group, https443->target group - Enable http stickiness in
- 在所有相关 SG 上打开 80 端口
- 使 NodeJS 在 80 上运行
- 启用 NodeJS 响应 http-80 请求(NodeJS 会在后端将 http 请求升级为 websocket)
- 让 ALB 目标组检查 http-80 和正确的 ping 路径
- 在 ALB 上创建侦听器:
http80->http80, https443->http80 - 在 ALB 上创建侦听器规则:
http80->target group, https443->target group - 启用 http 粘性

