Akka Remote Actor_简单示例一
参照Typesafe的activator-1.2.12生成的示例。
通过akka的配置文件来配置remote actor。
首先实现一个计算加减乘除的remote actor,如下,
package com.usoft9; import akka.actor.UntypedActor; /** * 计算加减乘除的Actor * getSender * getSelf */ public class CalculatorActor extends UntypedActor { @Override public void onReceive(Object message) { if (message instanceof Op.Add) { Op.Add add = (Op.Add) message; System.out.println("Calculating " + add.getN1() + " + " + add.getN2()); Op.AddResult result = new Op.AddResult(add.getN1(), add.getN2(), add.getN1() + add.getN2()); getSender().tell(result, getSelf()); } else if (message instanceof Op.Subtract) { Op.Subtract subtract = (Op.Subtract) message; System.out.println("Calculating " + subtract.getN1() + " - " + subtract.getN2()); Op.SubtractResult result = new Op.SubtractResult(subtract.getN1(), subtract.getN2(), subtract.getN1() - subtract.getN2()); getSender().tell(result, getSelf()); } else if (message instanceof Op.Multiply) { Op.Multiply multiply = (Op.Multiply) message; System.out.println("Calculating " + multiply.getN1() + " * " + multiply.getN2()); Op.MultiplicationResult result = new Op.MultiplicationResult( multiply.getN1(), multiply.getN2(), multiply.getN1() * multiply.getN2()); getSender().tell(result, getSelf()); } else if (message instanceof Op.Divide) { Op.Divide divide = (Op.Divide) message; System.out.println("Calculating " + divide.getN1() + " / " + divide.getN2()); Op.DivisionResult result = new Op.DivisionResult(divide.getN1(), divide.getN2(), divide.getN1() / divide.getN2()); getSender().tell(result, getSelf()); } else { unhandled(message); } } }
这个remote actor和本地actor没有什么区别。
相关的类如下,
package com.usoft9; import java.io.Serializable; public class Op { public interface MathOp extends Serializable { } public interface MathResult extends Serializable { } static class Add implements MathOp { private static final long serialVersionUID = 1L; private final int n1; private final int n2; public Add(int n1, int n2) { this.n1 = n1; this.n2 = n2; } public int getN1() { return n1; } public int getN2() { return n2; } } static class AddResult implements MathResult { private static final long serialVersionUID = 1L; private final int n1; private final int n2; private final int result; public AddResult(int n1, int n2, int result) { this.n1 = n1; this.n2 = n2; this.result = result; } public int getN1() { return n1; } public int getN2() { return n2; } public int getResult() { return result; } } static class Subtract implements MathOp { private static final long serialVersionUID = 1L; private final int n1; private final int n2; public Subtract(int n1, int n2) { this.n1 = n1; this.n2 = n2; } public int getN1() { return n1; } public int getN2() { return n2; } } static class SubtractResult implements MathResult { private static final long serialVersionUID = 1L; private final int n1; private final int n2; private final int result; public SubtractResult(int n1, int n2, int result) { this.n1 = n1; this.n2 = n2; this.result = result; } public int getN1() { return n1; } public int getN2() { return n2; } public int getResult() { return result; } } static class Multiply implements MathOp { private static final long serialVersionUID = 1L; private final int n1; private final int n2; public Multiply(int n1, int n2) { this.n1 = n1; this.n2 = n2; } public int getN1() { return n1; } public int getN2() { return n2; } } static class MultiplicationResult implements MathResult { private static final long serialVersionUID = 1L; private final int n1; private final int n2; private final int result; public MultiplicationResult(int n1, int n2, int result) { this.n1 = n1; this.n2 = n2; this.result = result; } public int getN1() { return n1; } public int getN2() { return n2; } public int getResult() { return result; } } static class Divide implements MathOp { private static final long serialVersionUID = 1L; private final double n1; private final int n2; public Divide(double n1, int n2) { this.n1 = n1; this.n2 = n2; } public double getN1() { return n1; } public int getN2() { return n2; } } static class DivisionResult implements MathResult { private static final long serialVersionUID = 1L; private final double n1; private final int n2; private final double result; public DivisionResult(double n1, int n2, double result) { this.n1 = n1; this.n2 = n2; this.result = result; } public double getN1() { return n1; } public int getN2() { return n2; } public double getResult() { return result; } } }
那么问题来了,如何与这个remote actor交互?使用Patterns.ask来与remote actor交互。如下是示例代码,
首先来看remote actor的配置,如下,
common.conf
akka { actor { provider = "akka.remote.RemoteActorRefProvider" } remote { netty.tcp { hostname = "127.0.0.1" } } }
calculator.conf
include "common" akka { # LISTEN on tcp port 2552 remote.netty.tcp.port = 2552 }
启动remote actor并与之交互,如下,代码可能写的有点复杂,但思路还是比较清楚的,要结合前面的Future部分知识点,不过用IDE来代码提示很轻松。
package com.usoft9; import akka.actor.ActorRef; import akka.actor.ActorSystem; import akka.actor.Props; import akka.dispatch.Futures; import akka.dispatch.OnSuccess; import akka.japi.Function; import akka.pattern.Patterns; import akka.util.Timeout; import com.typesafe.config.ConfigFactory; import scala.Function1; import scala.PartialFunction; import scala.concurrent.Await; import scala.concurrent.Future; import scala.concurrent.duration.Duration; import scala.runtime.BoxedUnit; import java.util.Arrays; import java.util.concurrent.Callable; /** * Created by liyanxin on 2015/1/19. */ public class RemoteActorDemo { public static void main(String args[]) { //不使用默认的配置,而是选择加载选定的remote actor配置 final ActorSystem system = ActorSystem.create("CalculatorWorkerSystem", ConfigFactory.load(("usoft9/calculator"))); //remote actor的ref final ActorRef calculatorActor = system.actorOf(Props.create(CalculatorActor.class), "CalculatorActor"); System.out.println("Started CalculatorWorkerSystem"); final Timeout timeout = new Timeout(Duration.create(5, "seconds")); Future<Object> addFuture = Patterns.ask(calculatorActor, new Op.Add(1, 2), timeout); Future<Object> subtractFuture = Patterns.ask(calculatorActor, new Op.Subtract(1, 2), timeout); Future<Object> multiplyFuture = Patterns.ask(calculatorActor, new Op.Multiply(1, 2), timeout); Future<Object> divideFuture = Patterns.ask(calculatorActor, new Op.Divide(1, 2), timeout); Iterable<Future<Object>> futureArray = Arrays.asList(addFuture, subtractFuture, multiplyFuture, divideFuture); Future<Iterable<Op.MathResult>> futureResult = Futures.traverse(futureArray, new Function<Future<Object>, Future<Op.MathResult>>() { @Override public Future<Op.MathResult> apply(final Future<Object> param) throws Exception { return Futures.future(new Callable<Op.MathResult>() { @Override public Op.MathResult call() throws Exception { return (Op.MathResult) Await.result(param, timeout.duration()); } }, system.dispatcher()); } }, system.dispatcher()); futureResult.onSuccess(new OnSuccess<Iterable<Op.MathResult>>() { @Override public void onSuccess(Iterable<Op.MathResult> result) throws Throwable { for (Op.MathResult r : result) { if (r instanceof Op.AddResult) { System.out.println("add result=" + ((Op.AddResult) r).getResult()); } else if (r instanceof Op.SubtractResult) { System.out.println("subtract result=" + ((Op.SubtractResult) r).getResult()); } else if (r instanceof Op.MultiplicationResult) { System.out.println("multiply result=" + ((Op.MultiplicationResult) r).getResult()); } else if (r instanceof Op.DivisionResult) { System.out.println("divide result=" + ((Op.DivisionResult) r).getResult()); } } } }, system.dispatcher()); } }
运行结果,如下,
[INFO] [01/20/2015 10:47:24.660] [main] [Remoting] Starting remoting
[INFO] [01/20/2015 10:47:25.328] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://[email protected]:8989]
[INFO] [01/20/2015 10:47:25.333] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://[email protected]:8989]
Started CalculatorWorkerSystem
Calculating 1 + 2
Calculating 1 - 2
Calculating 1 * 2
Calculating 1.0 / 2
add result=3
subtract result=-1
multiply result=2
divide result=0.5
==================END==================