• 深入理解HTTP keepalive(转)


    add by zhj: 客户端使用的是Apache的HttpClient

    原文:https://blog.csdn.net/Kingson_Wu/article/details/80102077

    作者:Torreson

    最近心里有几个疑问想要解决: 
    1. keepalive 是否开启服务端控制还是客户端控制? 
    2. keepalive的时间是由服务端控制还是客户端控制? 
    3. keepalive时间一到,是由客户端主动关闭还是服务端主动关闭? 
    4. 如果客户端不是httpclient,使用telnet连接服务端?

    下面带着上述问题,模拟相关场景进行抓包实验,先展示一张图,便于后续的分析:

    场景一

    1. httpclient连续两次请求,间隔10秒,服务端设置keealive时间为5秒
    2. client代码:

    closeableHttpClient.execute(httpGet);
    Thread.sleep(10000);
    closeableHttpClient.execute(httpGet);
    Thread.sleep(10000);

    3. 服务端设置keepalive:

    ((AbstractProtocol) connector.getProtocolHandler())
    .setKeepAliveTimeout(5000);

    4. 使用wireshark抓包

    从图中可以看到:第一次请求的端口是64360,并且在5秒之后,由服务端主动发送fin包关闭连接。而第二次请求显然已经不能复用连接了,使用的新的端口64361重新连接服务器,后续的行为基本和第一次请求一样。

    5. 查看本地的端口状态 

    可以看到服务端8080端口进入了FIN_WAIT_2状态,参照文中刚开始的第一张图,这显然是主动关闭方才会有的状态,同样64360进入了CLOSE_WAIT状态,说明client端是被动关闭的。
    这里比较奇怪的是,没能看到服务端进入TIME_WAIT状态(可能是环境问题,即使是客户端主动关闭也没看到)。

    场景二

    1. 改造场景一,httpclient请求头加上Connection: Close,请求时间间隔改为1秒 –

    httpGet.addHeader("Connection", "Close");

    2. wireshark抓包

    可以看到,主动关闭方还是服务器端,并且立刻关闭,并没有等待keepalive时间到达。

    场景三

    1. httpclient默认keealive,服务端响应头加上Connection: Close

    response.setHeader("Connection", "Close");

    2. wireshark抓包

    从图中看出,主动关闭方是客户端。如果客户端不是httpclient,是telnet,客户端会主动关闭?后面实验一下。
    如果客户端和服务端都加上Connection: Close,那么主动关闭方是客户端(已经抓包查看过)

    场景四

    1. 跟场景四一样,client有httpclient改成telnet,服务端返回Connection: Close 以及keepalive时间为 5秒

    2. telnet客户端

    3. wireshark抓包

     从图中可以看出,虽然服务端返回Connection: Close ,但是telnet客户端并不理会,而是等到服务端keepalive时间到了(5秒),才由服务端关闭。
    服务端keepalive改成30秒,同样是30秒后由服务端主动关闭。

    场景五

    1. HttpClient客户端keepalive=3秒,服务端keepalive=5秒

    2. wireshark 抓包

     

     服务端5秒后主动关闭,而不是期望的客户端主动关闭。估计客户端主动关闭只有在浏览器端才能实现,或者需要合适的参数和客户端实现。

    答疑

    基于文中开头的疑问做一个解答
    1. keepalive 是否开启服务端控制还是客户端控制?
    keepalive可以由双方共同控制,需要双方都开启才能生效,HTTP1.1客户端默认开启,客户端想关闭可以通过设置Connection: Close,服务端同样想关闭可以设置Connection: Close。双方哪方先收到Connection: Close 则由收到方关闭(前提是双方的实现都支持,比如telnet就不支持)

    2. keepalive的timeout时间是由服务端决定还是客户端决定?

    add by zhj: 案例中用的Apache的HttpClient,它应该是没有定时任务去关闭keepalive超时的连接,应该是当你用它再次请求时,它才会去检查keepalive是否过期,如果过期,才关闭,并创建新的连接。

    但一般的Http连接池都会实现定时检查连接的可用性,其实一项就是keepalive,如果过期,那就关闭。比如OkHttp就使用了Http连接池。  

    3. keepalive时间一到,是由客户端主动关闭还是服务端主动关闭?
    根据上述的分析,哪方的时间短,由哪一方来关闭,除非双方的实现有更明确的协议

    4. 如果客户端不是httpclient,使用telnet连接服务端?

    telnet客户端除了连接时进行三次握手,用来发送数据接收数据,基本无其他实现逻辑。即接收到服务器的响应之后,不会有相关HTTP协议的处理。

  • 相关阅读:
    食物
    连在一起的幻想乡
    【XSY3209】RGB Sequence
    【Luogu4389】付公主的背包
    【BZOJ4555】【TJOI2016】【HEOI2016】求和
    【BZOJ3456】城市规划
    【BZOJ2693】jzptab & 【BZOJ2154】Crash的数字表格
    【Learning】左偏树
    小Z的袜子
    【BZOJ3625】【CF438E】小朋友和二叉树
  • 原文地址:https://www.cnblogs.com/ajianbeyourself/p/15028112.html
Copyright © 2020-2023  润新知