为什么 Erlang 运行时(或 RabbitMQ)会监听随机 UDP 端口?

为什么 Erlang 运行时(或 RabbitMQ)会监听随机 UDP 端口?

更新到 RabbitMQ 3.7.8 和 Erlange 21.1(centOS 6 服务器)后,netstat 显示 beam.smp 正在所有接口上监听随机 UDP 端口:

~$ sudo netstat -pnul | grep beam
udp 0 0 0.0.0.0:45224 0.0.0.0:* 7320/beam.smp

该端口每次重启时都会发生变化,并且在停止应用程序时不会关闭,但在重新启动时会发生变化:

~$ sudo rabbitmqctl stop_app
停止节点 rabbit@host 上的 rabbit 应用程序...
~$ sudo netstat -pnul | grep beam
udp 0 0 0.0.0.0:45224 0.0.0.0:* 7320/beam.smp
~$ sudo rabbitmqctl start_app
正在启动节点 rabbit@host ...
 已完成 7 个插件。
~$ sudo netstat -pnul | grep beam
udp 0 0 0.0.0.0:51001 0.0.0.0:* 7320/beam.smp
  • 禁用所有插件不会改变这种行为,所以我猜这与插件无关。
  • tcpdump 没有显示此端口上的任何活动。
  • 我在 RabbitMQ 的文档中找不到任何关于此的痕迹。
  • 我在网上找不到与此相关的任何内容
  • 在“rabbitmq-server”的代码中查找“udp”并没有给出太多信息

主要问题是这个端口是用来做什么的?作为推论,是否可以配置它?

答案1

在我看来,它是一个由 syslog_logger 模块绑定的端口,来自这个 RabbitMQ 依赖项:

https://github.com/schlagert/syslog

看起来它默认在 RabbitMQ 节点上启动,并且在启动时绑定到随机端口:

依赖关系: https://github.com/rabbitmq/rabbitmq-server/blob/c1fb658ce13ae7f14919bd784eddd3dc77ab5144/Makefile#L139

打开端口的行: https://github.com/schlagert/syslog/blob/ac8b9eecd593b8cc5a8b1de332d5d7d874e25aa9/src/syslog_logger.erl#L323-L323

根据文档,此功能默认是禁用的,但 Erlang 应用程序已启动。我猜如果禁用时不启动应用程序会更好。

如果你想亲自验证,可以这样做:

启动远程 shell 进入 Rabbit Erlang VM:

% Start remote console
erl -sname test -remsh rabbit@$HOSTNAME
% Get all the port infos from the Erlang VM
PortInfos = lists:map(fun erlang:port_info/1, erlang:ports()).
% print the result
rp(PortInfos).
% Investigate the list for one which has the {name, udp_inet} line
% something like this: 
 [{name,"udp_inet"},
  {links,[<0.77.0>]},
  {id,9568},
  {connected,<0.77.0>},
  {input,0},
  {output,0},
  {os_pid,undefined}]
% And from this you can get the linked process, and see that it is a syslog_logger process
rp(erlang:process_info(erlang:list_to_pid("<0.77.0>"))).

% The result will be something like this
[{registered_name,syslog_logger},
 {current_function,{gen_server,loop,7}},
 {initial_call,{proc_lib,init_p,5}},
 {status,waiting},
 {message_queue_len,0},
 {messages,[]},
 {links,[#Port<0.1196>,<0.76.0>]},
 {dictionary,[{'$initial_call',{syslog_logger,init,1}},
              {'$ancestors',[<0.76.0>,<0.75.0>]}]},
 {trap_exit,false},
 ......]

您可以看到该$initial_call部分,它会告诉您它是哪个模块。

目前看来,这种行为无法控制。据我所知,代码只执行发送,模块中没有实现接收。

相关内容