Erlang gen_server против модуля без сохранения состояния

StackOverflow https://stackoverflow.com/questions/1613958

  •  06-07-2019
  •  | 
  •  

Вопрос

Я недавно закончил книгу Джо, и мне она очень понравилась. С тех пор я начал программировать мягкое приложение реального времени с помощью erlang, и должен сказать, что я немного запутался в использовании gen_server.

Когда мне следует использовать gen_server вместо простого модуля без сохранения состояния? Я определяю модуль без состояния следующим образом: - Модуль, который принимает свое состояние в качестве параметра (очень похоже на ETS / DETS), а не хранит его внутри (как gen_server)

Скажем, для модуля типа менеджера счетов-фактур, должен ли он инициализироваться и возвращать состояние, которое я потом передам ему? SomeState = InvoiceManager: Init (), SomeState = InvoiceManager: AddInvoice (SomeState, AnInvoiceFoo).

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

Где граница между ними?

(обратите внимание, что приведенный выше пример управления счетами - это просто пример, иллюстрирующий мой вопрос)

Это было полезно?

Решение

Это сильно зависит от ваших потребностей и дизайна приложения. Когда вам нужно общее состояние между процессами, вы должны использовать процесс, чтобы сохранить это состояние. Тогда gen_server , gen_fsm или другой gen _ * - ваш друг. Вы можете избежать этого дизайна, когда ваше приложение не является параллельным или этот дизайн не приносит вам других преимуществ. Например, разбить ваше приложение на процессы приведет к упрощению дизайна. В другом случае иногда вы можете выбрать единый дизайн процесса и использовать " без сохранения состояния " модули для производительности или тому подобное. & Quot; апатриды & Quot; Модуль - лучший выбор для очень простых задач без состояния (чисто функциональных). gen_server часто является лучшим выбором для мыслей, которые кажутся естественными "процессами". Вы должны использовать его, когда хотите поделиться чем-то между процессами (использование процессов может быть ограничено масштабируемостью или параллелизмом).

Другие советы

Я не думаю, что вы можете провести различие между тем, что вы называете модулем без состояния и gen_server. В обоих случаях существует рекурсивный цикл приема, который переносит состояние хотя бы в один аргумент. Этот основной цикл обрабатывает запросы, работает в зависимости от запросов и, при необходимости, отправляет результаты обратно запросчикам. Основной цикл, скорее всего, также будет обрабатывать несколько административных запросов, которые могут не являться частью основного API / протокола.

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

Какой метод лучше, зависит в значительной степени от того, что вам нужно. Использование gen_server упростит ваш код и предоставит вам дополнительную функциональность «бесплатно». но это может быть более ограничительным. Вращение собственного даст вам больше силы, но также вы дадите больше возможностей испортить вещи. Это, вероятно, немного быстрее, а также. Что тебе нужно?

Используя обе модели, я должен сказать, что использование предоставленного gen_server помогает мне легче структурироваться. Я думаю, именно поэтому он включен в стек инструментов OTP: gen_server - хороший способ убрать повторяющуюся суть.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top