AAA Java中使用akka

来源:互联网 发布:node.js搭建 编辑:程序博客网 时间:2024/05/17 08:05

什么是actor?

  • Actor模型在并发编程中是比较常见的一种模型。很多开发语言都提供了原生的Actor模型。例如erlang,scala等。
  • 它由Carl Hewitt于上世纪70年代早期提出,目的是为了解决分布式编程中一系列的编程问题。
  • Actor模型的本质已经被强调了无数遍:万物皆Actor。Actor之间只有发送消息这一种通信方式。
  • 一个Actor如何处理多个Actor的请求呢?它先建立一个消息队列,每次收到消息后,就放入队列,而它每次也从队列中取出消息体来处理。通常我们都使得这个过程是循环的。让Actor可以时刻处理发送来的消息。

什么是akka?

Akka是一个用Scala编写的库,用于简化编写容错的、高可伸缩性的Java和Scala的Actor模型应用。

  • 下面以在java项目中使用akka写代码为例子。

依赖

  • maven项目
  • java6 or 7
  • 添加akka相关的包
1234567891011121314151617181920
<dependency>            <groupId>com.typesafe.akka</groupId>            <artifactId>akka-actor_2.10</artifactId>            <version>2.3.1</version>        </dependency>        <dependency>            <groupId>com.typesafe.akka</groupId>            <artifactId>akka-remote_2.10</artifactId>            <version>2.3.1</version>        </dependency>        <dependency>            <groupId>com.google.protobuf</groupId>            <artifactId>protobuf-java</artifactId>            <version>2.5.0</version>        </dependency>        <dependency>            <groupId>com.typesafe.akka</groupId>            <artifactId>akka-testkit_2.10</artifactId>            <version>2.3.1</version>        </dependency>

依赖包解析

  • akka-actor 核心包,有这个包就可以写简单的代码了
  • akka-remote 远程包,有这个包,才能够跨进程和网络调用
  • protobuf-java 不解释了,之所有是要声明版本,是因为pb的版本太低会造成消息传递过程中序列化反序列化有问题
  • akka-testkit 测试集,有这个包,写test case方便

常见问题

  • Q:shutting down JVM since ‘akka.jvm-exit-on-fatal-error’ is enabled
  • A:所有出错的时候都会有这个提示,快速错误退出是一个常见的机制,让系统最快时间发现错误。
  • Q:java.lang.ClassNotFoundException: akka.remote.RemoteActorRefProvider
  • A:没有添加进来akka-remote的时候会这样
  • Q:class akka.remote.WireFormats$AkkaControlMessage overrides final method getUnknownFields.()Lcom/google/protobuf/UnknownFieldSet
  • A:这是pb版本太低导致的,声明到2.5.0或以上

例子

  • 这是typesafe的经典例子。
  • 所有actor的配置都在classpath中。
  • 此例启动了两个system(简称为worker与creator):startRemoteWorkerSystem && startRemoteCreationSystem
  • worker使用calculator.conf,在2552端口侦听。
  • creator使用remotecreation.conf,定义了它的worker在远程的2552端口,路径在creationActor下,自己的端口为2554。

creator中的逻辑

  • creator启动后,调用了schedule,进行了一秒一次的随机调用乘法或除法。
  • 具体的计算,在creationActor这个actor中完成。
  • 而creationActor这个actor被定义到了远程2552端口的进程中执行。
12345678
akka {  actor {    deployment {      "/creationActor/*" {        remote = "akka.tcp://CalculatorWorkerSystem@127.0.0.1:2552"      }    }  }

运行中进程观察

  • run CreationApplication.java
  • 一个进程 启动了一个端口
  • 进程通过这个端口,产生随机算式,交给另一个进程(这里是同一个进程)。

代码

  • 本文提及代码在 https://github.com/XiaoMi/rose/tree/master/rose-example
  • 注意这个代码里面包含了很多无用的代码
  • import akka.actor.ActorRef;import akka.actor.UntypedActor;import akka.actor.ActorSystem;import akka.actor.Props;import akka.actor.Inbox;import scala.concurrent.duration.Duration;import java.io.Serializable;import java.util.concurrent.TimeUnit;public class HelloAkkaJava {    public static class Greet implements Serializable {}    public static class WhoToGreet implements Serializable {        public final String who;        public WhoToGreet(String who) {            this.who = who;        }    }    public static class Greeting implements Serializable {        public final String message;        public Greeting(String message) {            this.message = message;        }    }    public static class Greeter extends UntypedActor {        String greeting = "";        public void onReceive(Object message) {            if (message instanceof WhoToGreet)                greeting = "hello, " + ((WhoToGreet) message).who;            else if (message instanceof Greet)                // Send the current greeting back to the sender                getSender().tell(new Greeting(greeting), getSelf());            else unhandled(message);        }    }    public static void main(String[] args) {        // Create the 'helloakka' actor system        final ActorSystem system = ActorSystem.create("helloakka");        // Create the 'greeter' actor        final ActorRef greeter = system.actorOf(Props.create(Greeter.class), "greeter");        // Create the "actor-in-a-box"        final Inbox inbox = Inbox.create(system);        // Tell the 'greeter' to change its 'greeting' message        greeter.tell(new WhoToGreet("akka"), ActorRef.noSender());        // Ask the 'greeter for the latest 'greeting'        // Reply should go to the "actor-in-a-box"        inbox.send(greeter, new Greet());        // Wait 5 seconds for the reply with the 'greeting' message        Greeting greeting1 = (Greeting) inbox.receive(Duration.create(5, TimeUnit.SECONDS));        System.out.println("Greeting: " + greeting1.message);        // Change the greeting and ask for it again        greeter.tell(new WhoToGreet("typesafe"), ActorRef.noSender());        inbox.send(greeter, new Greet());        Greeting greeting2 = (Greeting) inbox.receive(Duration.create(5, TimeUnit.SECONDS));        System.out.println("Greeting: " + greeting2.message);        // after zero seconds, send a Greet message every second to the greeter with a sender of the GreetPrinter        ActorRef greetPrinter = system.actorOf(Props.create(GreetPrinter.class));        system.scheduler().schedule(Duration.Zero(), Duration.create(1, TimeUnit.SECONDS), greeter, new Greet(), system.dispatcher(), greetPrinter);        //system.shutdown();    }    public static class GreetPrinter extends UntypedActor {        public void onReceive(Object message) {            if (message instanceof Greeting)                System.out.println(((Greeting) message).message);        }    }}



原创粉丝点击