Максимальное количество подключений к серверу Aiohttp - PullRequest
2 голосов
/ 27 мая 2019

Я не могу понять причину, по которой реализация сервера aiohttp (и asyncio в целом) не позволяет ограничить максимальное количество одновременных подключений (количество принятых сокетов или количество обработчиков запущенных запросов).(https://github.com/aio-libs/aiohttp/issues/675). Без этого ограничения легко исчерпать память и / или файловые дескрипторы.

В то же время, клиент aiohttp по умолчанию ограничивает количество одновременных запросов до 100 (https://docs.aiohttp.org/en/stable/client_advanced.html#limiting-connection-pool-size), aiojobs ограничивает количество запущенных задач и размер списка ожидающих задач, nginx имеет ограничение worker_connections, любая структура синхронизации ограничена количеством рабочих потоков по дизайну.

Хотя aiohttp может обрабатывать множество одновременных запросовэто число по-прежнему ограничено. В документации по aiojobs сказано: «Планировщик подразумевает ограничение количества одновременных заданий (по умолчанию 100). ... Он предотвращает переполнение программы, выполняя одновременно миллиард заданий».И все же, мы можем с радостью породить «миллиард» (ну, пока у нас не хватит ресурсов) обработчиков aiohttp.

Итак, вопрос в том, почему он реализован таким, какой он есть? Я упускаю некоторые важные детали?Я думаю, что мы можем как-то приостановить обработчики запросов, используя Semafor, но сокет все еще принимается aiohttp, а сопрограмма - это spaв отличие от nginx.Кроме того, при развертывании за nginx число желаемых пределов worker_connections и aiohttp, безусловно, будет разным (поскольку nginx также может обслуживать статические файлы)

1 Ответ

1 голос
/ 27 мая 2019

На основании комментариев разработчиков по связанной проблеме причины этого выбора следующие:

  • Приложение может вернуть ответ 4xx или 5xxесли он обнаруживает, что количество соединений больше, чем он может разумно обработать.(Это отличается от идиомы Semaphore, которая эффективно очередь соединение.)

  • Регулирование количества соединений с сервером большесложнее, чем просто указание числа, потому что предел вполне может зависеть от того, что делают ваши сопрограммы, то есть он должен, по крайней мере, основываться на пути.Эндрю Светлов ссылается на документацию NGINX об ограничении соединения для поддержки этого.

  • В любом случае рекомендуется установить aiohttp за специализированным фронтальным сервером, таким как NGINX.

Более подробную информацию могут предоставить только разработчики, которым известно, что они читают этот тег.

На данный момент представляется, что рекомендуемое решениелибо использовать обратный прокси-сервер для ограничения, либо ограничение на основе приложения, например, этот декоратор (не проверено):

REQUEST_LIMIT = 100

def throttle_handle(real_handle):
    _nrequests = 0
    async def handle(request):
        nonlocal _nrequests
        if _nrequests >= REQUEST_LIMIT:
            return aiohttp.web.Response(
                status=429, text="Too many connections")
        _nrequests += 1
        try:
            return await real_handle(request)
        finally:
            _nrequests -= 1
    return handle

@throttle_handle
async def handle(request):
    ... your handler here ...
...