Socket.io: ELB 后面的 AWS EC2 始终打印错误意外响应代码:400

创建于 2014-10-30  ·  66评论  ·  资料来源: socketio/socket.io

大家好 -

似乎找不到解决方案,但是当我在负载均衡器后面运行我的应用程序时,我在客户端上收到此错误:

WebSocket connection to 'wss://fakedomain.com/socket.io/?EIO=3&transport=websocket&sid=QH8VmXbiEcp3ZyiLAAAD' failed: Error during WebSocket handshake: Unexpected response code: 400 

我理解这个错误,因为它正在尝试与负载均衡器和现在的 EC2 实例通信(我对 AWS 不是很好,所以请随时为这个提供帮助!)但我不明白的是如何制作错误不显示!

我很想解决根本原因,但我猜它涉及一个单独的专用 socket.io 服务器来处理我目前没有时间处理的所有实时内容,但有人可以请我通过压制这个错误?

我假设它正在退回到轮询,这似乎工作得很好(我连接了套接字连接并触发),但我不想在控制台中启动时出现红色错误。

提前感谢您提供的任何建议!

最有用的评论

我假设您没有使用 Elastic Beanstalk(那里的说明会容易得多)。

转到 EC2-> 网络和安全-> 负载均衡器

选择您的负载均衡器并转到侦听器。 确保负载均衡器协议和实例协议都设置为端口 80 的 TCP 和端口 443 的 SSL,而不是 HTTP 和 HTTPS。

所有66条评论

另外,如果重要的话,我已经通过凉亭安装:

"socket.io-client": "~1.1.0",

你的服务器上有粘性连接吗?

我假设您没有使用 Elastic Beanstalk(那里的说明会容易得多)。

转到 EC2-> 网络和安全-> 负载均衡器

选择您的负载均衡器并转到侦听器。 确保负载均衡器协议和实例协议都设置为端口 80 的 TCP 和端口 443 的 SSL,而不是 HTTP 和 HTTPS。

天啊。 这是我在其他地方没有看到的可靠建议。 我会在上午尝试
并报告回来。 谢谢!

2014 年 10 月 29 日,星期三,晚上 7:48 Vadim Kazakov [email protected]
写道:

我假设您没有使用 Elastic Beanstalk(那里的说明会
容易得多)。

转到 EC2-> 网络和安全-> 负载均衡器

选择您的负载均衡器并转到侦听器。 确保负载
平衡器协议和实例协议设置为 TCP 端口 80 和
SSL 用于端口 443,而不是 HTTP 和 HTTPS。


直接回复此邮件或在 GitHub 上查看
https://github.com/Automattic/socket.io/issues/1846#issuecomment -61038664
.

所以也许我弄错了,但我们的网站是在 HTTPS 上运行的(使用我们的 SSL 证书)。 将它们更改为破坏了很多东西。 我在我的应用程序中检查 X-Forwarded-Proto 以确保请求是 HTTPS,如果不是,则强制它重定向。 显然,没有带有 SSL/TCP 的 X-Forwarded-Proto 标头,并且 Express 将 req.secure 报告为 false(即使我输入了 https)。

建议?

不确定,套接字使用 TCP/SSL 协议而不是 HTTP,因此您需要将其更改为 TCP/SSL 才能使 Web 套接字正常工作。 至于如何修复应用程序的其余部分,我不知道。

谢谢您的帮助。 我将不得不创造一个新环境并搞砸一点。 机器上有很多齿轮!

是否可以让 websocket 在自己的端口上运行? 如果是这样,您可以链接一些文档吗? (我很确定没有,但我可能是错的)

它们可以在您想要的任何端口上工作,只需指定连接端口的时间,如下所示:

io('https://myserver:123');

我正在使用 Elasticbeanstalk 并面临同样的问题,我没有安装 SSL,但通过常规 http 连接。

你好,
我有同样的问题,虽然我使用的是 SockJS。
我的应用程序是 Java Spring 4 应用程序,适用于开发机器和
在 AWS 上遇到同样的错误。
看起来升级标头正在被某人删除,我可以在客户端上看到它。

还能找到解决办法...

我在同一条船上并与 AWS 工程师进行实时聊天,我们都被难住了。 我确实确认 ELB 需要从 HTTP/HTTPS 更改为 TCP(或 SSL(安全 TCP)),但我仍然经常收到 400 错误。 在迁移到 Elastic Beanstalk 负载平衡集群之前,从来没有遇到过这个问题。

如果有的话,请尝试评论任何 app.use 中间件的东西(标题/cors 相关),或者 app.get("/",不确定哪一个对我有用,但请发布您的结果。

更新:我已经确认它是 ELB,无论是为 HTTP 还是 HTTPS 流量配置,socket.io 都失败了。 当我直接访问其中一个 EC2 时,一切正常。

附件是我在通过 ELB 时看到的内容。
snipimage

我似乎通过在负载均衡器前面添加 Route53 实例解决了我的问题。
我现在有一个在 AWS 环境下具有安全连接的工作 websocket。

尝试添加 Route 53,如果这不能解决您的问题,我很乐意分享我的配置。

@yoav200认为你可以分享你的整个配置,让事情对你

我已经设置了一个Route 53实例来管理我的域。
我已经配置了一个托管区域,其中包含将我的域直接指向负载均衡器的记录。

负载均衡器配置为将请求转发到我的 Tomcat 实例,如下所示:
lb-listeners

ELB 的安全组非常标准:
lb-security-group

你用的是 nginx 吗? 您是否必须在配置方面做任何特殊的事情?

我非常接近完成这项工作,过去两天与 AWS 支持工程师共度了近 8 个小时。 不得不将 nginx 从组合中剔除,但非常接近,套接字通过 ELB over http 工作正常,明天我想我可以在服务器端而不是 ELB 级别处理 https 的东西。

我将报告我的发现。

我不使用 nginx,我在亚马逊管理一切,我也将我的域移到了亚马逊,
但是,我已经从使用 AWS 作为其实例的托管云环境迁移了我的应用程序,但使用 nginx 管理负载,我在那里没有问题。

当被问及它对他们的效果如何时,他们的回答是:

我们不使用 Amazon Elastic Load Balancer,我们使用自己的 NGinx 负载均衡层。
一种解决方案可能是使用 Nginx 或 HAProxy 服务器而不是 ELB,并使用具有 haproxy/nginx 的 1 个节点的自动缩放组来确保组件的高可用性。

是的,有人告诉我 HAProxy 是另一种选择,但我很确定我会在一天结束时让它与以下服务一起工作:

  • 弹力豆茎
  • 电子负载均衡器
  • EC2 Autoscaling 组(由 EB 创建)
  • RDS
  • ElastiCache

节点应用程序目前正在使用所有这些服务,但就像我说的那样,只是通过 HTTP,所以没有太多工作要做来准备生产。 稍后我将报告我的发现/配置。

@niczak你能分享一下你是如何工作的吗?

现在,我正在尝试使用 ElastiCache 的 Redis 连接到 EC2 上的节点实例上的 Socket.IO。

我向公众开放了 EC2 实例并响应了一个公共 IP 地址,以便我可以轻松连接到套接字 (http://coding-ceo.ghost.io/how-to-run-socket-io-behind -elb-on-aws/)。 在我的 ELB 上,我正在使用粘性会话(希望这会保持连接),但是我的套接字仍然无法连接并给了我可爱的失败:连接在收到握手响应之前关闭。

轮询虽然工作正常,但试图让套接字和整个路径正常工作。

很想在这里看到一个用例,以便我可以正确配置我的实例(即使它只在 HTTP 而不是 http 和 https 上),因为我已经有一段时间了。

非常感谢你的帮助!

@petrogad

嘿,皮特!

我的 ELB 侦听器尽可能简单(见图),默认情况下,EC2 端口 80 使用 iptables 转发到 8080。 话虽如此,我可以通过 HTTPS 访问我的服务器,然后我的节点应用程序在 8080 上侦听并提供 SSL 证书本身。

elb

处理证书的节点代码如下:

        files = ["COMODOHigh-AssuranceSecureServerCA.crt", "AddTrustExternalCARoot.crt"];
        ca = (function() {
            var _i, _len, _results;
            _results = [];
            for (_i = 0, _len = files.length; _i < _len; _i++) {
                file = files[_i];
                _results.push(fs.readFileSync('/etc/ssl/tcerts/' + file));
            }
            return _results;
            })();

        httpsOptions = {
            ca: ca,
            key: fs.readFileSync('/etc/ssl/tcerts/multidomain.key', 'utf8'),
            cert: fs.readFileSync('/etc/ssl/tcerts/14432575.crt', 'utf8')
        };

        this.serverPort = 8080;
        var httpsServer = https.createServer(httpsOptions, apiInstance);
        httpsServer.listen(this.serverPort);
        startSockets(httpsServer);

为了让 Web 套接字正常工作(不退回到长轮询),我 _had_ 禁用了跨区域负载平衡。 不幸的是,AWS 并未声称通过其 ELB 支持 Web 套接字,因此这些类型的配置“黑客”是必要的。 希望这足以让您启动并运行!

谢谢@niczak

一切都运行良好,HTTP 流量正在运行,这让事情变得很糟糕。 还让redis跨多个实例工作; 最后一件事就是在 reCluster 上工作并允许 tcp 路由与特定的工作人员保持一致。

你在这方面取得了很大的成功吗? 我正在使用快递,所以粘性会话效果不佳。 你有运气吗?

再次感谢,希望这一切都完成后,可以为其他在类似项目上苦苦挣扎的人提供一篇不错的博客文章。

谢谢@niczak

我终于让我的工作了。 但是,除了配置
1)负载均衡器使用TCP协议
2) 负载均衡器禁用跨区域负载均衡

我也需要设置
3) 代理服务器在软件配置部分为“无”。

screen shot 2015-01-09 at 10 28 56 am

这是好消息@aidanbon@petrogad ,为 AWS 上的套接字而

非常感谢! 它解决了我的弹性豆茎问题。 删除 nginx 代理是有意义的

我原来的帖子的更新:

我将 HTTPS 更改为 SSL(443 ---> 我的自定义端口)并保留了 HTTP(80 ---> 我的自定义端口)。

我有使用 express !req.secure && X-Forwarded-Proto !=== https 检查的代码,如果你进入端口 80,它会将你重定向到 HTTPS ...

然而

更改为 SSL 会使 X-Forwarded-Proto 返回 undefined.... 断开此连接。 (也 req.secure 似乎它可能已被弃用)

所以现在:

if (req.get('X-Forwarded-Proto') === 'http') {
            res.redirect('https://' + req.get('Host') + req.url);
        }

似乎工作得很好,我不再在控制台中收到 400 错误。

Hullo - 我在 Elastic Beanstalk 上使用 Node、NGINX、SSL 和 ELB 完成了以下工作:

在 .ebextensions 中创建一个容器命令来修改 nginx 配置脚本以包含代理 websocket:

container_commands:
    00proxy:
        command: sed -i 's/proxy_http_version.*/proxy_http_version\ 1.1\;\n\ \ \ \ \ \ \ \ proxy_set_header\ \ \ \ \ \ \ \ Upgrade\ \ \ \ \ \ \ \ \ \$http_upgrade\;\n\ \ \ \ \ \ \ \ proxy_set_header\ \ \ \ \ \ \ \ Connection\ \ \ \ \ \ \"upgrade\"\;/g' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

使用 Elastic Beanstalk Web 控制台在负载均衡器上安装您的 SSL 证书。

然后转到 EC2 Web 控制台,并将负载均衡器更改为侦听 SSL 443 -> TCP 80。当我在 EB Web 控制台中更改它时,这不起作用,我必须直接在 EC2 中进行。

这应该让一切正常。 我不必做任何重定向,我也设法让 NGINX 工作。

@ChrisEdson在使用此解决方案的包中还有其他内容吗?
我试了一下,但由于错误,部署失败。 日志显示以下行:

/etc/init.conf: Unable to load configuration: No such file or directory

你可以发布你的代码吗?

2015 年 9 月 4 日星期五下午 1:13,Treyone [email protected]写道:

@ChrisEdson在使用此解决方案的包中还有其他内容吗?
我试了一下,但由于错误,部署失败。 日志显示以下行:

/etc/init.conf: Unable to load configuration: No such file or directory

直接回复本邮件或在 GitHub 上查看:
https://github.com/socketio/socket.io/issues/1846#issuecomment -137718880

该应用程序代码是一个非常基本的 socket.io 实现,几乎是一个开箱即用的示例用法。
我唯一添加的是 .ebextensions 中的 .config 文件,我在其中复制了您之前引用的代码片段。
所以我没有太多要发布的内容:)

不用担心,没有代码或日志很难调试。 能发一下日志吗? 可能不适合贴在这里,也许把它们放在一个粘贴箱里。

2015 年 9 月 4 日星期五下午 3:26,Treyone [email protected]写道:

该应用程序代码是一个非常基本的 socket.io 实现,几乎是一个开箱即用的示例用法。
我唯一添加的是 .ebextensions 中的 .config 文件,我在其中复制了您之前引用的代码片段。

所以我没有太多要发布的内容:)

直接回复本邮件或在 GitHub 上查看:
https://github.com/socketio/socket.io/issues/1846#issuecomment -137749890

嗯,我通过 grunt 而不是手动打包发布了我的代码,它就像一个魅力。 自动化应该是强制性的;)

很高兴听见!

2015 年 9 月 8 日星期二下午 3:14,Treyone [email protected]写道:

嗯,我通过 grunt 而不是手动打包发布了我的代码,它就像一个魅力。 自动化应该是强制性的;)

直接回复本邮件或在 GitHub 上查看:
https://github.com/socketio/socket.io/issues/1846#issuecomment -138572724

拯救我的一天!

我们也看到了这个基本问题。 基本上,因为 SocketIO 发送两个请求来建立 websocket 连接,如果这些调用跨实例联合,则无法识别会话 ID 并且握手失败,导致 SocketIO 退回到长轮询。 无论您使用的是 ws 还是 wss,这都是正确的; 它假设您已经在第 4 层(TCP)设置了负载平衡,因为我无法让第 7 层(HTTP)负载平衡与 websockets 一起使用。

解决方法是启用粘性会话,这样一旦调用传递到一个实例,负载均衡器就会继续将这些请求发送到同一个实例; 但是,如果您使用 AWS 的 ELB,它们不允许您使用粘性会话进行第 4 层负载平衡。

我们最终做的是使用原始 websockets,而不是 SocketIO,因为这样就没有需要在调用之间持久化的会话数据(只发生一次调用,握手,并且有效)。

AWS 方面的一个修复是允许以某种方式使用粘性会话来进行第 4 层负载平衡。

对 SocketIO 部分的修复是使 websocket 握手不需要先前 sessionID 的上下文(我不知道这方面的目的或生命周期;我假设它的存在既可以帮助长轮询,也可以用于更多在连接终止的情况下快速重新连接;如果客户端确定连接已终止,它可以生成一个新会话并成功重新连接,而不是让后端拒绝握手,因为它认为连接已经存在)。

一个潜在的解决方法是使用 Redis 在所有实例中保持会话状态。 我没有测试过这个。

如果您的负载允许,一种解决方法是确保每个可用区只有一个节点实例,并禁用跨区负载平衡。 这样,所有调用都将默认为单个节点,从而避免了这个问题。

@aidanbon我找不到Proxy server to be "none" in the Software Configuration section吗?

我只是使用 ubuntu 服务器和 MeteorJS 和 mup 部署..你能给我一个链接吗?

干杯

@sahanDissanayake我通过以下方式找到了我的代理服务器配置选项:

  1. 在感兴趣的环境中单击“配置”
  2. 在“配置”页面中单击“软件配置”
  3. “代理服务器”下拉菜单如我之前的屏幕截图所示。

注意:我的环境是大约一年前配置的。 不确定 AWS 面板是否已针对较新的环境进行了更新。 但是,我今天仍然可以在我的环境中看到这个下拉列表。

@aidanbon我不使用ec2以外的任何其他服务..所以你的设置与我无关? 还是我需要开始使用这个 poxy 服务器?

所以我遇到的问题是,我的网络应用程序 websockets 在端口 8080 中工作,但不在端口 80 中。

这是问题

@lostcolony谢谢你的总结。 我得出了同样的结论。 您是否阅读过这篇博文: https: //medium.com/@Philmod/load -balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t? 他本质上是说可以将第 4 层 (TCP) 传递到 HAProxy 实例,然后该实例移除 PROXY 标头并使用粘性会话将流量路由到正确的实例。 但是,对我来说,这两个 HAProxy 如何配置其“后端”服务器列表以及它在哪里运行以及实际 socket.io 服务器运行在哪里对我来说并不明显。 你能理解它吗?

编辑:我想我现在点击了。 他知道这个列表,因为他有一组已知的服务器并且不关心自动缩放......

服务器列表将在每个 HAproxy 框上配置。 我不确定如何
使用 Auto Scaling ec2 实例,除非你写了一些
当新服务器出现时更新该列表的额外基础设施
在线的。 Socket.io 它们与 Web 应用程序在同一台服务器上运行,所以
连接通过 Elb 进入,联合到 HAproxy 实例,
HAproxy 实例确保 IP 连接始终指向相同
web/app 服务器,这是设置 socket.io 的地方。
2016 年 1 月 13 日凌晨 2:50,“Felix Schlitter” [email protected]写道:

@lostcolony https://github.com/lostcolony谢谢你的总结。 一世
得出了同样的结论。 你读过这篇博文吗:
https://medium.com/@Philmod/load -balancing-websockets-on-ec2-1da94584a5e9#.hd2ectz8t?
他本质上是说可以将第 4 层 (TCP) 传递到
HAProxy 实例,然后取出 PROXY 标头并路由
使用粘性会话到正确实例的流量。 然而,它不是
对我来说很明显这两个 HAProxy 如何获得他们的“后端”服务器列表
配置和运行位置以及实际的 socket.io 服务器运行位置。
你能理解它吗?


直接回复此邮件或在 GitHub 上查看
https://github.com/socketio/socket.io/issues/1846#issuecomment -171208211
.

@lostcolony好的,我看到有一个关于亚马逊自动缩放的有趣项目,使用 HAProxy - 至少对参考有用: https :

如果您将 HAProxies 配置为基于 IP 路由连接,您
可以保证它会在同一个实例中结束。 也就是说,如果 HAProxies
所有人都有相同的规则,即 ip ABCD 指向实例一,
那么无论 ELB 命中哪个 HAProxy,它都会以相同的方式结束
地方。 这就是您发送的链接中发生的事情,他们正在平衡
通过源,这意味着 HAProxy 实例对 IP 进行哈希处理并使用它来
确定它去往哪个实例。 多个 HAProxy,前提是它们全部
知道相同的实例,因此会将流量从一个位置发送到
相同的后端实例。

2016 年 1 月 13 日星期三下午 1:19,Felix Schlitter [email protected]
写道:

@lostcolony https://github.com/lostcolony好的,我看到有一个
关于亚马逊自动缩放的有趣项目,使用 HAProxy -
至少有用的参考:
https://github.com/markcaudill/haproxy-autoscale。 我不明白为什么
在 HAProxy 前使用 ELB? 必须只有一个 HAProxy 实例,
不然怎么保证ELB把流量发到右边
HAProxy 实例? 除非它们(HAProxy 实例)共享一个公共
以某种方式使用 ElastiCache 或 Redis 或其他东西的粘性表
线? ...我确实意识到我们正在_way_偏离主题。


直接回复此邮件或在 GitHub 上查看
https://github.com/socketio/socket.io/issues/1846#issuecomment -171386260
.

@lostcolony我知道哈希是针对给定的ip确定性地派生的,但是,必须存在“哈希->实例”的映射。在您的情况下,您是说有一条规则说“ABCD 被定向到实例一个”,但是您是否不希望 HAProxy 确定自己重定向到的位置,给定可用服务器的列表?毕竟,“ABCD”只是一些客户的 ip,事先并不知道。

将哈希映射到实例的规则在所有 HAProxy 中都是相同的
实例。 也就是说,ABCD 将产生相同的哈希值,无论
它命中的 HAProxy 实例,该哈希将映射到同一台服务器,不
与使用中的 HAProxy 实例无关,前提是每个 HAProxy 都知道
相同的实例(并且可能以相同的顺序/相同的名称)。 这
实际 IP 不必事先知道,因为它们无关紧要。
任何 IP 都将散列到同一台服务器,无论它通过什么 HAProxy
通过。

对于一个完全伪造的例子(HAProxy 使用了一些不是这样的东西
可以预测,我敢肯定),假设我们有三台服务器,它们都已配置
依次为 server0、server1 和 serve2(实际细节无关紧要,
只是有一个明确的顺序,隐含的很好)。 每个 HAProxy
实例具有相同的服务器,顺序相同。 他们也有相同的
关于如何处理传入 IP 地址的规则。 对于这个老生常谈的例子,
它将地址的所有四个部分加起来为整数(很容易扩展为
支持 IPv6,将所有十六进制加到基数 10),然后除以 3,取
余。 所以 IP 123.12.61.24 = (123+12+61+24) % 3, or 1. 所以它被路由
到服务器 1。 所以无论它进入什么 HAProxy 实例,
连接将被发送到 server1。

现在,如果 server1 下线,算法会在所有 HAProxy 中发生变化
实例,添加所有部分,模数 2。

这通常有效 - 除非 - 你得到一个 netsplit (或配置
HAProxy 实例具有不同的服务器列表)。 一台 HAProxy 看到的地方
3 个实例,另一个看到 2 个。如果发生这种情况,您无法得到保证
到达相同的后端。 事实上,这可能会成为一个问题。 但
这就是链接中描述的解决方案。

2016 年 1 月 13 日星期三下午 3:51,Felix Schlitter [email protected]
写道:

@lostcolony https://github.com/lostcolony 我知道哈希是
对于给定的 ip 确定性地派生,但是,必须有一个映射
“哈希->实例”。 在您的情况下,您是说有一条规则是
说“ABCD 指向实例一”,但你不想
HAProxy 确定自己重定向到哪里,给定一个可用列表
服务器? 毕竟,“ABCD”只是一些客户的IP,并不知道
正面。


直接回复此邮件或在 GitHub 上查看
https://github.com/socketio/socket.io/issues/1846#issuecomment -171428465
.

我发现在 Elastic Beanstalk 上,即使我已将负载均衡器设置为通过 Web 界面使用 TCP 和 SSL,但当我直接检查负载均衡器配置时,它仍然使用 HTTPS 作为安全侦听器。 因此,您可能应该在 EC2 > 负载均衡器部分检查端口是否已按应有的方式设置:

screen shot 2016-03-08 at 16 08 34

排序后,将以下内容添加到 .ebextensions 中,一切对我来说都很好:)

container_commands:
  01_nginx_static:
    command: |
      sed -i '/\s*proxy_set_header\s*Connection/c \
              proxy_set_header Upgrade $http_upgrade;\
              proxy_set_header Connection "upgrade";\
          ' /tmp/deployment/config/#etc#nginx#conf.d#00_elastic_beanstalk_proxy.conf

但是,当您只有一个实例时,这只会 100% 有效,因为粘性会话支持不适用于 TCP。

@lostcolony@williamcoates 刚才的帖子提醒我感谢您的解释。 不敢相信我忘了这样做。 您的解释非常有帮助,所以感谢您抽出宝贵的时间。

所以我遇到了同样的问题,结果证明我已经将 ECB 设置为使用 HTTPS。
我将 HTTPS 更改为 SSL,但我不再收到该消息。
所以,不要使用 HTTP/HTTPS,而是使用 TCP/SSL

自 2016 年 8 月起,您可以使用 Amazon 的应用程序负载均衡器 (ALB) 而不是“经典”ELB。 在 HTTP 80 和 HTTPS 443 上为我“开箱即用”地工作。

@trans1t 亲爱的,谢谢你的信息! 我得去看看。

@niczak - 我还切换到 ALB 以实现套接字流量粘性。 然而,我首先在 ALB Sticky Sessions 配置方面遇到了困难(因为关于这个主题的文档并不多;至少几个月前)。 终于想通了。 关键是“粘性是在目标组级别定义的”,因此请确保您创建目标组来服务您的流量,然后为其添加粘性。

@aidanbon这是很棒的信息,非常感谢您的分享!

对于任何仍然遇到 AWS Application Load Balancer 问题的人,请尝试更新您的安全策略,我遇到了同样的问题,即使它在另一个网站的确切设置中运行良好,但注意到安全策略落后了大约 1 年。 将其更新到较新的似乎已经解决了这个问题。

@michaelmitchell您是否更改了任何内容,或者只是在不修改的情况下更新它?

我没有更改我的应用程序中的任何内容,我采取的唯一额外步骤是在 ALB 上删除并重新添加 HTTPS 侦听器,因为在更改为新策略后似乎不起作用。

但是我确实了解到,即使在更新安全策略之后看到错误很可能是我的浏览器会话保留了旧的安全策略,所以我不确定是否真的需要添加/重新添加侦听器,但是打开隐身它工作正常,之后关闭我所有的 chrome 会话并重新打开它工作正常,从那以后就再也没有见过它。

很高兴知道,谢谢!

勒文。 2017 年 3 月 31 日 à 12:02,Michael Mitchell [email protected]
评价:

我没有更改我的应用程序中的任何内容,这是我做的唯一额外步骤
采取的是在 ALB 上删除并重新添加 HTTPS 侦听器,如下所示
更改为新政策似乎没有奏效。

但是,我确实了解到即使在更新安全性之后也看到了错误
策略可能是我的浏览器会话保留了旧的安全策略
所以我不确定是否真的需要添加/重新添加监听器,但是
打开隐身它工作正常,并在关闭我所有的 chrome 会话后
并重新打开它工作正常,从那以后就再也没有见过它。


您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/socketio/socket.io/issues/1846#issuecomment-290672158
或静音线程
https://github.com/notifications/unsubscribe-auth/ADrIi_SXqccWOLUMIWF1IhClGXvKAGMcks5rrM8sgaJpZM4C0swP
.

似乎这个线程成为了解决 AWS/socket.io 问题的地方——

我的设置是客户端使用 socket.io 连接的数据发出 HTTPS 请求。
HTTPS 请求应使用粘性会话所需的 cookie 进行响应。 问题是我无法在 socket.io 连接中传递cookie标头。

我正在使用带有这些侦听器的 ALB:
image

它指向具有如下粘性的目标组:
image

我首先使用以下方法访问 HTTPS 端点:

fetch(`https://${url}/hub/api/spinup/${uuid}`, {
                method: 'GET',
                headers: headers,
            })

然后初始化套接字

connection = io(`wss://${url}:443/`, {
            path: `/user/${uuid}/spawn`,
        })

HTTPS 请求命中的实例_必须_是套接字连接命中的实例。

一旦建立了一个套接字(如果它碰巧碰上了正确的实例),它就会停留在那里并且一切正常,问题是让 websocket 命中与 HTTPS 请求相同的端点。

我的第一直觉是使用

connection = io(`wss://${url}:443/`, {
    path: `/user/${uuid}/spawn`,
    extraHeaders: {
        cookie: cookieValueFromFetchResponse
    }
})

适用于node ,但在浏览器中cookie是 XMLHTTPRequests 上的禁止标头,因此我无法将其发送。

有没有人做过类似的事情?

我没有做过类似的事情,但是,虽然 ALB 仍然没有基于标头的路由,但它们确实有基于主机的路由。 因此,这是非常骇人听闻的,但您基本上可以做到这一点,以便 ALB 后面的每个实例都有一个明确的路径,该路径是该实例知道的。 当初始 HTTP 请求发出时,部分响应包含路径,而 websocket 的连接包含该路径。 即,HTTP 请求命中实例“5”(基于任何标准;生成的 UUID 会更好),返回“5”作为响应的一部分,并且 websocket 被打开到 url/5。 ALB 有一条规则,即 url/5 被路由到实例 5。

如果您使用自动缩放(并且您的实例是牛而不是宠物),您需要让您的代码在实例上运行修改 ALB 设置以将适当的域路由到它。

在此处阅读更多信息: https :

但是,我还要说,如果可能的话,您可能只想避免使用您正在使用的模式。 HTTP 请求中的数据应该以每个实例(DB 或类似实例)都可以访问的方式存储,或者一旦建立,就应该通过 websocket 连接发送。 实际上,您仍然可能在 HTTP 请求和 websocket 打开之间有一个实例死机,并且您可能会遇到同样的问题(尽管频率要低得多)

@lostcolony感谢您的建议——这绝对值得一试。

http 请求是触发 websocket 服务器启动的原因(它实际上位于 docker 容器中,但已被抽象掉了)。 这两个请求需要路由到同一个实例,因此 websocket 服务器存在于正在连接的实例上

有了这条线,它有助于将 jupyter 服务器放在 elb 后面。

service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp

以防有人在aws上使用kubernetes来获得这张票。

我只是禁用HTTP2然后对我来说没问题。 您不必对 ELB 做任何其他事情。

Screen Shot 2019-12-13 at 16 12 49

你好,
我有同样的问题,虽然我使用的是 SockJS。
我的应用程序是 Java Spring 4 应用程序,适用于开发机器和
在 AWS 上遇到同样的错误。
看起来升级标头正在被某人删除,我可以在客户端上看到它。

还能找到解决办法...

@yoav200

救救我。
我陷入了同样的问题。 请帮忙
我正在为 websocket 使用 Springboot 2.x 和 SockJs
我已经创建了部署在 aws 中的 tomcat 应用程序,
带有经典负载均衡器的 Elastic beanstalk

现在的问题是
iOS 开发人员无法连接,它到达我的后端,但在握手期间失败
下面是我在 CLB 和 ALB 中得到的日志


2019-12-13 15:21:22.662 调试 27543 --- [nio-8080-exec-2] oswsDispatcherServlet:获取“/wtchat/websocket”,参数={}
2019-12-13 15:21:22.701 调试 27543 --- [nio-8080-exec-2] oswsssWebSocketHandlerMapping:映射到 org.springframework.web.socket.sockjs.support。 SockJsHttpRequestHandler@30c6a17
2019-12-13 15:21:22.714 调试 27543 --- [nio-8080-exec-2] oswssthDefaultSockJsService:处理传输请求:GET http://mydomain.com/wtchat/websocket
2019-12-13 15:21:22.716 错误 27543 --- [nio-8080-exec-2] cwcMyHandshakeHandler:由于升级标头无效,握手失败:null

2019-12-13 15:21:22.717 调试 27543 --- [nio-8080-exec-2] oswsDispatcherServlet:已完成 400 BAD_REQUEST

我已经按照你说的
image
image

在 Route 53 中创建了一个直接指向负载均衡器的记录集。

这样做之后,我也得到与上述错误相同的错误。

我还需要做什么?

此页面是否有帮助?
0 / 5 - 0 等级