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/
 
  • 抓包结果
notion image
看到 在 上一个请求结束之后(客户端 No.52,53) 等待了1秒钟,重新使用了此连接
发起了新请求(客户端 No.55),但在此请求到达服务端之前,服务端已经发送了fin消息给客户端(服务端 No.48)之后发送了 rst 丢弃了这个请求(服务端 No.50)。

解决办法

  1. 重试
    1. 给 istio加一条retryOn: reset 规则,但是可能会有幂等问题,因为服务端可能已经收到了数据。
       
  1. 保证 envoy 的 idle_timeout 小于 server keep-alive timeout
    1. 让 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

© Zzde 2020 - 2024