首页 > 其他分享 >开启 Keep-Alive 可能会导致http 请求偶发失败

开启 Keep-Alive 可能会导致http 请求偶发失败

时间:2024-04-03 15:57:33浏览次数:9  
标签:body http 请求 Alive Keep 重试 return 连接

大家好,我是蓝胖子,说起提高http的传输效率,很多人会开启http的Keep-Alive选项,这会http请求能够复用tcp连接,节省了握手的开销。但开启Keep-Alive真的没有问题吗?我们来细细分析下。

最大空闲时间造成请求失败

通常我们开启Keep-Alive后 ,服务端还会设置连接的最大空闲时间,这样能保证在没有请求发生时,及时释放连接,不会让过多的tcp连接白白占用机器资源。

问题就出现在服务端主动关闭空闲连接这个地方,试想一下这个场景,客户端复用了一个空闲连接发送http请求,但此时服务端正好检测到这个连接超过了配置的连接最大空闲时间,在请求到达前,提前关闭了空闲连接,这样就会导致客户端此次的请求失败。

过程如下图所示,

image.png

如何避免此类问题

上述问题在理论上的确是一直存在的,但是我们可以针对发送http请求的代码做一些加强,来尽量避免此类问题。来看看在Golang中,http client客户端是如何尽量做到安全的http重试的。

go http client 是如何做到安全重试请求的?

在golang中,在发送一次http请求后,如果发现请求失败,会通过shouldRetryRequest 函数判断此次请求是否应该被重试,代码如下,

func (pc *persistConn) shouldRetryRequest(req *Request, err error) bool {  
    if http2isNoCachedConnError(err) {  
       // Issue 16582: if the user started a bunch of  
       // requests at once, they can all pick the same conn       // and violate the server's max concurrent streams.       // Instead, match the HTTP/1 behavior for now and dial       // again to get a new TCP connection, rather than failing       // this request.      
        return true  
    }  
    if err == errMissingHost {  
       // User error.  
       return false  
    }  
    if !pc.isReused() {  
       // This was a fresh connection. There's no reason the server  
       // should've hung up on us.       //       // Also, if we retried now, we could loop forever       // creating new connections and retrying if the server       // is just hanging up on us because it doesn't like       // our request (as opposed to sending an error).       
       return false  
    }  
    if _, ok := err.(nothingWrittenError); ok {  
       // We never wrote anything, so it's safe to retry, if there's no body or we  
       // can "rewind" the body with GetBody.      
        return req.outgoingLength() == 0 || req.GetBody != nil  
    }  
    if !req.isReplayable() {  
       // Don't retry non-idempotent requests.  
       return false  
    }  
    if _, ok := err.(transportReadFromServerError); ok {  
       // We got some non-EOF net.Conn.Read failure reading  
       // the 1st response byte from the server.       
       return true  
    }  
    if err == errServerClosedIdle {  
       // The server replied with io.EOF while we were trying to  
       // read the response. Probably an unfortunately keep-alive       // timeout, just as the client was writing a request.       
       return true  
    }  
    return false // conservatively  
}

我们来挨个看看每个判断逻辑,

http2isNoCachedConnError 是关于http2的判断逻辑,这部分逻辑我们先不管。

err == errMissingHost 这是由于请求路径中缺少请求的域名或ip信息,这种情况不需要重试。

pc.isReused() 这个是在判断此次请求的连接是不是属于连接复用情况,因为如果是新创建的连接,服务器正常情况下是没有理由拒绝我们的请求,此时如果请求失败了,则新建连接就好,不需要重试。

if _, ok := err.(nothingWrittenError); ok 这是在判断此次的请求失败的时候是不是还没有向对端服务器写入任何字节,如果没有写入任何字节,并且请求的body是空的,或者有body但是能通过req.GetBody 恢复body就能进行重试。

标签:body,http,请求,Alive,Keep,重试,return,连接
From: https://www.cnblogs.com/hobbybear/p/18112850

相关文章

  • http前端面试题
    http状态码状态码分类1xx服务器收到请求2xx成功3xx重定向4xx客户端错误5xx服务器错误常见状态码http协议中的状态码有很多,但只有一些是我们常用的。也是面试常考的。200成功301永久重定向(同时返回一个location,写明重定向的url)。例如一个网站的网址永久性的切换......
  • 应用层的http和https协议
    HTTP和HTTPShttp和https是什么?http常用的协议版本http/1.0http/1.1改进http/2.0改进http和https有什么区别?http和https是什么?  HTTP(超文本传输协议)是一种用于在网络上传输超文本数据的协议。它是一种客户端-服务器协议,用于从web服务器传输文本、图像、音频......
  • keepalived高可用负载均衡
    为什么需要keepalived(保持存活)keepalived实现高可用的工作原理1.准备一个集群,为了实现高可用,如nginx负载均衡的2个机器,确保用户的请求,能正确,高可用性的到达这个nginx集群2.部署keepalived,生成VIP,虚拟IP资源。3.keepalived是将一组服务器,组成一个虚拟设备组,实现他们......
  • MySQL、Redis 和 Zookeeper 实现分布式锁方法及优缺点
    MySQL、Redis和Zookeeper都可以用来实现分布式锁,每种技术都有其特定的实现方法以及各自的优缺点。MySQL分布式锁实现方法在MySQL中实现分布式锁通常涉及到使用数据库表。可以创建一个专用的锁表,并利用行的唯一性(例如利用唯一索引)来实现锁机制。使用基于事务的 FORUP......
  • HTTP请求消息数据格式详解(请求头,请求行,请求体)
    HTTP:概念:HyperTextTransferProtocol超文本传输协议传输协议:定义了,客户端和服务器端通信时,发送数据的格式特点:基于TCP/IP的高级协议默认端口号:80基于请求/响应模型的:一次请求对应一次响应无状态的:每次请求之间相互独立,不能交互数据历史版本:1.0:每一次请求响应都会建立新的......
  • 基于http方式的portal 认证-对外
    之前portal认证都是使用的portal协议。目前需要支持所有厂商http协议华为:URL:https://support.huawei.com/enterprise/zh/doc/EDOC1100127139/609549d8#ZH-CN_CONCEPT_0176368423 华三:URL:https://www.h3c.com/cn/d_201908/1222239_30005_0.htm 思科:URL:https://github......
  • 搜索Maven相关依赖jar包(特别推荐)https://mvnrepository.com/
    搜索Maven相关依赖jar包(特别推荐)https://mvnrepository.com/根据maven查询jar包的步骤如下:打开Maven仓库中央库的网站https://mvnrepository.com/在搜索框中输入你需要查询的jar包的名称,例如:hutool-all点击搜索按钮,网站会列出所有符合条件的jar包信息,包括版本号、最近更新时间......
  • HTTP协议格式详解之首行信息解析
    HTTP(HypertextTransferProtocol)是一种用于传输超文本文档的应用层协议,通常用于在客户端和服务器之间传输网页、图片、视频等资源。它是建立在TCP/IP协议栈之上的应用层协议,使用标准的TCP连接来传输数据。HTTP的主要特点包括简单、灵活、可扩展性强等。在OSI(OpenSystemsInt......
  • C# HTTP帮助类
    HTTP请求类型枚举namespaceDemo{///<summary>///HTTP请求类型///</summary>publicenumHttpRequestType{///<summary>///GET请求///</summary>GET,///<summary>......
  • 强!10.6K star,一款开源HTTP测试工具,适合新手,简单、容易上手!
    大家好,我是狂师!今天给大家推荐一款开源的HTTP测试工具:Hurl,相比curl、wget功能更强大,且更容易上手、很适用新手使用。1、项目介绍Hurl是一个使用Rust语言开发的命令行工具,它允许用户运行以简单纯文本格式定义的HTTP请求。这个工具不仅适用于获取数据,还非常适合用于测试HTTP会话......