erlang에서 메시지가 손실되는 문제가 있습니다.erlang에서 메시지가 손실 됨
내가 사용하고있는 코드는 수동으로 사용할 때만 유효합니다. 많은 코드와 병렬로 코드를 테스트하는 '로드 테스트'에서 코드를 사용하는 경우에만 일부 메시지가 수신되지 않습니다. 수신기 부분에서. 모든 단계와 매개 변수 값을 기록 할 때 메시지를 보내는 주소가 정확한지 확인했습니다. 또한 메시지 자체에는 문제가 없습니다.
제 질문은 다음과 같습니다 : erlang에있는 '메시지 분실'에 대한 지식이 있습니까? 아직 erlang에 버그가 있습니까?
필자는 필요한 경우 일부 코드를 게시 할 수 있지만 특히이 질문에 많은 가치를 부여 할 것이라고 생각하지 않습니다.
업데이트 : 내 응용 프로그램의 주요 부분. 이것은 내 문제를 설명하기 위해 꽤 많은 코드이지만 단순화 된 버전에서 문제를 재현 할 수는 없습니다. 응용 프로그램은 할당 시스템입니다. 즉, 병렬로 그리드에 셀 모음을 예약합니다. 중요한 부분은 전체 할당 시스템을 제어하는 액터 인 globalManager입니다. rowManager는 전체 표의 한 행을 관리하며 예약이 이루어지면 해당 행을 잠글니다. 셀 영역을 예약해야하는 경우 request_specific_cells 함수가 호출됩니다. 이 함수는 행을 수정해야하는 모든 rowmanagers에게 예약 요청을 보냅니다. 행 관리자가 행의 영역을 예약하면 globalManager에 확인을 보냅니다. 모든 행 관리 프로그램이 확인을 보내면 요청을 시작한 프로세스로 확인이 전송되고 관리자 중 하나가 실패하면 globalmanager가 실패를 보냅니다.
globalManager(Grid) ->
receive
{Pid, request_specific_cells, ReservationId, Coordinates, Ctr, XX} ->
NewGrid = request_specific_cells(Grid, Pid, ReservationId, Coordinates, Ctr, XX);
{Pid, confirm_region, ResId, Rid, Sid, Region, Section, Ctr, XX} ->
NewGrid = confirm_region(Grid, Pid, ResId, Rid, Sid, Region, Section, Ctr, XX);
{Pid, failed_region, Rid, Region, Ctr, XX} ->
NewGrid = failed_region(Grid, Pid, Rid, Region, Ctr, XX);
Else ->
erlang:display({unexpectedMessage, actor, Else}),
NewGrid = Grid
end,
globalManager(NewGrid).
request_specific_cells(Grid, Pid, ReservationId, Coordinates, Ctr, XX) ->
{{Width, Height}, GridRows, MaxAllocationSize, FreeCells, {UnspecificRequests, NextId}, PendingRequests, BlockedRows} = Grid,
{X, Y, W, H} = Coordinates,
Rows = lists:seq(Y,Y+H-1),
% Is one of the blocks that have to be reserved currently blocked?
BlockedRow = lists:foldl(fun(B, Acc) -> Acc xor search_list(B,BlockedRows) end, false, Rows),
Request = lists:keyfind(ReservationId, 1, UnspecificRequests),
{ReservationId, _} = Request,
% Now we need the addresses of the sections in which the regions has to be reserved.
SubSectionIds = [ SPid || {_,SPid} <- [ lists:keyfind(Row, 1, GridRows) || Row <- Rows]],
% Storing request enables us to rollback if one of the registrations fails.
NewPendingRequests = PendingRequests ++ [{length(PendingRequests), 0, lists:map(fun(S) -> {S,null} end, SubSectionIds)}],
% Send a registration command with the needed section to each corresponding section manager.
[SPid ! {self(), request, Pid, ReservationId, length(PendingRequests), Coordinates, Ctr, XX} || SPid<- SubSectionIds],
NewBlockedRows = Rows ++ BlockedRows,
{{Width, Height}, GridRows, MaxAllocationSize, FreeCells, {UnspecificRequests, NextId}, NewPendingRequests, NewBlockedRows}
end.
confirm_region(Grid, Pid, URid, Rid, Sid, Region, Section, Cttr, XX) ->
{Dimensions, GridRows, MaxAllocationSize, FreeCells, {UnspecificRequests, NextId}, PendingRequests, BlockedRows} = Grid,
{_,RY,_,_} = Region,
if
% All blocks have confirmed the reservation so the entire request is successful
(Ctr+1) == length(Spids) ->
NewUnspecificRequests = lists:keydelete(URid, 1, UnspecificRequests),
NewPendingRequests = lists:keydelete(Rid, 1, PendingRequests),
NewSpids = lists:keyreplace(Sid, 1, Spids, {Sid, Section}),
[Spid ! {self(), confirm_region, Sec} || {Spid, Sec} <- NewSpids],
Pid ! {self(), request_specific_cells, Rid, success};
true ->
NewUnspecificRequests = UnspecificRequests,
% Safe the region that has to be marked/rolled back in the row
NewSpids = lists:keyreplace(Sid, 1, Spids, {Sid, Section}),
% Increase counter of confirmations
NewPendingRequests = lists:keyreplace(Rid, 1, PendingRequests, {Rid, Ctr+1, NewSpids})
end,
NewBlockedRows = delete_list(RY, BlockedRows)
{Dimensions, GridRows, MaxAllocationSize, FreeCells, {NewUnspecificRequests, NextId}, NewPendingRequests, NewBlockedRows}.
rowManager(Row) ->
receive
{Mid, request, Pid, URid, Rid, Region, Ctr, XX} ->
NewRow = request_region(Row, Mid, Pid, URid, Rid, Region, Ctr, XX);
Else ->
erlang:display({unexpectedMessage, rowManager, Else}),
NewRow = Row
end,
rowManager(NewRow).
request_region(Row, Mid, Pid, URid, Rid, Coordinates, Ctr, XX) ->
{RY, Content, Modified} = Row,
{X,_,W,_} = Coordinates,
if
Modified == false ->
Free = region_is_empty({X,1,W,1}, Content),
if
Free -> NewModified = true,
NewContent = mark_region({X,1,W,1}, Content, reserved),
Mid ! {Pid, confirm_region, URid, Rid, self(), Coordinates, {X,1,W,1}, Ctr, XX};
true -> NewModified = false,
NewContent = Content,
Mid ! {Pid, failed_region, Rid, Coordinates, Ctr, XX}
end;
true -> NewModified = false,
NewContent = Content,
Mid ! {Pid, failed_region, Rid, Coordinates, Ctr, XX}
end,
{RY, NewContent, NewModified}.
이 코드는 리저버로 사용됩니다
request_specific_cells(FollowUpPid, ReservationId, {X, Y, Width, Height}, Ctr, XX) ->
FollowUpPid ! {self(), request_specific_cells, ReservationId, {X, Y, Width, Height}, Ctr, XX},
receive
{FollowUpPid, request_specific_cells, ReservationId, SuccessOrFailure} ->
SuccessOrFailure
end.
내가 대답을 받기 전에 내가 알고 있기 때문에이 수신기가 사망 있다고 생각 확인/9에서
Pid ! {self(), request_specific_cells, Rid, success}
그 함수는 항상 올바른 값으로 실행되지만 함수에서 항상 수신되는 것은 아닙니다.
'분실 메시지'에 대해 들어 보지 못했습니다. 그러나 우리는 몇 가지 코드를 사용하여이 문제의 원인을 파악할 수 있습니다. 그러나 메시지가 예상대로 전달되지 않을 수 있습니다. 또한 대부분의 경우 수신자가 사망하면 메시지가 손실됩니다. –
한 노드 내에서 메시지가 손실되지 않습니다! 보낸 메시지가 도착합니다. "틀린"장소에서 이러한 메시지를받을 수있는 일반 수신 패턴이 있습니까? – rvirding
@MuzaayaJoshua 메시지와 주소가 모두 정확하기 때문에 내 문제의 원인은 수신자가 죽는 것입니다. 수신 된 메시지가 있기 전에 수신자가 왜 죽을 수 있습니까? 어떻게 이것을 막을 수 있습니까? 나는 내 문제에 대한 더 많은 정보를 줄 수있는 원래의 코드를 제공하려고 노력할 것이다. – Consec