简体   繁体   English

python的asyncio模块的最大连接并发性

[英]Max connection concurrency with python's asyncio module

Setup - The producer/s run on Host A. Multiple thousands of coroutines are created each of which try to send a message to the consumer on Host B. 设置-生产者在主机A上运行。创建了数千个协程,每个协程都尝试向主机B上的使用者发送消息。

import asyncio

NUM_MSGS = 15000
CONSUMER_IP = "<Host B's IP>"
CONSUMER_PORT = <Port #>


@asyncio.coroutine
def send_msg(i, loop):
    conn = asyncio.open_connection(host=CONSUMER_IP, port=CONSUMER_PORT, loop=loop)
    reader, writer = yield from conn

    writer.write(bytes(i, 'utf-8'))

    response = yield from reader.read(100)

    print('{0} - {1}'.format(i, response))
    writer.close()

@asyncio.coroutine
def msg_controller(loop):
    conns = []
    for i in range(NUM_MSGS):
        conns.append(asyncio.async(send_msg(str(i), loop)))
    yield from asyncio.wait(conns)

loop = asyncio.get_event_loop()
loop.run_until_complete(msg_controller(loop))
loop.close()

The consumer on Host B just accepts a connection & responds to it. 主机B上的使用者仅接受连接并对其进行响应。

import asyncio

L_PORT = <Port #>
L_HOST = "Host B's IP"
LOAD = 0 #seconds


def handle_connection(transport, data):
    print('Processed {0}'.format('.'))
    transport.write(pickle.dumps('Done'))

class ConsumerProtocol(asyncio.Protocol):

    def connection_made(self, transport):
        self.transport = transport

    def connection_lost(self, e):
        if e:
            print(e)

    def data_received(self, data):
        loop.call_later(LOAD, handle_connection, self.transport, data)


loop = asyncio.get_event_loop()

coro = loop.create_server(ConsumerProtocol, L_HOST, L_PORT)
server = loop.run_until_complete(coro)
print('Server running at {0} on port {1}...'.format(L_HOST, L_PORT))

try:
    loop.run_forever()
except KeyboardInterrupt:
    print('Server stopped')

server.close()
loop.run_until_complete(server.wait_closed())
loop.close()

Now, the setup works fine when NUM_MSGS <= 5000. Beyond 5000 (approx.) coroutines, say 15000, I see multiple hundreds of below error on the producer side - 现在,当NUM_MSGS <= 5000时,设置工作正常。超过5000(大约)协程,例如15000,在生产者端我看到数百个以下错误-

Traceback (most recent call last):
  File "/usr/lib64/python3.4/asyncio/tasks.py", line 234, in _step
    result = coro.throw(exc)
  File "aggressive_producer.py", line 15, in send_msg
    response = yield from reader.read(100)
  File "/usr/lib64/python3.4/asyncio/streams.py", line 452, in read
    yield from self._wait_for_data('read')
  File "/usr/lib64/python3.4/asyncio/streams.py", line 393, in _wait_for_data
    yield from self._waiter
  File "/usr/lib64/python3.4/asyncio/futures.py", line 386, in __iter__
    yield self  # This tells Task to wait for completion.
  File "/usr/lib64/python3.4/asyncio/tasks.py", line 287, in _wakeup
    value = future.result()
  File "/usr/lib64/python3.4/asyncio/futures.py", line 275, in result
    raise self._exception
  File "/usr/lib64/python3.4/asyncio/selector_events.py", line 662, in _read_ready
    data = self._sock.recv(self.max_size)
ConnectionResetError: [Errno 104] Connection reset by peer
Task exception was never retrieved

(Please ignore the fact that I haven't handled exceptions) (请忽略我没有处理异常的事实)

What's surprising is that on the consumer side, no errors are seen (connection_lost() doesn't report any exception). 令人惊讶的是,在消费者方面,没有看到错误(connection_lost()没有报告任何异常)。 In fact, the consumer does not even see the connections for which the above error is seen on the producer side (connection_made() cb is not received). 实际上,消费者甚至看不到在生产者端看到上述错误的连接(未收到connection_made()cb)。 Yet, the exception above seems to have occurred while waiting for a response from the consumer. 但是,上述异常似乎是在等待消费者响应时发生的。

I checked the logs (/var/log/messages) but did not find any errors there either. 我检查了日志(/ var / log / messages),但也没有发现任何错误。

Is this an asyncio limitation? 这是异步限制吗? Is there such a limit on max concurrency in asyncio? 异步中的最大并发性有这样的限制吗?

OS: RHEL 6.5 | 操作系统:RHEL 6.5 | python version: 3.4.3 python版本:3.4.3

PS - I have increased max open fd limit, max tcp syn backlog, usable port range, and enabled tcp_tw_reuse. PS-我增加了最大开放fd限制,最大tcp syn积压,可用端口范围和启用了tcp_tw_reuse。

You have definitely run out of resources. 您肯定没有资源。

Connection reset by peer message tells that problem not on client side but on server. Connection reset by peer消息Connection reset by peer告诉该问题不是在客户端,而是在服务器上。 I guess connections are rejected by server's firewall or antispam system. 我猜连接被服务器的防火墙或反垃圾邮件系统拒绝了。

$ ulimit -a
-t: cpu time (seconds)              unlimited
-f: file size (blocks)              unlimited
-d: data seg size (kbytes)          unlimited
-s: stack size (kbytes)             8192
-c: core file size (blocks)         0
-m: resident set size (kbytes)      unlimited
-u: processes                       30197
-n: file descriptors                1024
-l: locked-in-memory size (kbytes)  64
-v: address space (kbytes)          unlimited
-x: file locks                      unlimited
-i: pending signals                 30197
-q: bytes in POSIX msg queues       819200
-e: max nice                        0
-r: max rt priority                 0
-N 15:                              unlimited

$ ulimit -n 15000

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

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