문제

본 후 이 기사, 나는 Mochiweb와 함께 땜질을 해왔다. 기사에서 수행 한 작업을 복제하려고하는 동안 - 기본적으로 Mochiweb 서버를 설정하고, 두 개의 Erlang 노드가있는 다음 다른 노드에서 한 노드에서 정의 된 함수를 호출합니다 (Net_adm : ping ()을 두 노드 사이에 설정 한 후 각각을 알 수 있습니다. 다른).

나는 그 기능 호출 부분이 될 때까지 모든 것을 따를 수 있었다. Mochiweb 서버 인 N1@localhost에서 나는 (기사에서와 같이) 호출합니다.

router:login(IdInt, self()).

그런 다음 라우터 .ERL 스크립트 인 N2@LocalHost에서 로그인 기능을 정의했습니다.

login(Id, Pid) when is_pid(Pid) ->
    gen_server:call(?SERVER, {login, Id, Pid}).

handle_call({login, Id, Pid}, _From, State) when is_pid(Pid) ->
          ets:insert(State#state.pid2id, {Pid, Id}),
          ets:insert(State#state.id2pid, {Id, Pid}),
          link(Pid), % tell us if they exit, so we can log them out
          io:format("~w logged in as ~w\n",[Pid, Id]),
          {reply, ok, State};

코드의 관련 부분 만 붙여 넣었습니다. 그러나 이제 브라우저에서 웹 서버에 액세스하면 N1@LocalHost 에서이 오류 보고서를받습니다.

=CRASH REPORT==== 11-Jun-2009::12:39:49 ===
  crasher:
    initial call: mochiweb_socket_server:acceptor_loop/1
    pid: <0.62.0>
    registered_name: []
    exception error: undefined function router:login/2
      in function  mochiconntest_web:loop/2
      in call from mochiweb_http:headers/5
    ancestors: [mochiconntest_web,mochiconntest_sup,<0.59.0>]
    messages: []
    links: [<0.61.0>,#Port<0.897>]
    dictionary: [{mochiweb_request_path,"/test/123"}]
    trap_exit: false
    status: running
    heap_size: 1597
    stack_size: 24
    reductions: 1551
  neighbours:

=ERROR REPORT==== 11-Jun-2009::12:39:49 ===
{mochiweb_socket_server,235,{child_error,undef}}

인터넷 검색 후에, 나는 오류가 말하는 것에 대한 기본 요점을 얻었습니다. 기본적으로 n1@localhost에서 호출되는 로그인 함수는 정의되지 않았지만 n2@localhost에 정의되어 있습니다 (그리고 두 노드는 각각을 알고 있습니다. 다른 것 - 나는했다 nodes(). 확인하다) !! 내가 어디에서 잘못 될지 알려주세요!

도움이 되었습니까?

해결책

Right are aright -Router 용 코드 : 로그인은 실제로 호스트 N1@localhost에서 사용할 수 없습니다. 해당 함수 내 코드 (Gen_Server : Call Function)는 호출을 N2@LocalHost (That? Server Macro)로 라우팅하는 코드입니다. 그리고 그것이 실제 구현이있는 곳입니다. 최상위 기능은 단순히 해당 호출을 적절한 노드로 마무리하는 방법입니다.

하지만 최소한 로그인 구현이 필요합니다.

login(Id, Pid) when is_pid(Pid) ->
    gen_server:call(?SERVER, {login, Id, Pid}).

N1@localhost에서 사용할 수 있습니다.

(업데이트)

당신은 서버 매크로를 정의, 교체 또는 우리에게도 정의해야합니다. 기사의 샘플 코드에서 이것은입니다

-define(SERVER, global:whereis_name(?MODULE)).

그러나 이것은 귀하의 경우 잘못된 모듈 매크로를 사용합니다. 기본적으로 gen_server 프로세스 (라우터)가 시작될 때는? 모듈 자체로 등록됩니다.이 경우 다른 노드가 볼 수있는 원자 '라우터'에 맵핑됩니다 (Global : whereis_name (라우터)). 그래서 당신은 그냥 쓸 수 있어야합니다.

login(Id, Pid) when is_pid(Pid) ->
    gen_server:call(global:whereis_name(router), {login, Id, Pid}).

따라서 N1@localhost에서 로그인을 호출하는 효과는 라우터 gen_server 프로세스가 실행 중이며 자체적으로 등록되었다고 가정 할 때 N2@localhost의 handle_call 메소드를 라우터로 호출 할 수 있습니다. 해당 통화의 반환 값은 N1@LocalHost의 프로세스로 돌아옵니다.

다른 팁

질문의 예에서는 당신이로드 한 것처럼 보입니다. router 한 노드의 모듈. 노드는 기본적으로 서로로드 코드를 자동으로로드하지 않으므로 기능이 N2에서 정의되어 있다고해서 N1에서 로컬로 호출 할 수 있다는 의미는 아닙니다 (N1은 일반적인 방식으로로드 할 수 있어야합니다).

주어진 코드는 분산 시스템에서 실행되는 상태에서 올바르게 대처하는 것처럼 보입니다 (한 노드에서 라우터 서버를 시작하고 다른 노드에서 API 기능을 호출하면 라우터 요청을 올바른 위치로 보냅니다). 그래서 당신은 단지 router N1의 모듈은 작동해야합니다. N1을로드 할 수 있습니다 router N2의 모듈이지만 N1에게 코드 경로에 모듈의 사본을 제공하는 것과 비교할 때 약간의 번거 로움입니다.

흥미롭게도 라우터 코드에서는 불필요합니다. gen_server:call(global:whereis_name(?MODULE, Message)). 로서 gen_server:call/2 기능은 글로벌 등록 자체를 조회하는 방법을 알고 있습니다. -define(SERVER, {global, ?MODULE}). start_link 함수를 변경하면 잘 작동합니다. start_link() -> gen_server:start_link(?SERVER, ?MODULE, [], []).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top