查看源代码 运行堆栈
启动
一个用户可能与其它用户有多个“虚拟”连接。一个 MG 最多连接到一个 MGC,而一个 MGC 可以连接到任意数量的 MG。对于每个连接,用户选择一种传输服务、一种编码方案和一个用户回调模块。
MGC 必须启动其传输服务,以便监听尝试连接的 MG。实际传输如何启动不在本应用程序的范围内。然而,必须从传输服务提供一个发送句柄(通常是套接字 ID 或主机和端口),以便能够将消息发送到正确的目的地。我们不对这个不透明的句柄做任何假设。希望它足够小,因为它会在系统中的进程之间频繁传递。
用户可以根据 Erlang/OTP 的应用程序概念在 .config 文件中静态配置,或者使用配置设置作为 megaco:start_user/2 的参数动态启动。这些配置设置稍后可以使用 megaco:update_conn_info/2 进行更新。
函数 megaco:connect/4 用于告知 Megaco 应用程序它应该监视哪个控制进程、远程用户具有哪个 MID 以及它应该使用哪个回调模块来发送消息等。当这个“虚拟”连接建立后,用户可以使用 megaco:call/3 和 megaco:cast/3 向另一端发送消息。然后,由 MG 在应用一些巧妙的算法来解决启动雪崩问题(如 RFC 中讨论的那样)后,发送其第一个服务更改请求消息。
发起用户将等待回复或超时(由 request_timer 定义)。当它收到回复时,将可选地确认(由 auto_ack 控制),并转发给用户。如果收到临时的待处理回复,则将使用 long_request_timer 而不是通常的 request_timer,以便避免错误地重新发送请求。
在目标端,传输服务等待消息。每条消息通过 megaco:receive_message/4 回调函数转发到 Megaco 应用程序。传输服务可以提供或不提供阻塞和解除阻塞接收传入消息的方式。
如果在“虚拟”连接建立之前收到消息,则会自动设置连接。MGC 可以真正开放地动态决定使用哪种编码和传输服务,具体取决于传输层的联系方式。对于 IP 传输,有两个标准化的端口,一个用于文本编码,另一个用于二进制编码。例如,如果在文本端口上收到 UDP 数据包,则可以动态决定编码和传输。
解码消息后,会调用各种用户回调函数,以允许用户正确操作。有关回调参数的更多信息,请参见 megaco_user 模块。
当用户在其回调函数中处理完事务请求后,Megaco 应用程序会组装事务回复,使用选定的编码模块对其进行编码,并通过调用回调函数将消息发送回去
- SendMod:send_message(SendHandle, ErlangBinary)
消息的重新发送、处理待处理事务、确认等由 Megaco 应用程序自动处理,但用户可以通过各种配置选项自由覆盖默认行为。有关可能性,请参阅 megaco:update_user_info/2 和 megaco:update_conn_info/2。
当连接断开(即通过 megaco:disconnect/2 显式断开或其控制进程死亡时),会调用用户回调函数,以允许用户重新建立连接。保持消息的内部状态、重新发送定时器等不受此影响。当连接断开时,一些重新发送当然会失败,但是自动重新发送算法不会理会这一点,并且最终当连接恢复正常运行时,如果超时设置足够长,消息将被传递。用户可以选择显式调用 megaco:cancel/2 来取消连接的所有消息。
MGC 启动调用流程
为了准备 MGC 接收初始消息(希望是服务更改请求),需要执行以下操作
- 启动 Megaco 应用程序。
- 启动 MGC 用户。这可以通过 megaco:start_user/2 显式完成,也可以通过提供 -megaco users 配置参数隐式完成。
- 启动传输服务,并为其提供从 megaco:user_info/2 获取的接收句柄。
当初始消息到达时,传输服务将其转发到协议引擎,协议引擎会自动设置连接,并在调用 UserMod:handle_trans_request/3 处理服务更改请求之前调用 UserMod:handle_connect/2,如下所示
MG 启动调用流程
为了准备 MG 发送初始消息(希望是服务更改请求),需要执行以下操作
- 启动 Megaco 应用程序。
- 启动 MG 用户。这可以通过 megaco:start_user/2 显式完成,也可以通过提供 -megaco users 配置参数隐式完成。
- 启动传输服务,并为其提供从 megaco:user_info/2 获取的接收句柄。
- 使用 megaco:connect/4 设置与 MGC 的连接,并为其提供从 megaco:user_info/2 获取的接收句柄。
如果 MG 已配置了 MGC 的 MID,则可以将其作为 RemoteMid 参数提供给 megaco:connect/4,并且调用流程将如下所示
如果无法为 MG 配置 MGC 的 MID,则 MG 可以使用原子 'preliminary_mid' 作为 RemoteMid 参数传递给 megaco:connect/4,并且调用流程将如下所示
配置 Megaco 堆栈
有三种配置
用户信息 - 与 megaco 用户相关的信息。读/写。
用户是由 MID 标识的实体,例如 MGC 或 MG。
可以使用 megaco:user_info 检索此信息。
连接信息 - 关于连接的信息。读/写。
可以使用 megaco:conn_info 检索此信息。
系统信息 - 系统范围的信息。只读。
可以使用 megaco:system_info 检索此信息。
初始配置
Megaco 的初始配置应在 Erlang 系统配置文件中定义。为 Megaco 应用程序定义了以下配置参数
users = [{Mid, [user_config()]}].
每个用户由一个元组表示,其中包含用户的 MID 和配置参数列表(每个参数又是一个元组:
{Item, Value}
)。scanner = flex | {Module, Function, Arguments, Modules}
flex
将导致启动具有默认选项的 flex 扫描器。- MFA 替代方案使 Megaco 可以启动和监视由用户编写的扫描器(有关参数的说明,请参阅
supervisor:start_child
)。
有关更多信息,另请参阅 文本编码模块的配置。
更改配置
可以在运行时更改配置。这是通过函数 megaco:update_user_info 和 megaco:update_conn_info 完成的
事务发送器
事务发送器是一个进程(每个连接一个),如果配置了,则处理所有事务发送(请参阅 megaco:user_info 和 megaco:conn_info)。
事务发送器的目的是积累事务,以提高消息发送效率。积累的事务是事务请求和事务确认。对于事务确认,好处非常大,因为事务很小,并且可以有范围(这意味着事务 1、2、3 和 4 的事务确认可以作为一个范围 1-4 在一个事务确认中发送,而不是四个单独的事务)。
有许多配置参数控制事务发送器的操作。原则上,当满足以下条件时,从进程发送一条存储了所有内容(确认和请求)的消息
- 当
trans_timer
过期时。 - 当收到
trans_ack_maxcount
个确认时。 - 当收到
trans_req_maxcount
个请求时。 - 当所有收到的请求的大小超过
trans_req_maxsize
时。 - 当发送回复事务时。
- 当发送待处理事务时。
当要发送内容时,所有内容都会打包成一条消息,除非触发器是回复事务,并且回复和所有请求的增加大小大于 trans_req_maxsize
,在这种情况下,存储的事务会首先在单独的消息中发送,而回复会在另一条消息中发送。
当事务发送器收到一个已经“存储”的请求(由事务 ID 指示)时,它会被假定为重新发送,并且会发送所有存储的内容。如果 trans_timer
和 request_timer
的值选择不当,可能会发生这种情况。
事务回复的分段
在 Megaco 标准的第 3 版中,引入了 分段包
的概念。简单来说,该包定义了一种在传输层不自动执行分段(例如 UDP)时,对 Megaco 消息(事务回复)进行分段的程序。
尽管在已经执行分段的传输层(例如 TCP)上使用分段既无意义又适得其反,但 Megaco 应用程序并不检查这一点。相反,这需要用户正确配置。
接收分段消息
这由 Megaco 应用程序自动处理。但是,有一件事需要用户配置,即 segment_recv_timer 选项。
请注意,根据用于发出原始请求的函数,分段将以不同的方式传递给用户。当使用 megaco:cast 函数发出请求时,分段将通过 handle_trans_reply 回调函数逐个传递给用户,因为它们会到达。但这显然不适用于 megaco:call 函数。在这种情况下,分段会累积,然后作为函数返回时一次性全部传递。
发送分段消息
这也由 Megaco 应用程序自动处理。首先,只有在配置了的情况下才会尝试分段,请参阅 segment_send 选项。其次,Megaco 依赖于所使用的编解码器编码操作回复的能力,这是 Megaco 应用程序在分段时处理的最小组件。第三,只有当操作回复的大小总和(加上任意的消息头大小)大于指定的最大消息大小(请参阅 max_pdu_size 选项)时,才会对回复进行分段。最后,如果决定进行分段,则每个操作回复都将构成其自己的(分段)消息。