Передать управление от одного gen_fsm к другому
Я создаю универсальный сервер Erlang, который должен одновременно обрабатывать сотни клиентских подключений. Для простоты предположим, что сервер выполняет для каждого клиента некоторые базовые вычисления, например, сложение или вычитание каждых двух значений, которые предоставляет клиент.
В качестве отправной точки я использую это руководство для базового взаимодействия TCP-клиент-сервер. Отрывок, представляющий дерево надзора:
+----------------+
| tcp_server_app |
+--------+-------+
| (one_for_one)
+----------------+---------+
| |
+-------+------+ +-------+--------+
| tcp_listener | + tcp_client_sup |
+--------------+ +-------+--------+
| (simple_one_for_one)
+-----|---------+
+-------|--------+|
+--------+-------+|+
| tcp_echo_fsm |+
+----------------+
Я хотел бы расширить этот код и разрешить tcp_echo_fsm
передать контроль над сокетом одному из двух модулей: tcp_echo_addition
(чтобы вычислить сложение каждых двух значений клиента), или tcp_echo_subtraction
(чтобы вычислить вычитание между каждыми двумя значениями клиента).
tcp_echo_fsm
будет выбирать, какой модуль обрабатывать сокет, основываясь на первом сообщении от клиента, например, если клиент отправляет <<start_addition>>
тогда он передаст контроль tcp_echo_addition
,
Предыдущая диаграмма становится:
+----------------+
| tcp_server_app |
+--------+-------+
| (one_for_one)
+----------------+---------+
| |
+-------+------+ +-------+--------+
| tcp_listener | + tcp_client_sup |
+--------------+ +-------+--------+
| (simple_one_for_one)
+-----|---------+
+-------|--------+|
+--------+-------+|+
| tcp_echo_fsm |+
+----------------+
|
|
+----------------+---------+
+-------+-----------+ +-------+--------------+
| tcp_echo_addition | + tcp_echo_subtraction |
+-------------------+ +-------+--------------+
Мои вопросы:
Я на правильном пути? Является ли учебник, который я использую, хорошей отправной точкой для разработки масштабируемого TCP-сервера?
Как я могу передать управление от одного gen_fsm (а именно,
tcp_echo_fsm
) другому gen_fsm (либоtcp_echo_addition
или жеtcp_echo_subtraction
)? Или еще лучше: это правильный / чистый способ разработки сервера? Этот связанный с этим вопрос предполагает, что передача управления между gen_fsm и другим модулем не является тривиальной задачей, и в этом подходе может быть что-то не так.
1 ответ
Для 2 вы можете использовать gen_tcp:controlling_process/2
передать контроль над tcp-соединением: http://erlang.org/doc/man/gen_tcp.html.
Во-первых, я не уверен в значении порождения нового модуля, в отличие от обработки логики вычитания и сложения как части определенных состояний в вашем конечном автомате. Это создает код, который теперь выполняется за пределами вашего дерева контроля, поэтому труднее обрабатывать ошибки и перезапускать. Почему бы не определить сложение и вычитание, поскольку различные состояния в ваших конечных автоматах обрабатывают эту логику в этих двух состояниях?
Вы можете создать tcp_echo_fsm:subtraction_state/2,3
а также tcp_echo_fsm:addition_state/2,3
чтобы обработать эту логику и использовать ваше первое сообщение для перехода в соответствующее состояние, а не усложнять приложение.