Автор оригинала: FreeCodeCapm Team.
Paweł Piotr Przzanadowski
Можно ли ударить миллион запросов в секунду с Python? Вероятно, не до недавнего времени.
Многие компании переходят вдали от Python и на другие языки программирования, чтобы они могли повысить производительность своей работы и сэкономить на ценах на серверы, но на самом деле нет необходимости. Python может быть правильным инструментом для работы.
Сообщество Python в последнее время делает много вокруг работы. CPYPHON 3.6 Усилил общий производительность переводчика с новой реализацией словаря. CPYSHON 3.7 будет еще быстрее, благодаря введению более быстрых звонков конвенции и кэши поиска словаря.
Для задач Crunching Crunching вы можете использовать Pypy с компиляцией кода Route-Time. Вы также можете запустить тестовый люкс Numpy, который теперь улучшил общую совместимость с расширениями C. Позже этого года ожидается, что Pypy достигнет соглашения Python 3.5.
Вся эта великая работа вдохновила меня в инновации в одной из областей, в которых Python широко используется: разработка веб- и микросервисов.
Введите japronto!
Японто является совершенно новой микро-каркасом, адаптированной для ваших потребностей микросервисов. Его основные цели включают в себя быть быстро , Масштабируемый, и легкий Отказ Это позволяет вам делать обоим Синхронный и асинхронный Программирование благодаря Asyncio Отказ И это бесстыдно быстро Отказ Даже быстрее, чем у Nodejs и уходят.
Ошибка: Как указывает User @heeppu, HTTP-сервер Go’s STDLIB может быть 12% быстрее Чем этот график показывает, когда написано более тщательно. Также есть удивительный fasthttp Сервер для поступления, что видимо, это только на 18% медленнее чем японто в этом конкретном этапе. Потрясающие! Подробнее см. https://github.com/squeaky-pl/japronto/pull/12 и https://github.com/squeaky-pl/japronto/pull/14 Отказ
Мы также можем увидеть, что Meinheld WSGI Server почти на ногу с Nodejs и Go. Несмотря на его по своей сути, блокируя дизайн, это отличный исполнитель по сравнению с предыдущими четыреми, которые являются асинхронными решениями Python. Поэтому никогда не доверяйте никому, кто говорит, что асинхронные системы всегда виднее. Они почти всегда более одновременно, но к нему гораздо больше, чем просто.
Я выполнил этот микросхема, используя «Hello World!» Приложение, но это четко демонстрирует накладные расходы на сервер для ряда решений.
Эти результаты были получены на экземпляре AWS C4.2XLarge, который имел 8 VCPUS, запущенный в регионе Сан-Паулу с общим арендой и виртуализацией HVM и магнитным хранилищем. Машина была запущена Ubuntu 16.04.1 LTS (Xenial xerus) с ядром Linux 4.4.0-53-Generic X86_64. ОС сообщила о CPU Xeon® CPU E5-2666 V3 @ 2,90 ГГц. Я использовал Python 3.6, который я свеже скомпилировал из исходного кода.
Быть справедливым, все участники (в том числе GO) работали односистему. Серверы были загружены, используя WRK С 1 нитью, 100 соединениями и 24 одновременными (трубовыми) запросами на соединение (совокупное параллельность 2400 запросов).
HTTP Pibelining Здесь имеет решающее значение, поскольку это одна из оптимизаций, которые Japronto учитывает при выполнении запросов.
Большинство серверов выполняют запросы от поручительных клиентов того же моды, они бы из неперерабатывающих клиентов. Они не пытаются его оптимизировать. (Фактически Sanic и Meinheld также будут молча запрашивать запросы от конфидирующих клиентов, что является нарушением протокола HTTP 1.1.)
По простым словам, Pipelining – это техника, в которой клиент не должен ждать ответа перед отправкой последующих запросов за то же TCP-соединение. Чтобы обеспечить целостность связи, сервер отправляет назад несколько ответов в одном получении запросов заказа.
Горы деталей оптимизации
Когда многие мелкими запросами на получение являются трубопроводными клиентом, существует высокая вероятность того, что они прибудут в один пакет TCP (благодаря Aglecte Algorithm aGle ) на стороне сервера, а затем читать Вернуться на один Системный звонок Отказ
Выполнение системного вызова и движущихся данных из ядра-пространства для пользовательского пространства – очень дорогостоящая операция по сравнению с, скажем, перемещение памяти внутри процесса. Вот почему важно выполнить как можно больше необходимых системных вызовов (но не менее).
Когда japronto получает данные и успешно анализирует несколько запросов, он пытается выполнить все запросы как можно быстрее, клеев ответы назад в правильном порядке, то Написать Вернуться в Один системный звонок Отказ На самом деле ядро может помочь в склеивании, благодаря Scatter/Соберите IO Системные звонки, которые japronto еще не используют.
Обратите внимание, что это не всегда возможно, поскольку некоторые из запросов могут занять слишком много времени, и ждем, пока их не будут увеличить задержку.
Берегите себя, когда вы настраиваете эвристику и рассмотрите стоимость системных вызовов и ожидаемого времени завершения запроса.
Помимо задержки пишет для конвейерных клиентов, есть несколько других методов, которые используют код.
Японто Записывается почти полностью в C. Парсер, протокол, подключение жнец, маршрутизатор, запрос и объекты ответа записаны в виде C расширений.
Японто Трудно сложно отложить создание роботных аналогов своих внутренних структур, пока не спрашивают явно. Например, словарь заголовков не будет создан до тех пор, пока он не запрашивается с видом. Все границы токена уже отмечены раньше, но нормализация клавиш заголовка, а создание нескольких объектов STR выполняется, когда они обращаются в первый раз.
Japronto полагается на отличную библиотеку PicoHTTPParser C для разбора строки состояния, заголовки и консервации HTTP-сообщений. PicoHTTPParser напрямую использует инструкции по обработке текста, найденные в современных процессорах с расширениями SSE4.2 (почти любой 10-летний процессор X86_64 имеет его), чтобы быстро соответствовать границам токенов HTTP. Ввод/вывод обрабатывается супер потрясающим UVLoop, который сама – это обертка вокруг Libuv. На самом низком уровне это мост для системного вызова EPOLL, обеспечивающий асинхронные уведомления о готовности к чтению.
Python – это сборщик мусора, так что забота должна быть принята при разработке высокопроизводительных систем, чтобы не без необходимости увеличивать давление на сборщик мусора. Внутренний дизайн Японто пытается избежать ссылочных циклов и делать как необходимо несколько распределений/делилоцирование. Это делает это путем предварительной обработки некоторых объектов в так называемые арены. Он также пытается повторно использовать объекты Python для будущих запросов, если они больше не ссылаются, а не бросают их.
Все ассигнования делаются как кратные 4 КБ. Внутренние структуры тщательно выложены, чтобы данные, использованные часто вместе, достаточно близко в памяти, минимизация возможности пропускания кэша.
Japronto пытается не копировать между буферами без необходимости, и делает много операций на месте. Например, это проценты – декодирует путь перед сопоставлением в процессе маршрутизатора.
Открытые источники вкладчиков, я мог бы использовать вашу помощь.
Я работал над Японто непрерывно за последние 3 месяца – часто в выходные дни, а также нормальные рабочие дни. Это было возможно только из-за того, что я совершил перерыв от моей регулярной работы программиста и вложил все свои усилия в этот проект.
Я думаю, что пришло время поделиться плодами моего труда с сообществом.
В настоящее время Японто реализует довольно твердый набор функций:
- Реализация HTTP 1.x с поддержкой для разбитых загрузки
- Полная поддержка HTTP Pibelining
- Держитесь в живых соединениях с настраиваемым жнецком
- Поддержка синхронных и асинхронных видов
- Модель Master-Multiworker на основе раздела
- Поддержка для перезарядки кода на изменениях
- Простая маршрутизация
Я хотел бы заглянуть в Websockets и потоковую HTTP-ответы асинхронно дальше.
Есть много работы, которые можно сделать с точки зрения документирования и тестирования. Если вы заинтересованы в помощи, пожалуйста Свяжитесь со мной прямо в Twitter Отказ Вот Репозиторий Japronto GitHub проекта Отказ
Кроме того, если ваша компания ищет разработчику Python, который является выступлением, а также DEVOPS, я открываю, чтобы услышать об этом. Я собираюсь рассмотреть позиции по всему миру.
Окончательные слова
Все эти методы, которые я упомянул здесь, на самом деле не специфичны для Python. Они могут быть, вероятно, работали на других языках, таких как Ruby, JavaScript или даже PHP. Я был бы заинтересован в том, чтобы делать такую работу тоже, но это, к сожалению, не произойдет, если кто-то не сможет его финансировать.
Я хотел бы поблагодарить сообщество Python за их постоянные инвестиции в производительность. А именно Виктор Стиннер @Victorstinner, Инада Наоки @methane и Юрий Селиванов @ 1st1 и всю изымую команду.
За любовь к питону.