Tomcat 是如何實現keep-alive

http無狀態,又是基於tcp,所以每次請求都要握手分手,在頻繁的請求來說,很是浪費,且沒有必要。
於是就有了大家都知道的keep-alive。關於keep-alive的概念,網上一大堆,我就不重複了,盜一張圖,描述一下:

keepAlive

keep-alive主要靠服務器實現,那麼問題來了,作爲java程序的主流服務容器,tomcat 是如何實現keep-alive的呢?

先看tomcat,以主流的nio實現爲例

在NioEndpoint.SocketProcessor#doRun的方法中會處理三次握手:

                if (handshake == 0) {
                    log.info("開啓三次握手驗證");
                    SocketState state = SocketState.OPEN;
                    // Process the request from this socket
                    if (event == null) {
                        log.info("state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);");
                        state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
                    } else {
                        log.info("state = getHandler().process(socketWrapper, event);");
                        state = getHandler().process(socketWrapper, event);
                    }
                    if (state == SocketState.CLOSED) {
                        poller.cancelledKey(key, socketWrapper);
                    }
                } else if (handshake == -1 ) {
                    getHandler().process(socketWrapper, SocketEvent.CONNECT_FAIL);
                    poller.cancelledKey(key, socketWrapper);
                } else if (handshake == SelectionKey.OP_READ){
                    socketWrapper.registerReadInterest();
                } else if (handshake == SelectionKey.OP_WRITE){
                    socketWrapper.registerWriteInterest();
                }

處理後的finally會將當前的SocketProcessor加入到緩存中:

                if (running && !paused && processorCache != null) {
                    processorCache.push(this);
                }

下次Poller在執行processSocket 中會先判斷processorCache是否爲空,不爲空則拿出來直接使用,跳過三次握手

就這麼簡單嗎?

仔細想想,好像不對,tomcat是怎麼判斷兩次請求是應該複用同一個processSocket的呢?除非,第一次創建socketChannel沒有關閉。 那就意味着,這個socketChannel一直阻塞在work threadPool裏?!太可怕,所以tomcat 對keep-alive有很苛刻的要求,線程池容量不夠的情況下也不支持。

這篇文章寫完大半年後,看到了H大的文章,不禁眼淚掉下來。我將這篇文章大部分內容刪掉,只保留了自己的思考和線索。以後這類文章少寫,或者放在自己的備忘錄就好了。
H大的文章地址:tomcat對keep-alive的實現邏輯

最後:這裏有一個旨在替換掉tomcat+spring+mybatis的基於netty,支持ioc,router,aop,ddd,restful的極簡後端框架: https://github.com/rongjoker/quarantineJ ,.歡迎star和fork,相信會對你做java開發、併發編程、網絡編程有非常大的幫助.

發佈了24 篇原創文章 · 獲贊 6 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章