У нас была беседа с Джеймсом, и он разделяет код . Код реализует http-сервер и обрабатывает запрос следующим образом:
- Принять новый входящий HTTP-запрос.
- Отправьте запрос в tarantool (используя бинарный протокол).
- Ожидание ответа от tarantool (синхронно, невозможно обработать другие входящие http-запросы).
- Ответ на запрос http.
Корень проблемы в том, что мы не можем использовать полную полосу пропускания сети между http-сервером и tarantool. Такой сервер должен использовать select () / poll () / epoll () (в Linux) / kqueue (во FreeBSD) или такую библиотеку, как libev, чтобы определить, может ли он записывать в сокет, читать из него или принимать запрос.
Позвольте мне вкратце описать, как она должна работать, чтобы, по крайней мере, максимально использовать сеть (при выполнении этого из одного потока) в наборе правил типа «когда X, то Y»:
- Когда приходит новый http-запрос, он должен зарегистрировать необходимость отправки запроса в tarantool (позвольте мне назвать его в ожидании запроса).
- Когда сокет для tarantool готов к записи и имеется хотя бы один ожидающий запрос, сервер должен сформировать запрос к tarantool, сохранить его идентификатор (см. tnt_stream.reqid ) и записать запрос в розетка.
- Когда сокет для tarantool готов для чтения, сервер должен прочитать ответ из tarantool, сопоставить его идентификатор (см. tnt_reply.sync ) с сохраненным и написать ответ в http-клиент, затем закрыть розетка клиенту.
Если необходимо поддерживать http keepalive / pipelining, сервер должен проверить сокет для http-клиента на готовность выполнить read () / write (). Также необходимо зарегистрировать ожидающие ответы http, а не записывать их, когда они появляются.
Кроме того, сам HTTP нелегко реализовать надлежащим образом: он всегда преподносит вам сюрпризы, если вы не контролируете реализации как клиента, так и сервера.
Итак, я опишу альтернативы реализации своего собственного http-сервера, которые совместимы с tarantool и способны работать с ним асинхронно для достижения хорошей производительности. Это:
- Использование http.server модуля tarantool, который позволяет обрабатывать http-запросы прямо во внешней службе tarantool без внешней службы и без использования соединителя для tarantool.
- Использование nginx_upstream_tarantool Модуль nginx, позволяющий выполнить запрос на tarantool от nginx с использованием двоичного протокола.
Есть минусы и плюсы для обоих этих способов. Однако недостатки http.server можно преодолеть с помощью nginx в качестве интерфейса для передачи запросов к tarantool (s), сохраняя преимущества http.server.
http.server минусы:
- Нет поддержки https.
- Один процессор связан / один экземпляр tarantool связан.
- Возможно, хуже, чем у nginx (но не намного).
- Возможно, хуже поддержка предупреждений HTTP (но я не знаю).
http.server профи:
- Проще начать разработку.
- Проще в настройке / развертывании: части конфигурации приложения не распространяются по конфигам для tarantool и nginx.
nginx_upstream_tarantool Минусы и плюсы обратны http.server. Также я бы особо отметил, что nginx позволяет вам балансировать нагрузку между несколькими экземплярами tarantool, которые могут образовывать группу репликации или могут разделять внешние интерфейсы. Эта возможность может быть использована для масштабирования сервиса в смысле желаемой производительности, как при прокси на http.server, так и при использовании nginx_upstream_tarantool.
Полагаю, вам также интересны результаты сравнительного анализа для http.server и nginx_upstream_tarantool. Посмотрите на это измерение. Однако обратите внимание, что он довольно синтетический: он выполняет небольшие запросы и отвечает небольшими ответами. Реальные числа RPS могут различаться в зависимости от размера запросов и ответов, аппаратного обеспечения, необходим ли https и т. Д.