gen_server, сервер не может вызывать свои собственные функции API?
Когда я прочитал книгу Erlang OTP Action, я обнаружил это напоминание на странице 117:
Используя свой RPC-сервер, вы можете попробовать вызвать любую функцию, экспортированную из любого модуля, доступного на стороне сервера, кроме одной: вашего собственного tr_server: get_count / 0. В общем, сервер не может вызывать свои собственные функции API. Предположим, вы выполняете синхронный вызов того же сервера из одной из функций обратного вызова: например, если handle_info / 2 пытается использовать функцию API get_count / 0. Затем он выполнит gen_server: call(...) самому себе. Но этот запрос будет помещен в очередь до тех пор, пока не завершится текущий вызов handle_info / 2, что приведет к циклическому ожиданию - сервер окажется в тупике.
Но я посмотрел пример кода tr_server:
get_count() ->
gen_server:call(?SERVER, get_count).
stop() ->
gen_server:cast(?SERVER, stop).
handle_info({tcp, Socket, RawData}, State) ->
do_rpc(Socket, RawData),
RequestCount = State#state.request_count,
{noreply, State#state{request_count = RequestCount + 1}};
......
do_rpc(Socket, RawData) ->
try
{M, F, A} = split_out_mfa(RawData),
Result = apply(M, F, A), % tr_server process -> handle_info -> do_rpc ->call & cast
gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Result]))
catch
_Class:Err ->
gen_tcp:send(Socket, io_lib:fwrite("~p~n", [Err]))
end.
Я обнаружил, что примеры и предостережения в книге несовместимы, gen_server: call и gen_server: кастуются самим процессом tr_server. Я неправильно это истолковываю?
1 ответ
Звонок
gen_server:cast
изнутри серверного процесса все в порядке, потому что он асинхронный: он добавляет сообщение в почтовый ящик процесса, а затем продолжает, возвращая
ok
. Только
gen_server:call
имеет эту проблему, потому что заставляет процесс ждать ответа от самого себя.