Является ли это правильным способом настройки? В отличие от создания соединения с базой данных для каждого посещения «/». В этом последнем случае мы могли бы иметь миллионы соединений одновременно. Это обескураживает? Каковы преимущества и недостатки такого подхода?
Вы не хотите открывать одно соединение, а затем использовать его. HTTP-сервер, который вы используете, который лежит в основе Scotty, называется Warp. У Warp есть multi-core, multi-green-thread design. Вы разрешили для совместного использования одинакового соединения по всем темам, так как Database.MongoDB
прямо говорит, что соединения потокобезопасны, но произойдет то, что когда один поток заблокирован в ожидании ответа (the MongoDB protocol follows a simple request-response design) все темы в вашей сети служба блокирует. Это несчастливо.
Мы можем вместо этого создать соединение на каждый запрос. Это тривиально решает проблему блокировки одного потока, но приводит к собственной доле проблем. Накладные расходы на настройку TCP-соединения, хотя и не существенные, также не равны нулю. Напомним, что каждый раз, когда мы хотим открыть или закрыть сокет, мы должны перейти от пользователя к ядру, дождаться, когда ядро обновит его внутренние структуры данных, а затем вернется (контекстный переключатель). Мы также должны иметь дело с рукопожатием TCP и прощанием. Мы также под высокой нагрузкой закончили файловые дескрипторы или память.
Было бы неплохо, если бы у нас было решение где-то посередине.Решение должно быть
- поточно-
- Давайте Макс переплете число соединений, поэтому мы не исчерпывают ограниченные ресурсы операционной системы
- Быстрый
- Делиться между потоками в рамках нормальная нагрузка
- Создайте новые соединения по мере увеличения нагрузки
- Позвольте нам очистить ресурсы (например, закрыть ручку), поскольку соединения удаляются при уменьшенной нагрузке
- Надеюсь, уже написана и боевые испытания других систем производства
Именно это именно проблема, что resource-pool тали.
Некоторые говорят, что я должен использовать пул (Data.Pool). Похоже, что это только ограничит количество посетителей, использующих одно и то же соединение с базой данных одновременно. Но зачем мне это делать? Разве соединение MongoDB не имеет встроенной поддержки одновременного использования?
Непонятно, что вы подразумеваете под одновременным использованием. Есть одна интерпретация, на которую я могу догадаться: вы имеете в виду что-то вроде HTTP/2, который имеет конвейерную обработку, встроенную в протокол.
standard picture of pipelining http://research.worksap.com/wp-content/uploads/2015/08/pipeline.png
Выше мы видим клиент делает несколько запросов на сервер, не дожидаясь ответа, а затем клиент может получить ответы обратно в некотором порядке. (Время течет сверху вниз). У этого MongoDB нет. Это довольно сложный дизайн протокола, который не намного лучше, чем просто попросить ваших клиентов использовать пулы соединений. И MongoDB здесь не одинок: простой дизайн запроса и ответа - это то, на что рассчитывали Postgres, MySQL, SQL Server и большинство других баз данных.
И: правда, пул соединений ограничивает загрузку, которую вы можете использовать в качестве веб-службы, прежде чем все потоки будут заблокированы, и ваш пользователь просто увидит панель загрузки. Но эта проблема будет существовать в любом из трех сценариев (пул соединений, одно совместное соединение, одно соединение на запрос)! Компьютер имеет конечные ресурсы, и в какой-то момент что-то рухнет при достаточной нагрузке. Преимущество пула соединений заключается в том, что он масштабируется грациозно вплоть до момента, когда он не может. Правильное решение для обработки большего трафика - увеличить количество компьютеров; Из-за этой проблемы мы не должны избегать пула.
В приведенном выше приложении, что происходит, если соединение по какой-либо причине потеряно по какой-либо причине и должно быть создано снова? Как бы вы оправились от этого?
Я считаю, что такие виды чего-то не входят в сферу переполнения стека и не имеют лучшего ответа, чем «попробуйте и посмотрите». Buuuuuuut, учитывая, что сервер завершает соединение, я могу взять удар в том, что может случиться: предположив, что Warp развивает зеленый поток для каждого запроса (что, я думаю, это так), каждый поток будет испытывать непроверенный IOException
, когда он пытается записать в закрытое TCP-соединение. Warp поймал бы это исключение и подал бы его как HTTP 500, мы надеемся написать что-то полезное для журналов. Предполагая, что у вас есть модель с одним соединением, вы можете сделать что-то умное (но высоко в строках кода), где вы «перезагрузите» свою функцию main
и настроите второе соединение.Что-то, что я делаю для проектов хобби: если что-то странное произойдет, например, отброшенное соединение, я попрошу мой процесс диспетчера (например, systemd) посмотреть журналы и перезапустить веб-службу. Хотя это явно не идеальное решение для производства, веб-сайт money-makin, он работает достаточно хорошо для небольших приложений.
Как насчет аутентификации с помощью функции auth
? Должна ли функция auth
вызываться только один раз после создания трубы или она должна быть вызвана при каждом ударе на «/»?
Его следует вызывать один раз после создания соединения. Аутентификация MongoDB - для каждого соединения. Вы можете увидеть an example here of how the db.auth()
command mutates the MongoDB server's data structures corresponding to the current client connection.
Этот комментарий к конструкции привода API может помочь: https://github.com/mongodb-haskell/mongodb/blob/master/doc/Article1.md#pipelining – ErikR