我打算通过python3 asyncio编写一个多进程服务器程序,我发现在Abstracteventloop.create_server中有一个名为'reuse_port'的参数,它看起来像我想要的。<<<<<<<<<。/p>
所以我编写了一些代码,我使用多处理来创建一些过程,每个过程都会创建一个异步事件循环,并且所有这些过程都在同一端口上收听。
我认为这些过程将共同奏效,响应请求,但是当我测试此服务器程序时,我发现只有一个过程一直响应我的请求。
为什么其他人处理没有响应请求?我的代码中有任何错误吗?
OSX10.11 Python3.5.2
服务器:
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import sys
import multiprocessing
import asyncio
import socket
tcp_listen_port = 44330
class Listener:
def __init__(self, protocol, listen_port, listen_host='localhost'):
self._protocol = protocol
self._listen_port = listen_port
self._listen_host = listen_host
self._loop = None
self._server = None
self._pid = os.getpid()
def run(self):
asyncio.set_event_loop(asyncio.new_event_loop())
self._loop = asyncio.get_event_loop()
coro = self._loop.create_server(
self._protocol,
host=self._listen_host,
port=self._listen_port,
family=socket.AF_INET,
reuse_port=True
)
self._server = self._loop.run_until_complete(coro)
print('Listener Server on {}, pid {}'.format(
self._server.sockets[0].getsockname(),
self._pid
))
self._loop.run_forever()
def close(self):
self._server.close()
self._loop.run_until_complete(self._server.wait_closed())
self._loop.close()
class ProtocolEcho(asyncio.Protocol):
def connection_made(self, transport):
self.transport = transport
def data_received(self, data):
data = 'hello python asyncio from pid {}rnrn'.format(os.getpid()).encode()
self.transport.write(data)
self.transport.close()
def create_tcp_srv(listen_port):
listener = Listener(ProtocolEcho, listen_port)
try:
listener.run()
except KeyboardInterrupt:
listener.close()
def main():
cpu_count = multiprocessing.cpu_count()
srvproclist = list()
for i in range(cpu_count):
p = multiprocessing.Process(
target=create_tcp_srv,
args=(tcp_listen_port,)
)
srvproclist.append(p)
for proc in srvproclist:
proc.start()
for proc in srvproclist:
proc.join()
if __name__ == '__main__':
main()
客户端
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
import os
import asyncio
import multiprocessing
async def req():
connect = asyncio.open_connection('localhost', 44330)
reader, writer = await connect
writer.write('hello'.encode('utf-8'))
await writer.drain()
while True:
line = await reader.readline()
if line == b'rn':
break
print('proc {} recv {}'.format(os.getpid(), line.decode()))
writer.close()
def begin_test():
asyncio.set_event_loop(asyncio.new_event_loop())
loop = asyncio.get_event_loop()
tasks = [req() for i in range(10)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
plist = list()
for i in range(4):
p = multiprocessing.Process(
target=begin_test
)
plist.append(p)
for proc in plist:
proc.start()
for proc in plist:
proc.join()
这样的客户端输出:
proc 72319 recv hello python asyncio from pid 72310
proc 72318 recv hello python asyncio from pid 72310
proc 72319 recv hello python asyncio from pid 72310
proc 72320 recv hello python asyncio from pid 72310
proc 72321 recv hello python asyncio from pid 72310
proc 72319 recv hello python asyncio from pid 72310
proc 72318 recv hello python asyncio from pid 72310
proc 72320 recv hello python asyncio from pid 72310
proc 72321 recv hello python asyncio from pid 72310
proc 72318 recv hello python asyncio from pid 72310
proc 72320 recv hello python asyncio from pid 72310
proc 72321 recv hello python asyncio from pid 72310
最后一个数字'72310'是响应我的请求的服务器进程PID,因此我认为只有一个过程正在工作。但是为什么...
要使任何程序一次做一件事需要大量工作。您正在使用一个永无止境的过程创建一台服务器,并且没有通过回调(即Connection_made((,data_received((等来指导程序。但是,这是一个简单的解决方案,使用了Coroutines。
简单地说,看起来您没有任何事件调用其他回调。
在您的脚本中实现Coroutines将很轻松,因为您似乎正在为每个过程返回相同的字符串。您要做的就是将每个功能(过程(包装在Coroutine Decorator(@asyncio.coroutine(中,然后以您看到的方式设置Coroutine程序。
检查一下。这是关于Asyncio的一篇很棒的文章。Asyncio现在正在炒作很多,因为它正在制作编写程序,同时进行多件事。
实施"产量"特别很棒。
注意:我会在评论中提出这一点,但我还没有街头信誉。一天....