1

感谢上一个答案中的人,现在我可以构建一个多进程 TCP 服务器,每个进程分别运行一个异步服务器,但都绑定到一个端口。(使用 asyncio 时无法使用 os.fork() 将多个进程绑定到一个套接字服务器

理论上?当每个进程平等地处理传入消息时,此模型将达到其最佳性能。好处可能是更低的延迟或更高的 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)

↑ 那么唯一能接受请求的进程就是父进程。而子进程被完全阻止。好像如果你在进程被阻塞之前获得了锁,那么它总是会这样。口译员只是忠实地按照我们的指示去做。


总之,这是我的两个问题:

  • 1\如果有什么方法可以让这个预先分叉的异步服务器负载平衡?
  • 2\有没有什么办法可以引入锁来帮助解决这个问题?

谢谢!

PS:如果有人能告诉我如何在pypy的解释器中使用uvloop驱动eventloop?非常感谢!

4

0 回答 0