V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xuelang
V2EX  ›  程序员

这个 HTTP header 导致的超时,有人遇见过吗?

  •  
  •   xuelang ·
    selfboot · 2023-08-09 07:43:27 +08:00 · 1746 次点击
    这是一个创建于 473 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在实际业务中遇到了一个很奇怪的问题,服务 A 通过 HTTP 请求访问 Go 语言的服务 B ,少部分请求会超时。进一步分析发现,如果一个请求超时,其重试也一定会超时,说明针对特定请求内容,超时是必然发生的问题。通过检查服务 B 的处理日志发现,对于超时的请求,其业务逻辑处理的耗时正常。

    一开始通过排除法来分析,逐步替换怀疑有问题的模块,结果并没有定位到问题。后来通过抓包,分析正常包与超时包的区别,合理猜测有问题的部分并进行验证,最终定位到原来是 Expect: 100-continue 这个请求 HTTP header 导致了这里的超时。整个排查和修复过程,踩了不少坑,记录下来可以给大家参考。

    完整内容在: 由 HTTP Header 引起的请求超时问题排查

    Imgur

    HTTP 协议中当客户端要发送一个包含大量数据的请求时(通常是 POST 或 PUT 请求),如果服务器无法处理这个请求(例如因为请求的数据格式不正确或者没有权限),那么客户端会浪费大量的资源来发送这些数据。为了解决这个问题,HTTP/1.1 引入了 Expect: 100-continue 头部,允许客户端在发送请求体前询问服务器是否愿意接收请求。如果服务器不能处理请求,客户端就可以不发送大量数据,从而节省资源。

    这里具体的实现原理是把一个完整的 HTTP 请求分成两个阶段来发送。第一个阶段只发送 HTTP 请求的头部,第二个阶段在收到服务器确认后才发送 HTTP 请求的主体。从 HTTP 的角度看,仍然是一个单一的 HTTP 请求,只是改变了请求的发送方式。

    这里一般靠网络库和底层的 TCP 协议来实现,当使用了”Expect: 100-continue”头部,网络库(比如 libcurl)会先只发送 Expect 部分的 TCP 数据,然后等待服务器的 100 Continue 响应。收到 TCP 回复后,网络库会接着发送请求主体的 TCP 数据包。如果服务器没有返回 100 Continue 响应,网络库可能会选择等待一段时间,然后发送请求主体,或者关闭连接。

    17 条回复    2023-08-09 10:42:50 +08:00
    lasuar
        1
    lasuar  
       2023-08-09 08:50:04 +08:00
    课上了,该说说为何服务器没有即时响应 100 Continue ?这到底属于服务端接口问题。
    crystom
        2
    crystom  
       2023-08-09 09:06:46 +08:00   ❤️ 1
    这个过时了,客户端不建议添加
    zhangkunkyle
        3
    zhangkunkyle  
       2023-08-09 09:07:30 +08:00
    学到了
    dode
        4
    dode  
       2023-08-09 09:08:10 +08:00
    后端把这个请求头逻辑写死处理,
    runliuv
        5
    runliuv  
       2023-08-09 09:24:55 +08:00
    Expect: 100-continue , 一般设置为 false.
    flycat1626
        6
    flycat1626  
       2023-08-09 09:26:59 +08:00
    内容都写到这份上了,还非要导流自己的 blog 吗?真想交流的话,格局还是不够大啊。
    lsk569937453
        7
    lsk569937453  
       2023-08-09 09:31:54 +08:00
    看样子不用这个 c++库的一般不会碰到。
    zzzkkk
        8
    zzzkkk  
       2023-08-09 09:34:05 +08:00
    所以你的 A 服务用来什么 http client
    不要发 expect 100-continue 不就好了
    vfs
        9
    vfs  
       2023-08-09 09:34:33 +08:00
    这娃所有的文章看起来都是给博客导流的。。。
    xuelang
        10
    xuelang  
    OP
       2023-08-09 09:39:19 +08:00
    @lasuar 对,是服务层问题,后面会继续看下服务层这里 bug 在哪里
    xuelang
        11
    xuelang  
    OP
       2023-08-09 09:39:42 +08:00
    @crystom http2 就没有了,不过 1.1 里 libcurl 还是会自动加
    xuelang
        12
    xuelang  
    OP
       2023-08-09 09:40:21 +08:00
    导流有啥问题吗?
    xuelang
        13
    xuelang  
    OP
       2023-08-09 09:40:49 +08:00
    @lsk569937453 嗯,试了 go 的库,没有自动加这个 header
    xuelang
        14
    xuelang  
    OP
       2023-08-09 09:41:04 +08:00
    @zzzkkk 最后就是这样修复的
    xuelang
        15
    xuelang  
    OP
       2023-08-09 09:42:47 +08:00
    @vfs 内容主要在博客更新,这里只是分享出来而已,没必要全部重新粘贴一遍。

    理解成导流没问题,不过只要不是导的垃圾流,就没啥问题吧。

    关键还是看文章质量,对你有用你就看。
    xuhai951753
        16
    xuhai951753  
       2023-08-09 10:27:42 +08:00
    我在想这种情况下是不是超时是正确的,因为服务器没处理,不然可能会过载
    当然服务器因为 bug 没处理那是另外一回事
    xuelang
        17
    xuelang  
    OP
       2023-08-09 10:42:50 +08:00
    @xuhai951753 这种服务 mesh 层没处理好 http 的转发,和过载没关系的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   901 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 22:01 · PVG 06:01 · LAX 14:01 · JFK 17:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.