Python AIOHTTP.web服务器多处理负载均衡器?

时间:2019-12-06 17:33:41

标签: python python-3.x multiprocessing load-balancing aiohttp

我目前正在使用aiohttp模块开发一个Web应用程序。我正在使用:

aiohttp.webasynciouvloopaiohttp_sessionaiohttp_securityaiomysqlaioredis

我已经针对它进行了一些基准测试,尽管它们相当不错,但我不禁想要更多。我知道Python本质上是单线程的。 AIOHTTP使用异步是非阻塞的,但是我假设它没有利用所有CPU内核是正确的吗?

我的主意:在多处理模式下通过concurrent.futures运行aiohttp.web代码的多个实例。每个过程将在不同的端口上为站点提供服务。然后,我会在它们前面放置一个负载平衡器。 MySQL和Redis可用于在必要时共享状态,例如用于会话。

问题:给定具有多个CPU内核的服务器,这是否会提高预期的性能?如果是这样,是否有任何特定的模式可用来避免问题?我无法想到这些aio模块正在执行的任何操作都将只需要一个线程,尽管我可能是错的。

注意:这不是我提出的主观问题。该模块当前是否绑定到一个线程/进程,或者没有绑定-可以从多处理模块+负载均衡器中受益,或者不能。

1 个答案:

答案 0 :(得分:0)

是的,asyncio仅使用一个CPU。 (一个事件循环仅使用一个线程,因此仅使用一个CPU)

我不能说整个项目是网络还是CPU约束。 您必须尝试。

您可以使用nginx或haproxy作为负载均衡器。 您甚至可能根本不使用任何负载平衡器。我从未尝试过,但是有了新内核,多个进程可以侦听同一个端口,而我猜想是由内核来进行轮询。 如果对此感兴趣,我可以尝试找到一个例子。

添加了20191209:

这是一个HTTP服务器的小示例,可以在同一套接字上侦听多次启动。 内核将分发任务。我从未检查过这是否有效。

reuseport.py:

import asyncio
import os
import socket
import time
from aiohttp import web


def mk_socket(host="127.0.0.1", port=8000, reuseport=False):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    if reuseport:
        SO_REUSEPORT = 15
        sock.setsockopt(socket.SOL_SOCKET, SO_REUSEPORT, 1)
    sock.bind((host, port))
    return sock

async def handle(request):
    name = request.match_info.get('name', "Anonymous")
    pid = os.getpid()
    text = "{:.2f}: Hello {}! Process {} is treating you\n".format(
        time.time(), name, pid)
    time.sleep(0.5)  # intentionally blocking sleep to simulate CPU load
    return web.Response(text=text)

if __name__ == '__main__':
    host = "127.0.0.1"
    port=8000
    reuseport = True
    app = web.Application()
    sock = mk_socket(host, port, reuseport=reuseport)
    app.add_routes([web.get('/', handle),
                    web.get('/{name}', handle)])
    loop = asyncio.get_event_loop()
    coro = loop.create_server(
        protocol_factory=app.make_handler(),
        sock=sock,
        )
    srv = loop.run_until_complete(coro)
    loop.run_forever()

一种测试方法:

./reuseport.py & ./reuseport.py & 
sleep 2 # sleep a little so servers are up
for n in 1 2 3 4 5 6 7 8 ; do wget -q http://localhost:8000/$n -O - & done

输出看起来像:

1575887410.91: Hello 1! Process 12635 is treating you
1575887410.91: Hello 2! Process 12633 is treating you
1575887411.42: Hello 5! Process 12633 is treating you
1575887410.92: Hello 7! Process 12634 is treating you
1575887411.42: Hello 6! Process 12634 is treating you
1575887411.92: Hello 4! Process 12634 is treating you
1575887412.42: Hello 3! Process 12634 is treating you
1575887412.92: Hello 8! Process 12634 is treating you

相关问题