Akka2使用探索7——“云计算”示例(Actor、Future、Remoting

假设有一个很耗时的运算,单台机器已经没法满足需求,这时你可以想到由多台计算机协作完成。具体怎么做呢。

举个很简单的例子,假设这个耗时的运算是从1加到100000,你现在有两台服务器,可以让这两台服务器分别完成从1加到50000,和从50001加到100000,然后本机完成这两个结果之和。

 

两台服务器分别启动两个akka Server,同时还有一个CalcActor。这个计算actor接收两个参数:Integer start和Integer end,可以从start一直加到end,最后将结果返回给发送者:getSender().tell(result)。

@Log4j class CalcActor extends UntypedActor { @Override void onReceive(Object message) { log.debug " CalcActor received: ${message}----self:${getSelf()},sender:${getSender()}" if (message instanceof String) { String[] args = message.split(" ,") int start = Integer.parseInt(args[0]) int end = Integer.parseInt(args[1]) int result = 0 println(" start calc:" + start + " upto " + end) start.upto(end) { result += it } sleep(5000) //模拟还要额外耗时5秒 println(" result:" + result) getSender().tell(result) } else { unhandled(message) } } }
两个服务器分别为: AkkaServerApp serverA = new AkkaServerApp(" sc", " 10.68.3.122", 8888, " calc") //AkkaSystemName为sc,ip为10.68.3.122,端口为8888,serviceName为calc。 AkkaServerApp serverA = new AkkaServerApp(" sp", " 10.68.3.124", 8888, " calc") //AkkaSystemName为sp,ip为10.68.3.124,端口为8888,serviceName为calc。
主要的代码在客户端:
public static void main(String[] args) throws Exception { final AkkaServerApp app = new AkkaServerApp(" xwc", " 127.0.0.1", 6666, " client"); //客户端akka配置 ActorRef remoteCalcA1 = app.getSystem().actorOf( new Props(CalcActor. class)..withDeploy( new Deploy( new RemoteScope( new Address(" akka", " sc", " 10.68.3.122", 8888)))), " clientCalcA1"); //将CalcActor发布到远程10.68.3.122上 ActorRef remoteCalcA2 = app.getSystem().actorOf( new Props(CalcActor. class)..withDeploy( new Deploy( new RemoteScope( new Address(" akka", " sc", " 10.68.3.122", 8888)))), " clientCalcA2"); //将CalcActor发布到远程10.68.3.124上 final List<Future&lt;Double>&gt; frs = new ArrayList<Future&lt;Double>&gt;(); //异步返回结果Future存放在list中 //tell只请求,是否响应它完全不知道。ask是请求,并明确知道未来会相应。 // remoteCalcA.tell("1,10000", app.getServerActor()); // remoteCalcB.tell("10001,20000", app.getServerActor()); Future f1 = akka.pattern.Patterns.ask(remoteCalcA1, " 1,50000", 150000); //让远程122计算从1加到50000,超时时间为150秒 Future f2 = akka.pattern.Patterns.ask(remoteCalcA1, " 50001,100000", 150000); //并发地让远程124计算从50001加到100000,超时时间150秒 frs.add(f1); frs.add(f2); Future<Iterable&lt;Double>&gt; future = Futures.sequence(frs, app.getSystem().dispatcher());将未来返回的结果转换成Future<Iterable&lt;Double>&gt; Future<Double> fr = future.map( new Mapper<Iterable&lt;Double>, Double&gt;() { @Override public Double apply(Iterable<Double> parameter) { Double result = 0d; for (Double s : parameter) { //计算两个服务器返回的结果 result += s; } return result; } }); fr.onSuccess( new OnSuccess<Double>() { @Override public void onSuccess(Double result) { System.out.println(" 云计算返回结果-----" + result); } }); }

 

还可以让服务器并发处理:把给从1加到50000的任务分成5个线程并行处理:1..10000,10001..20000,20001..30000,30001..40000,40001..50000,这样能更好地提高效率。

如果按上面的方法仅仅是发布多个remote actor:

ActorRef remoteCalcAn = app.getSystem().actorOf(new Props(CalcActor.class)..withDeploy(new Deploy(new RemoteScope(new Address("akka", "sc", "10.68.3.122", 8888)))), "clientCalcAn");

是没法提高效率的,因为这时的CalcActor是单线程的,它只会先接收1..10000,处理完后再接收10001..20000并处理。。。。。

使其能够并行处理很简单,创建remoteActor时加上withRoute即可:

ActorRef remoteCalcAn = app.getSystem().actorOf( new Props(CalcActor. class).withRouter( new RoundRobinRouter(5)).withDeploy( new Deploy( new RemoteScope( new Address(" akka", " sc", " 10.68.3.122", 8888)))), " clientCalcAn"); //RoundRobinRouter的参数5可以理解为分配5个线程并行处理

代码跟上面基本相同
public static void main(String[] args) throws Exception { final AkkaServerApp app = new AkkaServerApp(" xwc", " 127.0.0.1", 6666, " client"); ActorRef remoteCalcA1 = app.getSystem().actorOf( new Props(CalcActor. class).withRouter( new RoundRobinRouter(4)).withDeploy( new Deploy( new RemoteScope( new Address(" akka", " sc", " 10.68.3.122", 8888)))), " clientCalcA1"); ActorRef remoteCalcB1 = app.getSystem().actorOf( new Props(CalcActor. class).withRouter( new RoundRobinRouter(4)).withDeploy( new Deploy( new RemoteScope( new Address(" akka", " sp", " 10.68.3.124", 8888)))), " clientCalcB1"); final List<Future&lt;Double>&gt; frs = new ArrayList<Future&lt;Double>&gt;(); Future f1 = akka.pattern.Patterns.ask(remoteCalcA1, " 1,10000", 150000); Future f2 = akka.pattern.Patterns.ask(remoteCalcA1, " 10001,20000", 150000); Future f3 = akka.pattern.Patterns.ask(remoteCalcA1, " 20001,30000", 150000); Future f4 = akka.pattern.Patterns.ask(remoteCalcA1, " 30001,40000", 150000); Future f5 = akka.pattern.Patterns.ask(remoteCalcB1, " 40001,50000", 150000); Future f6 = akka.pattern.Patterns.ask(remoteCalcB1, " 50001,60000", 150000); Future f7 = akka.pattern.Patterns.ask(remoteCalcB1, " 60001,70000", 150000); Future f8 = akka.pattern.Patterns.ask(remoteCalcB1, " 70001,80000", 150000); frs.add(f1); frs.add(f2); frs.add(f3); frs.add(f4); frs.add(f5); frs.add(f6); frs.add(f7); frs.add(f8); Future<Iterable&lt;Double>&gt; future = Futures.sequence(frs, app.getSystem().dispatcher()); Future<Double> fr = future.map( new Mapper<Iterable&lt;Double>, Double&gt;() { @Override public Double apply(Iterable<Double> parameter) { Double result = 0d; for (Double s : parameter) { result += s; } return result; } }); fr.onSuccess( new OnSuccess<Double>() { @Override public void onSuccess(Double result) { System.out.println(" 云计算返回从1加到80000的结果-----" + result); } }); }

你可能感兴趣的:(服务器,计算机,云计算,start,的)