【发布时间】:2020-10-28 21:56:00
【问题描述】:
我对 Google Kubernetes Engine 还是很陌生,一般来说只是 Kubernetes。 我创建了一个“生产型”Kubernetes 集群,运行我使用 socket.io 的旧 Node.js 应用程序。为了帮助自己做到这一点,我使用了 Google 的 "Deploying a containerized web application" how-to,之后我设置了一个带有 Ingress 的负载均衡器,它通过遵循另一个指南 Using Google-managed SSL certificates (the Setting up the managed certificate part) 来使用托管证书。这给我留下了一个使用 1 个池和三个实例组的集群,每个实例组使用 1-2 个节点。
后端已启动,并且前端能够正确连接到它。问题在于 WebSockets 和前端收到错误 WebSocket connection to 'wss://mycooldomain.com/socket.io/?EIO=3&transport=websocket&sid=afskjaisfhf-afasfoiaofis' failed: Error during WebSocket handshake: Unexpected response code: 400,我整天都在试图弄清楚。
我一直在使用的两个指南中的后者提到创建节点端口和托管证书,然后是一个将两者链接在一起的入口。我决定为负载均衡器创建一个具有不同后端配置的 Ingress 以解决问题:
apiVersion: cloud.google.com/v1beta1
kind: BackendConfig
metadata:
name: my-cool-backendconfig
namespace: my-cool-namespace
spec:
timeoutSec: 60
connectionDraining:
drainingTimeoutSec: 30
sessionAffinity:
affinityType: "CLIENT_IP"
创建它的原因是尝试不同的超时值以保持 WebSocket 连接。我也尝试过timeoutSec: 20000 或drainingTimeoutSec: 3000 等值。 sessionAffinity 部分也来自许多 StackOverflow 线程和 GitHub 问题。
所以必须在我的 NodePort 上应用该配置:
apiVersion: v1
kind: Service
metadata:
namespace: my-cool-namespace
name: my-cool-nodeport
labels:
app: my-cool-app
annotations:
cloud.google.com/backend-config: '{"ports": {"80":"my-cool-backendconfig"}}'
spec:
selector:
app: my-cool-app
type: NodePort
ports:
- protocol: TCP
port: 80
targetPort: 8080
如果我理解正确,在我的 Ingress 上:
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
namespace: my-cool-namespace
name: my-cool-ingress
annotations:
kubernetes.io/ingress.global-static-ip-name: my-cool-global-ip
networking.gke.io/managed-certificates: my-cool-certificate
cloud.google.com/backend-config: '{"default": "my-cool-backendconfig"}'
spec:
backend:
serviceName: my-cool-nodeport
servicePort: 80
在尝试了不同的超时值后,我注意到Error during WebSocket handshake: Unexpected response code: 400 错误不一定会发生在每个socket.emit() 上,而且相当多变,这取决于我猜负载平衡器是否允许连接(?) .
即使 Google 指导 mention 使用更大的超时值,即使是最淫秽的(timeoutSec: 20000 如上所述)也无助于建立稳定的 WebSocket 连接,因为它们最终偶尔会抛出错误。
从后端/前端节点应用程序的角度来看问题,我只是更改了 socket.io 配置以尝试在 polling 之前先建立 websocket 连接:
const server = http.createServer(app);
const io = require('socket.io').listen(server);
io.set('transports', ['websocket', 'polling']);
这也没有帮助。
如何让它工作而不时不时抛出错误?
额外问题:我注意到很多有相同/类似问题的用户都使用 Nginx Ingress 控制器,这对于适当的负载平衡来说是必要的,还是仅适用于实际生产环境?
【问题讨论】:
-
您使用的是什么 GKE 版本。你能分享你的整个 Socket.io 配置吗?
-
@PjoterS 我在
1.16.13-gke.401。我的 socket.io 没有太多配置。前端和后端都将websocket指定为polling之前的第一个传输,仅此而已。前端连接到www.mycooldomain.com(这是一个示例,顺便说一句,我有一个与我自己不同的域,并且正确配置了 DNS),没有指定端口。顺便说一句,我的前端使用ngx-socket-io。
标签: kubernetes websocket socket.io load-balancing google-kubernetes-engine