2017-09-26 3 views
2

는 지금은 분산 응용 프로그램을 구축하고 있고 사용하여 RPC로 찾고 있어요 : 캐스트를 RPC 대 : 나는 호출 프로세스가 반환 값에 기다리고 싶지 않기 때문에 전화, 또는 하나가 나타납니다. 출연진과 전화 ​​:rpc : cast를 실행하는 프로세스는 무엇입니까?

캐스팅이 완벽하게 작동하지만 나는 호기심, 어떤 프로세스는 RPC에 의해 전달 함수를 실행? 과소/동시 실행 부족에 대해 걱정해야합니까? 내가 코드를 실행하는 다른 프로세스를 할 때

일반적으로, 나는 노동자의 풀을 사용하고 그 중 하나 gen_server와 비동기 캐스트를 보내/2를 캐스팅하고 그것을 처리 할 수 ​​있습니다. 그러나 RPC의 경우 어떤 프로세스가 계산을 수행하는지 정의하지 않습니다. 프로세스가 사전 할당되어 대기 중입니까? 또는 rpc가 해당 프로세스를 호출하고 종료 할 때마다 모든 프로세스가 생성됩니까? 내가 읽은 것으로부터, 많은 호출을하는 경우 이것은 매우 비효율적입니다. 프로세스가 단지 생성되고 파괴되기 때문에 계산 상 쉽지 않습니다.

미리 도움을 주셔서 감사합니다.

답변

1

TL; DR은 :

방법은 RPC를 처리하기 위해 상기 타겟 노드 스폰.

토론

우리는 RPC 모듈의 코드를 살펴 경우, 우리가 disterl에 기본이되는 일반 노드 간 메시징 기능을 래핑 볼 :

https://github.com/erlang/otp/blob/master/lib/kernel/src/rpc.erl#L398-L403

-spec cast(Node, Module, Function, Args) -> true when 
     Node :: node(), 
     Module :: module(), 
     Function :: atom(), 
     Args :: [term()]. 

cast(Node, Mod, Fun, Args) when Node =:= node() -> 
    catch spawn(Mod, Fun, Args), 
    true; 
cast(Node, Mod, Fun, Args) -> 
    gen_server:cast({?NAME,Node}, {cast,Mod,Fun,Args,group_leader()}), 
    true. 

현재 일어나고있는 일은 캐스트가 현재 노드에서 호출 될 때 새 프로세스이 제공된 MFA와 함께 스폰됩니다. 처형되다. 대/소문자가 다른 노드에서 호출되는 경우 메시지는 gen_server:cast/2을 통해 표시된 노드의 그룹 리더에게 전송되고 대상 노드의 그룹 리더는 MFA를 처리하는 프로세스를 생성합니다.

캐스트에 대한 처리 코드는 여기에 있습니다 :

https://github.com/erlang/otp/blob/master/lib/kernel/src/rpc.erl#L130-L139 당신은 이미 당신을 처리 다른 노드로 메시지를 파견하려는 알고 경우

-spec handle_cast(term(), state()) -> {'noreply', state()}. 

handle_cast({cast, Mod, Fun, Args, Gleader}, S) -> 
    spawn(fun() -> 
      set_group_leader(Gleader), 
      apply(Mod, Fun, Args) 
     end), 
    {noreply, S}; 
handle_cast(_, S) -> 
    {noreply, S}. % Ignore ! 

, 다음 노드의 메쉬를 슈퍼 노드로 취급하고, rpc 모듈을 완전히 우회하여 gen_server 호출을 작성하거나 직접 전달할 수 있습니다. 물론 어떤 접근 방식을 사용하는 것이 취향과 아키텍처의 문제인지는 물론입니다.

+0

그래서 node1이 node2에서 rpc를 수신 할 때마다 내가 읽었던 완전히 새로운 프로세스를 생성해야하기 때문에 rpc 통신을 많이 보내지 않는 것이 좋습니다. – Ryan

+0

노드에 대한 미리 정의 된 정보를 얻고 gen_server를 보내려면 다른 방법을 제안하십시오. cast() - 이상적으로 1) 새로운 프로세스가 생성되지 않도록 (시간이 걱정되는) 풀을 사용하려는 경우 2) 의 메시지가 오면 동시성이 제한됩니다. 어떻게하면 프로세스 ID를 알 수 있습니까? 프로세스 id를 얻으려면 먼저 node2에서 node2의 grpoc_get_worker 형식을 참조해야합니다. 이 문제에 대해 일반적으로 받아 들여지는 해결책이 있습니까, 아니면 모두가 다르게하는 "수정"입니까? – Ryan

+1

@ 라이언 사실, 나는 너에게 좋은 소식이있다! 얼랑 (Erlang)에서의 스폰 프로세스는 시간, 메모리 및 CPU면에서 매우 가볍습니다 *. 다른 노드와 통신 할 때 발생하는 네트워크 통신 및 대기 시간은'rex' 작업보다 훨씬 비쌉니다. 따라서 상대방에'rex'가 하나 밖에 없더라도 요청에 너무 심하게 스팸 메일을 보낼 수 있습니다. 'rex' 작업의 오버 헤드는 무시할 수 있습니다. RPC가 적합한 경우 계산이 상당히 복잡하다면 캐스트 비용은 오버 헤드 우려가 가장 적습니다. – zxq9

1

프로세스의 이름은 rex입니다. apply(M, F, A)을 실행하는 프로세스를 생성하는 등록 된 프로세스입니다.

https://github.com/erlang/otp/blob/master/lib/kernel/src/rpc.erl#L28

https://github.com/erlang/otp/blob/master/lib/kernel/src/rpc.erl#L402

은 BTW, 모든 rpc:call/4rpc:cast/4 및 다른 매개 변수 확장 성을 제한하는 하나 개의 프로세스를 통해 이동을 의미합니다. rpc 모듈은 높은 처리량을 목적으로하지 않습니다.

+0

그들은'rex'를 통해 전달하지만,'rex'는'call_block'을 보내지 않는 한 각각의 작업을 실제로 실행하기 위해 별도의 작업자를 생성합니다 ('rex'는 그것 자신을 실행합니다). – zxq9

+0

네, 맞습니다. 'rex'는 실제 작업을 수행하는 프로세스를 생성합니다. 나는 대답을 편집한다. –

+1

얼랑 (Erlang)에서의 산란이 너무 빠르기 때문에 큰 성능 병목 현상의 놀라움은 사람들이 크고 작은 메시지를 보내는 것 사이에 사람들이 겪게 될 차이라고 생각합니다. rpc 호출에 대한 인수가 바이트 측면에서 거대한 경우 이상한 동작이 발생할 수 있습니다. 또는 연결 속도가 느리거나 대기 시간이 긴 경우 RPC는 꽤 빠르게 복잡해 지지만, 스폰 부분이 모든 오버 헤드 중 가장 작은 부분이라고 생각합니다 (8 마이크로 초 정도의 순서로, 네트워크 대기 시간은 보통 이것보다 길어질 것입니다). – zxq9