Python的asyncio模块在create_connection时是不是同步的?

在Windows下使用asyncio模块(事件循环用的是默认的_WindowsSelectorEventLoop

探究其BaseEventLoop.create_connection的调用层次,发现其中还同步调用了connect和select函数。

首先,调用层次如下:

BaseEventLoop.create_connection BaseSelectorEventLoop.sock_connect BaseSelectorEventLoop._sock_connect socket.connect

然后参考socket.connect的实现,发现其中调用了connect后,还调用了select。

问题是,本来在程序等待三次握手的时候,Python可以把执行别的协程的,但是这样同步的调用,使得Python只能等待三次握手了。

这样会造成性能问题吗?

如果在异步上下文中调用了阻塞函数,确实会造成性能问题。不过呢,这里的 socket.connect非阻塞的,所以不会有性能问题。见 asyncio/base_events.py 393 行:

 sock = socket.socketfamily=family, type=type, proto=proto sock.setblockingFalse

这里设置了 socket 对象为非阻塞的,所以你看到的下面这些代码都会立即返回:

 res = connects->sock_fd, addr, addrlen; // <<<<<<<< 1 #ifdef MS_WINDOWS if s->sock_timeout > 0.0 { if res < 0 && WSAGetLastError == WSAEWOULDBLOCK && IS_SELECTABLEs { /* This is a mess. Best solution: trust select */ fd_set fds; fd_set fds_exc; struct timeval tv; tv.tv_sec = ints->sock_timeout; tv.tv_usec = ints->sock_timeout - tv.tv_sec * 1e6; FD_ZERO&fds; FD_SETs->sock_fd, &fds; FD_ZERO&fds_exc; FD_SETs->sock_fd, &fds_exc; res = selectPy_SAFE_DOWNCASTs->sock_fd+1, SOCKET_T, int, NULL, &fds, &fds_exc, &tv; // <<<<<<<< 2 if res == 0 { res = WSAEWOULDBLOCK; // <<<<<<<<<< 3 timeout = 1; } else if res > 0 {

——即使三次握手还没有完成。异步等待握手完成的代码见 asyncio/selector_events.py 的 308 行:

 except BlockingIOError, InterruptedError: self.add_writerfd, self._sock_connect, fut, True, sock, address 

发表评论

电子邮件地址不会被公开。 必填项已用*标注