一個簡單的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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM