Tomcat 是如何实现keep-alive

自古美人都是妖i 提交于 2020-01-12 08:48:55

http无状态,又是基于tcp,所以每次请求都要握手分手,在频繁的请求来说,很是浪费,且没有必要。
于是就有了大家都知道的keep-alive。关于keep-alive的概念,网上一大堆,我就不重复了,盗一张图,描述一下:

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开发、并发编程、网络编程有非常大的帮助.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!