代理 WebSocket 连接
WebSocket 通过长连接在客户端与服务器之间提供双向通信。Ingress Controller 转换路由时,生成的网关路由必须允许 HTTP 连接升级为 WebSocket。
网关可以代理通过 HTTPRoute、ApisixRoute 或 Ingress 配置的 WebSocket 后端。如需限制并发 WebSocket 连接,请参阅 limit-conn 插件。
前置条件
- 完成设置 Ingress Controller 和网关。
- 安装 websocat 以验证 WebSocket 连接。
启用 WebSocket
WebSocket 的启用位置取决于路由资源:
| 资源 | 配置 |
|---|---|
| HTTPRoute | 将后端 Service 端口的 appProtocol 设置为 kubernetes.io/ws 或 kubernetes.io/wss。HTTPRoute 没有路由级替代配置。 |
| ApisixRoute | 将 spec.http[].websocket 设置为 true,或使用 Service 端口的 appProtocol。 |
| Ingress | 将 k8s.apisix.apache.org/enable-websocket 注解设置为 true,或使用 Service 端口的 appProtocol。 |
以下示例配置 HTTPRoute 和 ApisixRoute。如果无法修改后端 Service,请使用 ApisixRoute 字段或 Ingress 注解,不要使用 HTTPRoute。
启动示例上游服务
创建 Kubernetes manifest 文件,部署 WebSocket 服务器及其 Service。该服务器在 /.ws 提供 WebSocket 端点,并会回显收到的任何消息。
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: websocket-server
spec:
replicas: 1
selector:
matchLabels:
app: websocket-server
template:
metadata:
labels:
app: websocket-server
spec:
containers:
- name: echo-server
image: jmalloc/echo-server
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: websocket-server
spec:
selector:
app: websocket-server
ports:
- name: ws
port: 8080
targetPort: 8080
protocol: TCP
appProtocol: kubernetes.io/ws
type: ClusterIP
HTTPRoute 示例需要此 appProtocol 设置。未设置时,网关会将 WebSocket 握手视为普通 HTTP 请求。成功的 HTTP/1.1 WebSocket 握手返回 101 Switching Protocols;如果返回 200 OK 等普通响应,表示连接没有升级。相同设置也可以为 Ingress 和 ApisixRoute 启用 WebSocket。kubernetes.io/ws 表示与上游建立 HTTP 连接;上游接受 TLS 连接时使用 kubernetes.io/wss。完整协议映射请参阅使用 appProtocol 检测上游协议。
将配置应用到集群:
kubectl apply -f ws-echo.yaml
创建路由
为示例 Service 选择 HTTPRoute 或 ApisixRoute:
- Gateway API
- APISIX CRD
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: ws-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /.ws
backendRefs:
- name: websocket-server
port: 8080
HTTPRoute 没有路由级 WebSocket 字段。Ingress Controller 会读取所引用 Service 端口的 appProtocol,并在生成的路由上启用协议升级。
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: ws-route
spec:
ingressClassName: apisix
http:
- name: ws-route
match:
paths:
- /.ws
websocket: true
backends:
- serviceName: websocket-server
servicePort: 8080
即使 Service 端口未声明 appProtocol,ApisixRoute 的 websocket: true 字段也已足够。在此示例中,任一设置都可启用协议升级。
将配置应用到集群:
kubectl apply -f ws-route.yaml
验证连接
对于 APISIX 本地评估环境,GATEWAY_SERVICE 使用默认值 apisix-gateway。对于 API7 安装,请将它改为 API7 控制台生成的网关 Service 名称,然后将该 Service 暴露到本地机器。
GATEWAY_SERVICE=apisix-gateway
kubectl port-forward "svc/${GATEWAY_SERVICE}" 9080:80 &
通过该路由与 WebSocket 服务器建立连接:
websocat "ws://127.0.0.1:9080/.ws"
在终端中发送 hello 消息。你应看到 WebSocket 服务器回显相同消息:
Request served by 1cd244052136
hello
hello
你可以继续发送更多消息,WebSocket 服务器会回显你发送的任何消息。这表示双向连接已成功建立并保持可用。
更新或删除路由
更改后端 Service 端点只会影响新的 WebSocket 连接。已建立的连接会一直连接到其选定的后端,直至连接结束,因此请新建连接来验证端点变更。
删除路由会阻止建立新的匹配连接,但不会关闭已经完成 WebSocket 升级的连接。这些连接会保持打开状态,直到客户端、后端或网关将其关闭。