OkHttp无限重试问题

背景:

公司值班同学收到反馈,xxx-tc-tke-prodd请求频繁超时导致页面查询超时问题。

现象

1.调用方耗时长。
在这里插入图片描述

2.调用方发送一次请求,服务提供方收到大量重复请求。如下图
在这里插入图片描述
调查步骤:
1.当请求参数过长时,问题可以重现。注:问题发生时,请求经过的链路为:xxx-tc-tke-prod->腾讯LB
->MK网关->gis
2.查看okhttp源码,重试逻辑在okhttp3.internal.http.RetryAndFollowUpInterceptor类中。
关键逻辑介绍:

  1. RetryAndFollowUplnterceptor拦截器会对服务端返回的异常信息做分析。判断异常是否可通过重试解决(代码
    逻辑,okhttp3.internal.http.RetryAndFollowUplnterceptor#reecover)。
  2. RetryAndFollowUpInterceptor拦截器收到的异常类为:IOException,异常详细信息:“stream was reset:
    CANCEL”,符合重试逻辑。
    在这里插入图片描述
    3.请求重试后,拦截器再次收到同样的异常,再次重试,并无限循环下去。

问题:
1.为什么okhttp会不断收到"stream was reset:CANCEL"异常常?

结论如下:
a.腾讯云LBHTTP2协议默认最大的HEADER大小为4kb,数据超过最最大值后,LB直接拒绝并发送FIN包给调用方。然
而,调用方因请求数据并未发送完,所以会继续发送数据,LB4收到额外数据后,发送RESET包给调用方,故,okhttp
收到"stream was reset: CANCEL"异常。
b.以上分析与抓包数据吻合

2.为什么okHttp会无间断的重试?
经测试,此为okhttp低版本的bug,虽然okhttp也有最大重试次数的判断逻辑,但无法触达。高版本okhttp已修复该问题。详情见解决方案。

问题复现条件:

1.使用HTTP2协议。
2.流量经过腾讯LB网关,且请求头信息超过LB配置的最大值(当前值为4kb)。
3.使用okHttp的问题版本。

import okhttp3.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class TestController {
   

    private static final String s = "https://api-les-gis-test.nioint.com/v1/fence/batch?fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos=119898&fenceNos&#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值