Read_reply в tarantool-c идет слишком медленно
Я настраиваю c
сервер и использовал tarantool в качестве базы данных, используя tarantool-c. Тем не менее, каждый раз, когда я настраиваю read_reply()
запрос в секунду танков так же, как использование MySQL. Как это исправить?
0 ответов
У нас было обсуждение с Джеймсом, и он поделился кодом. Код реализует http-сервер, и вот как он обрабатывает запрос:
- Примите новый входящий HTTP-запрос.
- Отправить запрос в tarantool (по бинарному протоколу).
- Дождитесь ответа от tarantool'а (синхронно, другие входящие HTTP-запросы не обрабатываются).
- Ответ на http-запрос.
Корень проблемы здесь в том, что мы не можем использовать полную пропускную способность сети между http-сервером и tarantool. Такой сервер должен использовать select() / poll() / epoll() (в Linux) / kqueue (во FreeBSD) или библиотеку, такую как libev, чтобы определить, может ли он записывать в сокет, читать из него или принимать запрос.
Позвольте мне вкратце описать, как он должен работать, чтобы по крайней мере использовать сеть в максимально возможной степени (при выполнении этого из одного потока) в наборе правил типа когда-X-затем-Y:
- Когда приходит новый http-запрос, он должен регистрировать необходимость отправки запроса в tarantool (позвольте мне назвать его ожидающим запросом).
- Когда сокет в tarantool готов к записи и есть хотя бы один ожидающий запрос, сервер должен сформировать запрос к tarantool, сохранить его ID (см. 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, позволяющего выполнять запрос к тарантулу из nginx по бинарному протоколу.
У обоих способов есть свои плюсы и минусы. Однако недостатки http.server можно преодолеть, используя nginx в качестве интерфейса для проксирования запросов к тарантулам, сохраняя преимущества http.server.
Минусы http.server:
- Нет поддержки https.
- Ограничение одного процессора / одного экземпляра тарантула.
- Возможно, худшая производительность, чем у 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 и т. Д.