我正在创建一个通用的Erlang服务器,它应该能够同时处理数百个客户端连接。为简单起见,我们假设服务器为每个客户端执行一些基本计算,例如,添加或减少客户端提供的每两个值。
作为一个起点,我使用this tutorial进行基本的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
(计算每两个客户端值的添加),或{ {1}}(计算每两个客户端值之间的减法)。
tcp_echo_subtraction
将根据来自客户端的第一条消息选择处理套接字的模块,例如,如果客户端发送tcp_echo_fsm
,则它会将控制传递给<<start_addition>>
。
上图变为:
tcp_echo_addition
我的问题是:
我是在正确的道路上吗?我正在使用的教程是可扩展TCP服务器设计的良好起点吗?
如何将控件从一个gen_fsm(即 +----------------+
| tcp_server_app |
+--------+-------+
| (one_for_one)
+----------------+---------+
| |
+-------+------+ +-------+--------+
| tcp_listener | + tcp_client_sup |
+--------------+ +-------+--------+
| (simple_one_for_one)
+-----|---------+
+-------|--------+|
+--------+-------+|+
| tcp_echo_fsm |+
+----------------+
|
|
+----------------+---------+
+-------+-----------+ +-------+--------------+
| tcp_echo_addition | + tcp_echo_subtraction |
+-------------------+ +-------+--------------+
)传递给另一个gen_fsm(tcp_echo_fsm
或tcp_echo_addition
)?或者更好的是:这是设计服务器的正确/干净方式吗?
这个related question表明在gen_fsm和另一个模块之间传递控制并不是微不足道的,这种方法可能有问题。
答案 0 :(得分:3)
对于2,您可以使用gen_tcp:controlling_process/2
来传递对tcp连接的控制:http://erlang.org/doc/man/gen_tcp.html#controlling_process-2。
对于1,我不确定产生新模块的价值,而不是将减法和加法逻辑作为有限状态机中定义状态的一部分。这样做会创建现在在监督树之外运行的代码,因此处理错误和重新启动会更加困难。为什么不将加法和减法定义为状态机中的不同状态来处理这两种状态中的逻辑?
您可以创建tcp_echo_fsm:subtraction_state/2,3
和tcp_echo_fsm:addition_state/2,3
来处理此逻辑,并使用您的第一条消息转换到适当的状态,而不是为您的应用添加复杂性。