【发布时间】:2020-11-30 05:32:15
【问题描述】:
我的节点测试随机失败“客户端网络套接字在建立安全 TLS 连接之前已断开”,我已经调试了数周。出了什么问题?我正在使用超测
【问题讨论】:
标签: node.js ssl port supertest
我的节点测试随机失败“客户端网络套接字在建立安全 TLS 连接之前已断开”,我已经调试了数周。出了什么问题?我正在使用超测
【问题讨论】:
标签: node.js ssl port supertest
Tldr;不要依赖 supertest 在你的服务器上调用监听和关闭。在调用 supertest.agent 之前调用 server.listen 并自行处理调用 close。
有用的阅读:https://gavv.github.io/articles/ephemeral-port-reuse/
net.Server.listen 创建的套接字添加了 SO_REUSEADDR 标志。这意味着可以有多个绑定到同一个端口,因为它们都添加了 SO_REUSEADDR 标志。
默认情况下,Supertest 将调用 server.listen(0),它使用 SO_REUSEADDR 在临时端口上创建和 ipv6 套接字。
当您稍后使用 supertest 与本地服务器通信时,它似乎更喜欢通过 ipv4 而不是 ipv6 进行连接。这至少在 Mac 上是可以的,因为如果是双堆叠,即绑定到 ipv6 上的“::”也会监听 ipv4 上的相同端口,如果它没有被其他进程占用。
但是,每隔一段时间就会有另一个进程在侦听测试使用的临时端口的 ipv4 版本(SO_REUSEADDR 允许这样做)。上面的双重堆叠逻辑将选择 ipv4 套接字到一个随机进程,而不是实际来自您的测试的 ipv6 套接字。
这不应该工作的原因有一百万个,并且外部进程在 TLS 握手完成之前关闭其结束,随机给您问题中的错误。值得庆幸的是,如果您的服务器在您调用 supertest.agent 时已经在侦听,那么 supertest 不再试图巧妙地隐式调用 listen/close,您可以使用临时范围之外的固定端口来避免所有这些。
【讨论】: