java中使用akka手記三 cluster詳例__akka

來源:互聯網
上載者:User

http://www.tuicool.com/articles/m2muui

原文  http://2014.54chen.com/blog/2014/04/17/how-to-use-akka-in-java-3/ 一個例子 同樣是typesafe的經典例子。 例子提供的服務是傳輸文本。當文本發給frontend節點,它會委派backend節點,backend執行轉化任務,把結果返回給原來的用戶端。 新的backend節點和frontend節點,都可以動態地在cluster上增減。 message

 
public interface TransformationMessages {  public static class TransformationJob implements Serializable {    private final String text;//......  }  public static class TransformationResult implements Serializable {    private final String text;//.....  }  public static class JobFailed implements Serializable {    private final String reason;    private final TransformationJob job;//....  }  public static final String BACKEND_REGISTRATION = "BackendRegistration";}
backend處理邏輯
 
public class TransformationBackend extends UntypedActor {  Cluster cluster = Cluster.get(getContext().system());//...    @Override  public void onReceive(Object message) {    if (message instanceof TransformationJob) {      TransformationJob job = (TransformationJob) message;      getSender().tell(new TransformationResult(job.getText().toUpperCase()),          getSelf());    } else if (message instanceof CurrentClusterState) {      CurrentClusterState state = (CurrentClusterState) message;      for (Member member : state.getMembers()) {        if (member.status().equals(MemberStatus.up())) {          register(member);        }      }    } else if (message instanceof MemberUp) {      MemberUp mUp = (MemberUp) message;      register(mUp.member());    } else {      unhandled(message);    }  }  void register(Member member) {    if (member.hasRole("frontend"))      getContext().actorSelection(member.address() + "/user/frontend").tell(          BACKEND_REGISTRATION, getSelf());  }}
backend訂閱了cluster的事件,檢測frontend節點,還會發一條訊息告訴fontend可以使用了。 frontend節點接收使用者的任務,扔給註冊好的backend節點。 frontend節點
 
public class TransformationFrontend extends UntypedActor {  List<ActorRef> backends = new ArrayList<ActorRef>();  int jobCounter = 0;  @Override  public void onReceive(Object message) {    if ((message instanceof TransformationJob) && backends.isEmpty()) {      TransformationJob job = (TransformationJob) message;      getSender().tell(          new JobFailed("Service unavailable, try again later", job),          getSender());    } else if (message instanceof TransformationJob) {      TransformationJob job = (TransformationJob) message;      jobCounter++;      backends.get(jobCounter % backends.size())          .forward(job, getContext());    } else if (message.equals(BACKEND_REGISTRATION)) {      getContext().watch(getSender());      backends.add(getSender());    } else if (message instanceof Terminated) {      Terminated terminated = (Terminated) message;      backends.remove(terminated.getActor());    } else {      unhandled(message);    }  }}
frontend用List 儲存了backend的actor位置,有需要的時候就輪循發給backend。 getSender 本次收到訊息的上遊,一般用來回複訊息。 getContext 本actor的上下文。 getContext().watch DeathWatch,相當於watch了誰,誰有啥公開動作就會告訴我,包括掛了之類的。 ActorRef.forward與tell、ask的區別,效能最好的是tell,發完就走。ask是發完等Future,要等的話效能是個問題。forward用於從一個actor轉寄訊息給另一個actor,原始的sender資訊會被保留,在做路由、負載平衡、備份時非常有用。 運行TransformationApp sample.cluster.transformation.TransformationApp 啟動三個backend 2551 2552 0為一個cluster,啟動一個fronend。 frontend每5秒會收到一次任務,接收成功後print代碼,代碼如下:
 
system.scheduler().schedule(interval, interval, new Runnable() {      public void run() {        ask(frontend,            new TransformationJob("hello-" + counter.incrementAndGet()),            timeout).onSuccess(new OnSuccess<Object>() {          public void onSuccess(Object result) {            System.out.println(result);          }        }, ec);      }    }, ec);
frontend節點中,收到job的時候會去檢查backend註冊數是否可用了,如果有可用的就forward任務。
 
public void onReceive(Object message) {    if ((message instanceof TransformationJob) && backends.isEmpty()) {      TransformationJob job = (TransformationJob) message;      getSender().tell(          new JobFailed("Service unavailable, try again later", job),          getSender());    } else if (message instanceof TransformationJob) {      TransformationJob job = (TransformationJob) message;      jobCounter++;      backends.get(jobCounter % backends.size())              .forward(job, getContext());    } else if (message.equals(BACKEND_REGISTRATION)) {      getContext().watch(getSender());      backends.add(getSender());    } else if (message instanceof Terminated) {      Terminated terminated = (Terminated) message;      backends.remove(terminated.getActor());    } else {      unhandled(message);    }  }
在backend中有一句代碼如下:
 
void register(Member member) {    if (member.hasRole("frontend"))      getContext().actorSelection(member.address() + "/user/frontend").tell(          BACKEND_REGISTRATION, getSelf());  }
解析:backend訂閱了memberUp事件,所以在cluster中如果有memberUp了,都會執行上述代碼。 actorSelection是根據地址進行lookup,返回一個ActorSelection,可以當成本地的actor一樣tell。 代碼 本文提及代碼在 https://github.com/54chen/akka_cluster_learn


原創文章如轉載,請註明:轉載自五四陳科學院[ http://www.54chen.com ]

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.