一个简单的http请求 怎么延迟这么大?

问题出在哪里:TCP协议有一个TCP_NODELAY 参数会引发延迟。

调用方使用 Apache HTTPClient tcpNoDelay 默认 true , 

被调用方使用HTTP服务,用的JDK自带的HttpServer 在ServerConfig 中发现 noDelay 默认 false

static {
    AccessController.doPrivileged(new PrivilegedAction<Void>() {
        public Void run() {
            ServerConfig.idleInterval = Long.getLong("sun.net.httpserver.idleInterval", 30L) * 1000L;
            ServerConfig.clockTick = Integer.getInteger("sun.net.httpserver.clockTick", 10000);
            ServerConfig.maxIdleConnections = Integer.getInteger("sun.net.httpserver.maxIdleConnections", 200);
            ServerConfig.drainAmount = Long.getLong("sun.net.httpserver.drainAmount", 65536L);
            ServerConfig.maxReqHeaders = Integer.getInteger("sun.net.httpserver.maxReqHeaders", 200);
            ServerConfig.maxReqTime = Long.getLong("sun.net.httpserver.maxReqTime", -1L);
            ServerConfig.maxRspTime = Long.getLong("sun.net.httpserver.maxRspTime", -1L);
            ServerConfig.timerMillis = Long.getLong("sun.net.httpserver.timerMillis", 1000L);
            ServerConfig.debug = Boolean.getBoolean("sun.net.httpserver.debug");
            ServerConfig.noDelay = Boolean.getBoolean("sun.net.httpserver.nodelay");
            return null;
        }
    });
}

解决:后端HTTP服务,加上启动项“Dsun.net.httpserver.nodelay=true”参数,问题解决。

原因:

1.TCP_NODELAY 是什么?

在socket编程中,TCP_NODELAY是用来控制是否开启Nagle算法的。true 表示关闭 Nagle算法 false则表示打开。

2.Nagle算法是什么?

Nagle算法是一种通过减少发送网络数据包数量来提高TCP/IP网络效率的方法。

思路:如果一个请求很小1字节 发送这1字节有效数据的数据包需要40字的包头(IP头部20字节,TCP头部20字节),这种方式利用率很低。

Nagle做法:

如果发送内容大小>= 1MSS立刻发送 ,(MSS 为 TCP 数据包每次能够传输的最大数据分段)

如果之前的包没有被ACK 立即发送,

如果之前报被ACK 缓存发送部分,

如果收到ACK立刻发送缓存内容。

3.Delayed ACK是什么呢?

思路:TCP 为了保证传输的可靠性,规定接收到数据包时候向对方发送一个确认,只发送一个确认代价比较高 跟发1字节的请求一个道理。

TCP Delayed ACK(延迟确认) :将几个ACK组合在一起的单个响应,或者将ACK与响应数据一起发送给对方,从而减少协议开销。

具体做法:

  当有响应数据发送时,ACK会随响应数据一起发送给对方。

  如果没有响应数据,ACK将延迟发送,看是否有其他响应数据一起发送, linux上这个延迟是40ms.

  如果等待发送ACK期间对方的第二个数据包又到达了,则立即发送ACK,这时如果第三个数据包相继到达 是否发送ACK 要看前两条

4.Nagle 和 Delayed ACK一起会发生什么?

  A 使用Nagle B 使用Delayed ACK 

  A  向 B 发送一个包 由于B Delayed ACK 就等着 A再发 这时候 A 也在等着B返回ACK 导致白白等40ms。

posted @ 2019-10-10 17:30  皮肤黝黑的小白  阅读(2036)  评论(0编辑  收藏  举报