Назад | Перейти на главную страницу

Почему среда выполнения 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
Stopping rabbit application on node rabbit@host ...
~$ sudo netstat -pnul | grep beam
udp        0      0 0.0.0.0:45224          0.0.0.0:*             7320/beam.smp
~$ sudo rabbitmqctl start_app
Starting node rabbit@host ...
 completed with 7 plugins.
~$ sudo netstat -pnul | grep beam
udp        0      0 0.0.0.0:51001          0.0.0.0:*             7320/beam.smp

Главный вопрос - для чего используется этот порт? Как следствие, можно ли это настроить?

Мне кажется, это порт, связанный с модулем 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 запущено. Думаю, было бы лучше, если бы приложение не запускалось, когда оно отключено.

Если вы хотите убедиться в этом сами, вы можете сделать это:

Запустите удаленную оболочку в виртуальной машине Rabbit Erlang:

% 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 часть, он сообщает вам, какой это модуль.

В настоящее время не похоже, что это поведение можно контролировать. Код выполняет только отправку, как я вижу, в модуле не реализован прием.