在前面的回答中对大家的提示,现在我可以构建一个多进程TCP服务器,每个进程分别运行一个异步服务器,但所有进程都绑定到一个端口。 (Could not use os.fork() bind several process to one socket server when using asyncio)
从理论上讲?当每个进程均等地处理传入消息时,该模型将实现其最佳性能。好处可能像更低的延迟或更高的tps?我不确定。
这是问题所在。我创建了一个四进程服务器,并统计了每个进程将接受多少tcp请求(由不断发出新连接请求的循环客户端)的结果。{p1:20000次,p2:16000次,p3:13000次,p4:10000次} <-这个。可能不是某种好结果。
我正在弄清楚锁是否有帮助(让获得锁的进程接受请求,而不是让进程直接竞争地接受请求)。但是事实证明,只有父进程才能获得锁。而另一个完全不能。
试图找出解决方案,需要您的帮助。
这是一个简单的示例服务器代码(预分叉的模型,其中的进程直接竞争性地接受请求):
# sample_server.py
import asyncio
import os
from socket import *
def create_server():
sock = socket(AF_INET , SOCK_STREAM)
sock.setsockopt(SOL_SOCKET , SO_REUSEADDR ,1)
sock.bind(('',25000))
sock.listen()
sock.setblocking(False)
return sock
async def start_serving(loop , server):
while True:
client ,addr = await loop.sock_accept(server)
loop.create_task(loop ,client)
async def handler(loop ,client):
with client:
while True:
data = await loop.sock_recv(client , 64)
if not data: break
print(f"Incoming message {data} at pid {pid}")
await loop.sock_sendall(client , data)
server = create_server()
for i in range(4 - 1):
pid = os.fork()
if pid <= 0:
break
pid = os.getpid()
loop = asyncio.get_event_loop()
loop.create_task(start_serving(loop , server))
loop.run_forever()
然后我们可以将其输出重定向到这样的文件中:
python3 sample_server.py > sample_server.output
下一步,我们可能会大致处理以下数据:
import re
from collections import Counter
with open('./sample_server.output','r') as f:
cont = file.read()
pat = re.compile('[\d]{4}')
res = pat.findall(cont)
print(Counter(res))
获取这样的输出(其中key表示端口号,而value表示它们处理的回声数):
Counter({'3788': 23136, '3789': 18866, '3791': 18263, '3790': 10817})
不平等。
当我这样引入多处理锁时,情况变得更加糟糕:
from multiprocessing import Lock
l = Lock()
async def start_serving(loop , server):
while True:
with l:
client ,addr = await loop.sock_accept(server)
loop.create_task(loop ,client)
↑然后唯一可以接受请求的进程是父进程。而子进程完全被阻塞。好像您在进程被阻止之前获得了一个锁,那么它将始终像这样。口译员只是在忠实地按照我们的指示去做。
总而言之,这是我的两个问题:
谢谢!
PS:是否有人可以告诉我如何在pypy的解释器中使用uvloop drive eventloop?非常感谢!