我正在尝试在服务器上实现基于 GraphQL WebSocket 的@subscription(使用 NestJS @subscription)。服务器托管在 AWS ECS 上并位于 ALB 后面。 我们目前有一个通过 VPC 链接到我们的 ALB 的 AWS API GW 连接。
我尝试使用我们在 HTTP API GW 中使用的相同 VPC 链接构建专用的 Websocket API GW。 我还尝试在我们的 ECS 上启动一个新的 NLB(网络负载均衡器)以及一个新的 REST VPC 链接以在专用 Websocket API GW 中使用。
客户端和服务器正在使用
graphql-transport-ws
库通过 graphql-ws
子协议进行通信,并且通信在本地主机设置上运行良好。
在本地主机上运行以下命令时,我能够建立 Web 套接字连接:
wscat -c ws://localhost:3000/graphql -s graphql-transport-ws
针对 WebSocket API GW URL 运行相同的操作时
wscat -c wss://*****.execute-api.*****.amazonaws.com/**** -s graphql-transport-ws
我明白了:
error: Server sent no subprotocol
该错误表明子协议存在问题,因此当删除子协议时,会建立连接并且我收到提示:
Connected (press CTRL+C to quit)
>
但是,没有迹象表明已到达服务器,并且似乎仅与 WebSocket API GW 本身建立了连接。
当我绕过网关并直接连接面向互联网的 NLB 时,我能够建立 WebSocket 连接。
我不是超级Websocket专家,但我知道WebSocket连接将被API网关终止,并且不能用作连接传递。 您可以使用 AWS_PROXY 集成将 Web 套接字事件转发到 graphQL 服务器后端,但它不是维护的直接连接 - API Gateway 终止并将事件发送到后端集成,并且不会将集成响应返回到 WebSocket,因为它是事件驱动的而不是面向连接的服务 - 因此您会看到“错误:服务器未发送子协议”。
因此,要使用 API GW 作为 WebSocket 层,您需要在某处构建连接管理功能来管理 APIGW 基于事件的性质,并将数据发送到 APIGW 连接,或者调整 graphql 服务器内的集成机制以利用@connection 功能向 WebSocket 消费者发送响应/通知。
API GW Websockets 非常适合构建自定义解决方案,但需要付出一些努力,因为您将配置事件的设置。
对于 AWS 上的 GraphQL API - 我建议查看 AppSync,它是一项 AWS 托管 GraphQL 服务 - 它通过 WebSocket 本地处理 GraphQL 订阅,并且具有零额外代码,并且具有开箱即用的高度可扩展性,并且可以简化 GraphQL基于 ECS 的解决方案的托管负担。
我怀疑可能还有很多其他原因需要在 ECS 上使用现有的 GraphQL 进行构建,因此请理解,并不总是可以转向 AppSync 之类的东西。 我觉得您尝试的 NLB 解决方案在现有的 ECS 后端环境中是可以的,并且正如您所指出的,它是面向连接的(通过 NLB),因此将实现您想要的结果。