Сетевой уровень Ejabberd не работает
Я знаю, что сервер ejabberd эффективен и разработан для обеспечения высокой производительности и отказоустойчивости, но я не понимаю, почему я вижу, что его модули слушателей обрабатывают соединения последовательно, в книге Джо Армстронга я вижу, что параллельные серверы работают следующим образом:
{ok, Listen}=gen_tcp:listen(....),
spawn(fun() ->parallel(Listen) end).
parallel(Listen) ->
{ok, Socket}=gen_tcp:accept(Listen),
spawn(fun() ->parallel(Listen) end),
handling(Socket).
handling(Socket) ->
....
Но в слушателе EJABBERD с именем ejabberd_listener.erl механизм прослушивания прост: у супервизора есть дочерние элементы рабочих, и каждый дочерний элемент представляет прослушиватель модуля с его параметрами прослушивания (порт, сетевой протокол, ip,...), есть 4 или 5 дочерних элементов. и все дочерние элементы запускают одну из двух функций при запуске: TCP или UDP, и последняя представляет функцию прослушивания для входящих подключений, и когда соединение принимается и создается Socket, прослушиватель передал Socket в качестве аргумента функции запуска Модуль и продолжайте принимать другие соединения, самая важная часть кода:
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
init_tcp(PortIP, Module, Opts, SockOpts, Port, IPS) ->
%% Some of work
....
ListenSocket = listen_tcp(PortIP, Module, SockOpts, Port, IPS),
%% Some of work
....
accept(ListenSocket, Module,.... ),
%% Some of work
....
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
listen_tcp(....) ->
Res = gen_tcp:listen(....),
%% Some of work
....
case Res of {ok, ListenSocket} ->Listensocket;
%% Some of work
....
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
accept(ListenSocket, Module,... ) ->
case gen_tcp:accept(ListenSocket) of
{ok, Socket} ->
%% Some of work
....
Module:start(....,Socket,....),
%% Some of work
....
accept(ListenSocket, Module,.... );
Совершенно ясно, что это последовательный слушатель, и он работает медленнее, чем параллельный, так почему же они не используют параллельный механизм для большей эффективности и производительности? Может быть, я что-то испортил, или это потому, что это версия сообщества, и вам нужно изменить код, так что кто имел опыт работы с Erlang и Ejabberd, может мне помочь, пожалуйста?
1 ответ
Оба варианта фактически параллельны. называет
start
функции в модуле слушателя, что, по крайней мере, в случае
ejabberd_c2s
заканчивается звонком
xmpp_stream_in:start
, который запускает новый процесс gen_server. В
ejabberd_listener
затем процесс можно позвонить
gen_tcp:accept
снова ждем очередного входящего соединения.
Фрагмент из книги Джо Армстронга делает все наоборот: он порождает новый процесс для приема дальнейших входящих соединений и обрабатывает текущее соединение в существующем процессе. Непонятно (по крайней мере, для меня), что любой из этих способов более эффективен, чем другой.