Erlang集群RPC通道拥塞问题及解决方案
原创文章,转载请注明: 转载自系统技术非业余研究
本文链接地址: Erlang集群RPC通道拥塞问题及解决方案
Erlang的集群默认情况下是全联通的,也就是当一个节点加入集群的时候,介绍人会推荐集群里面所有的节点主动来和新加入的节点建立联系,
效果如下图:
我们这次不讲如何避免全联通而是来讲这个节点间通道的问题。
我们知道erlang的消息发送是透明的,只要调用Pid!Msg, 虚拟机和集群的基础设施会保证消息到达指定的进程的消息队列,这个是语义方面的保证。那么如果该Pid是在别的节点,这个消息就会通过节点间的rpc通道来传递。rpc模块就是基于erlang的这个语义在上面实现了远程函数调用。
目前社区推比较推荐erlang服务分层,所以层和层之间的交互基本上透过rpc来进行的。类似下图的分层结构越来越多,当大量的消息在节点间流动的话,势必会造成通道拥塞。
阻塞会导致发送进程被挂起,而rpc是单进程(gen_server)的,被挂起,rpc调用就废了。当然除了RPC, Pid!Msg 这种方式还是可以并行的走的。
这种阻塞极大的影响力系统的rt, 对性能和体验有很大的影响。
那这个问题如何定位、解决呢?Erlang很贴心的提供了一揽子解决方案:
首先是发现问题:
erlang:system_monitor(MonitorPid, Options) -> MonSettings
busy_dist_port
If a process in the system gets suspended because it sends to a process on a remote node whose inter-node communication was handled by a busy port, a message {monitor, SusPid, busy_dist_port, Port} is sent to MonitorPid. SusPid is the pid that got suspended when sending through the inter-node communication port Port.
比如说 riak_sysmon 就用了以下代码:
BusyDistPortP = get_busy_dist_port(), Opts = lists:flatten( [[{long_gc, GcMsLimit} || lists:member(gc, MonitorProps) andalso GcMsLimit > 0], [{large_heap, HeapWordLimit} || lists:member(heap, MonitorProps) andalso HeapWordLimit > 0], [busy_port || lists:member(port, MonitorProps) andalso BusyPortP], [busy_dist_port || lists:member(dist_port, MonitorProps) andalso BusyDistPortP]]), _ = erlang:system_monitor(self(), Opts),
当我们收到{monitor, SusPid, busy_dist_port, Port}消息的时候,就可以确认系统经常有阻塞问题。
那么如何解决呢?
社区早就认识到这个问题, 所以设计dist_buf_busy_limit是个可配置的值。
Read more…
Post Footer automatically generated by wp-posturl plugin for wordpress.
Recent Comments