istio 随机 503
date
Nov 20, 2021
updateDate
slug
istio-random-503
status
Published
tags
Istio
Network
TCP
summary
当我们服务启用 isito 后,发现有部分请求会 503,猜测是 envoy 默认
idleTimeout
远大于服务端 的 keep-alive time
...type
Post
当我们服务启用 isito 后,发现有部分请求会 503,初步排查 猜测是 envoy 默认
idleTimeout
远大于服务端 的 keep-alive time
,导致客户端(envoy)发起请求的同时 server 端关掉了连接。发生 竞争条件(race-condition)。复现
- server
const Koa = require('koa'); const app = new Koa(); const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)) app.use(async ctx => { await sleep(5000) ctx.body = 'Hello World'; }); const serv = app.listen(3000) serv.setTimeout(60*1000)
- client
hey -c 10 -z 10s http://<service>:3000/
- 抓包结果
看到 在 上一个请求结束之后(客户端 No.52,53) 等待了1秒钟,重新使用了此连接
发起了新请求(客户端 No.55),但在此请求到达服务端之前,服务端已经发送了fin消息给客户端(服务端 No.48)之后发送了 rst 丢弃了这个请求(服务端 No.50)。
解决办法
- 重试
给 istio加一条
retryOn: reset
规则,但是可能会有幂等问题,因为服务端可能已经收到了数据。- 保证 envoy 的
idle_timeout
小于 server 的 keep-alive timeout
让 server 主动关闭连接之前,envoy先关闭连接
例如我们服务的大部分 keep-alive 时间是 50s,可以让 envoy 的
idle_timeout
小于此值即可。
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: custom-idle-timeout namespace: istio-system spec: configPatches: - applyTo: CLUSTER match: context: ANY patch: operation: MERGE value: common_http_protocol_options: idle_timeout: 50s