繁体   English   中英

为什么Tomcat的非阻塞连接器使用阻塞套接字?

[英]Why Tomcat's Non-Blocking Connector is using a blocking socket?

我正在阅读非阻塞I / O,java NIO和tomcat连接器,查看了tomcat的NIO Connector的代码,并NioEndpoint.bind()找到了这个

serverSock.configureBlocking(true); //mimic APR behavior

我没有NIO的经验,所以有人可以解释当套接字配置为阻塞时它是如何非阻塞的吗?

看起来在此次提交中引入了以下行:https://github.com/apache/tomcat/blob/bd8122700c2e70e5adbaddcd289fb1a974f981fe/java/org/apache/tomcat/util/net/NioEndpoint.java

据我所知,NioEndpoint正在使用阻塞ServerSocketChannel来阻止和等待传入连接,并且只有在接受它之后才以非阻塞方式处理这个传入套接字通道(请参阅setSocketOptions方法)。

使得ServerSocketChannel成为非阻塞的替代方法将导致作者指出忙读 - 即线程将不断轮询传入连接,因为非阻塞模式下的accept()可能返回null。

你可以在这里找到一些有用的解释。

PS我认为神秘的APR代表Apache Portable Runtime。

看完代码后:

serverSock对象正在侦听传入连接是否阻塞 与其新接受的连接关联的socket通道对象是实现非阻塞 I / O的对象。

作为侦听传入连接的线程的Acceptor class在其run方法中具有以下定义:

protected class Acceptor extends AbstractEndpoint.Acceptor {
        @Override
        public void run() {
            // Loop until we receive a shutdown command
            while (running) {
                // Loop if endpoint is paused
                while (paused && running) {
                   ...
                try {
                        ........
                    SocketChannel socket = null;
                    try {
                        // Accept the next incoming connection from the server
                        // socket
                        socket = serverSock.accept(); 

                    } catch (IOException ioe) {............}
                ...................
                // setSocketOptions() will add channel to the poller
                // if successful
                if (running && !paused) {
                    if (!setSocketOptions(socket)) {
                        countDownConnection();
                        closeSocket(socket);
                    }
                } ....

正如您所看到的那样,它是处理新socketsetSocketOptions方法,它具有以下代码:

protected boolean setSocketOptions(SocketChannel socket) {
        // Process the connection
        try {
            //disable blocking, APR style, we are gonna be polling it
            socket.configureBlocking(false);
            Socket sock = socket.socket();
            socketProperties.setProperties(sock); 

与用于在相应连接的端点中发送/接收数据的每个连接相关联的socket通道对象是真正实现non-blocking I/Osocket通道对象。

尽管可以始终将serverSock对象accept方法设置为非阻塞,但我认为将select (即accept)操作设置为非阻塞是不切实际的,并且不会服务于任何实际目的,并且在任何实际上下文中都不会有用。 我想不出任何非阻塞接受操作有用的用例。 那对我来说。

从呼叫者的角度看非阻塞。 API仍然需要使用阻塞(在工作线程中)或异步I / O来实际完成操作。 否则,套接字将需要一个自旋锁,并产生CPU浸泡。

您需要查看实现的其余部分,以了解如何完成此映射。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM