Erlang: gen_server или мой собственный сервер?

Мне нужно написать сервер, который будет получать инструкции от других модулей и выполнять действия в зависимости от полученных инструкций. Эффективность — моя главная задача. Итак, я использую gen_server или пишу свой собственный сервер. Под «мой собственный сервер» я имею в виду что-то вроде:

-module(myserver).
-export([start/0, loop/0]).

start() ->
        spawn(myserver, loop, []).

loop() ->
   receive
        {From, Msg} -> %Do some action here... ;
        message2 -> %Do some action here...;
        message3 -> %Do some action here...;
        message4 -> %Do some action here...;
        .
        .
        .
        _-> ok
   end,
   loop().

Итак, чтобы использовать myserver, я, вероятно, зарегистрирую процесс под зарегистрированным именем при его запуске, и тогда каждый клиент будет отправлять сообщения на сервер, используя этот pid.

Так должен ли я использовать этот метод или вместо этого реализовать сервер, используя поведение gen_server? Есть ли преимущества в использовании gen_server? Но добавит ли использование gen_server каких-либо накладных расходов по сравнению с myserver?


person ErJab    schedule 03.12.2009    source источник
comment
Вы были очень обеспокоены эффективностью последних нескольких вопросов. Есть ли у вас цифры требований к производительности?   -  person Christian    schedule 03.12.2009
comment
О, и обязательно используйте gen_server, пока вы не сможете определить, где находятся ваши узкие места.   -  person Christian    schedule 03.12.2009
comment
Сейчас у меня нет никаких цифр, чтобы количественно оценить требования к производительности системы. Это экспериментальная система, поэтому все, что я знаю на данный момент, это то, что серверам придется обрабатывать невероятный объем трафика. Поэтому я стараюсь уделять больше внимания эффективности и максимально оптимизировать.   -  person ErJab    schedule 03.12.2009
comment
@Christian, да, и сообщит вам, когда система будет готова к работе в прайм-тайм, если вам интересно :)   -  person ErJab    schedule 03.12.2009
comment
@ErJab: просто опубликуйте URL-адрес своей записи в блоге, анонсирующей услугу, в своем профиле.   -  person jldupont    schedule 03.12.2009
comment
@ErJab: не могли бы вы принять ответ, пожалуйста?   -  person jldupont    schedule 04.12.2009
comment
@jldupont Свет, камера, Pixza! Я работаю над многопользовательской браузерной игрой в реальном времени под названием Pixza. И да, мы используем erlang для серверной части. Игра доступна на pixza.com . Дайте мне знать, что вы думаете.   -  person ErJab    schedule 06.05.2010
comment
Кстати, это многопользовательская игра, так что только если в нее играют 10 или более человек, это будет по-настоящему весело. Но вы можете осмотреться иначе.   -  person ErJab    schedule 06.05.2010


Ответы (5)


gen_server будет иметь незначительные накладные расходы по сравнению с самореализуемыми серверами, поскольку для каждого сообщения требуется несколько дополнительных вызовов функций (один из которых является динамическим). Я не думаю, что вы должны учитывать это на данном этапе реализации. Если вы передумали в какой-либо момент, переход с gen_server на ваш собственный сервер должен быть простым.

Что вы получаете с gen_server по сравнению с простым циклом:

  • отладка (с sys)
  • ведение журнала SASL
  • поддержка гибернации
  • поддержка обновления кода
person Zed    schedule 03.12.2009
comment
Но вы можете добавить sys и proc_lib, чтобы сделать ваш простой цикл OTP совместимым и получить все преимущества, перечисленные выше. См. erlang.org/doc/design_principles/spec_proc.html и хороший пример из Масштабируемость книги с помощью ограничения одноразового пароля eralang. 10, github.com/francescoc/scalabilitywitherlangotp/blob/master/ch10/ - person Henry H.; 16.02.2016

Я бы тоже пошел с gen_server. После того, как вы воспользуетесь этим средством, вы научитесь ценить его ценность. Обратный вызов функции может быть немного неудобным (например, handle_cast для асинхронных вызовов), но в конце концов вы к нему привыкнете.

Кроме того, я бы посоветовал не заниматься «преждевременной оптимизацией», не проведя некоторое тестирование. Вы, вероятно, не хотите жертвовать читаемостью/ремонтопригодностью ради незначительного повышения эффективности.

person jldupont    schedule 03.12.2009

Я бы выбрал gen_server просто потому, что столько усилий было потрачено на то, чтобы заставить его работать правильно в различных обстоятельствах. Он заботится о деталях, которые трудно исправить. Я предполагаю, что gen_server может добавить некоторые накладные расходы, но я перестал давать советы по производительности. Если вам действительно интересно, реализуйте оба и измерьте скорость, это единственный верный способ выяснить это.

person svenningsson    schedule 03.12.2009

Вы также можете использовать gen_server2 от разработчиков RabbitMQ. .

Это похоже на gen_server, за исключением следующих настроек (из комментариев):

1) the module name is gen_server2

2) more efficient handling of selective receives in callbacks
gen_server2 processes drain their message queue into an internal
buffer before invoking any callback module functions. Messages are
dequeued from the buffer for processing. Thus the effective message
queue of a gen_server2 process is the concatenation of the internal
buffer and the real message queue.
As a result of the draining, any selective receive invoked inside a
callback is less likely to have to scan a large message queue.

3) gen_server2:cast is guaranteed to be order-preserving
The original code could reorder messages when communicating with a
process on a remote node that was not currently connected.
person Eric    schedule 03.12.2009

Из вашего вопроса я предполагаю, что вы пишете более «постоянный» сервер.

В общем, развертывание собственного сервера более универсально и немного быстрее, если вы все сделаете правильно. Но, и это большое НО:

  • Все придется делать самому, что увеличивает риск ошибок!

  • Если вы хотите, чтобы ваш сервер управлялся с помощью OTP, что вы, вероятно, делаете, если создаете надежную систему, вам также придется справиться со всем этим самостоятельно. И поймите это правильно.

Если бы я делал постоянный сервер, я бы начал с gen_server и только откатывался и запускал свой собственный, если сталкивался с серьезными трудностями при реализации того, что мне нужно.

Другое дело недолговечные серверы.

person rvirding    schedule 03.12.2009