21、聊聊akka(一)使用及集群调用(负载)

7人阅读 评论(0) 收藏 举报
分类:

问到:akka的线程模型
为actor模型,那actor模型具体是怎么样的呢?
一种类似于协程的事件(消息)驱动?


AKKA提供一种Actor并发模型,其粒度比线程小很多,这意味着你可以在项目中使用大量的Actor。
Akka提供了一套容错机制,允许在Actor出错时进行一些恢复或者重置操作
AKKA不仅可以在单击上构建高并发程序,也可以在网络中构建分布式程序,并提供位置透明的Actor定位服务


Akka是一个运行时与编程模型一致的系统,为以下目标设计:

垂直扩展(并发)
水平扩展(远程调用)
高容错

可惜在我设计的项目里只用做了异步机制,是远远不够的,杀鸡用了牛刀。

一个简单的启动

public static void main(String[] args) {
    ActorSystem system = ActorSystem.create("helloWorld");
    ActorRef helloWorld = system.actorOf(Props.create(HelloWorld.class), "helloWorld");
    helloWorld.tell(HelloWorld.Msg.Starting, ActorRef.noSender());

调用ActorSystem的actorOf方法创建一个Actor实例,返回一个引用ActorRef,它包括一个UID和一个Path,标识了一个Actor,可以通过该引用向该Actor实例发送消息。
Actor:

public interface Actor {
    ActorContext context();
    ActorRef self();
    ActorRef sender();
    PartialFunction<Object, BoxedUnit> receive();
    void aroundReceive(PartialFunction<Object, BoxedUnit> var1, Object var2);
    void aroundPreStart();
    void aroundPostStop();
    void aroundPreRestart(Throwable var1, Option<Object> var2);
    void aroundPostRestart(Throwable var1);
    SupervisorStrategy supervisorStrategy();
    void preStart() throws Exception;
    void postStop() throws Exception;
    void preRestart(Throwable var1, Option<Object> var2) throws Exception;
    void postRestart(Throwable var1) throws Exception;
    void unhandled(Object var1);
    ...

Akka程序是由多个Actor组成的。它的工作原理是把一项大运算分割成许多小任务然后把这些任务托付给多个Actor去运算。Actor不单可以在当前JVM中运行,也可以跨JVM在任何机器上运行,这基本上就是Akka程序实现分布式运算的关键了。当然,这也有赖于Akka提供的包括监管、监视各种Actor角色,各式运算管理策略和方式包括容错机制、内置线程管理、远程运行管理(remoting)等,以及一套分布式的消息系统来协调、控制整体运算的安全进行。

Supervisor

在一个ActorSystem是具有分层结构(Hierarchical Structure)的:一个Actor能够管理(Oversee)某个特定的函数,他可能希望将一个task分解为更小的多个子task,这样它就需要创建多个子Actor(Child Actors),并监督这些子Actor处理任务的进度等详细情况,实际上这个Actor为一个Supervisor来监督管理子Actor执行拆分后的多个子task,如果一个子Actor执行子task失败,那么就要向Supervisor发送一个消息说明处理子task失败。需要知道的是,一个Actor能且仅能有一个Supervisor,就是创建它的那个Actor。基于被监控任务的性质和失败的性质,一个Supervisor可以选择执行如下操作选择:

重新开始(Resume)一个子Actor,保持它内部的状态 ,该Actor的所有子Actor都继续工作
重启一个子Actor,清除它内部的状态,该Actor的所有子Actor都被重新启动
终止一个子Actor,该Actor的所有子Actor都被终止(默认)
扩大失败的影响,从而使这个子Actor失败

一个ActorSystem在创建过程中,至少启动3个Actor,如下图所示:
这里写图片描述
上图是一个类似树状层次结构,ActorSystem的Top-Level层次结构,与Actor关联起来,称为Actor路径(Actor Path),不同的路径代表了不同的监督范围(Supervision Scope)。下面说明ActorSystem的监督范围:

“/”路径:通过根路径可以搜索到所有的Actor
“/user”路径:用户创建的Top-Level Actor在该路径下面,通过调用ActorSystem.actorOf来实现Actor的创建
“/system”路径:系统创建的Top-Level Actor在该路径下面
“/deadLetters”路径:消息被发送到已经终止,或者不存在的Actor,这些Actor都在该路径下面
“/temp”路径:被系统临时创建的Actor在该路径下面
“/remote”路径:改路径下存在的Actor,它们的Supervisor都是远程Actor的引用

System.out.println(helloWorld.path());
//akka://helloWorld/user/helloWorld

Gossip协议

Akka基于Gossip实现集群服务,而且支持服务自动失败检测。
在consul里面是否对Gossip有了一些了解:

Gossip协议是点对点(Computer-to-Computer)通信协议的一种,它受社交网络中的流言传播的特点所启发。现在分布式系统常常使用Gossip协议来解决其他方式所无法解决的问题,或者是由于底层网络的超大特殊结构,或者是因为Gossip方案是解决这类问题最有效的一种方式。

一个Akka集群由一组成员节点组成,每个成员节点通过hostname:port:uid来唯一标识,并且每个成员节点之间是解耦合的(Decoupled)。一个Akka应用程序是一个分布式应用程序,它具有一个Actor的集合S,而每个节点上可以启动这个Akka应用S的集合的的一部分Actor,而不必是全集S。如果一个新的成员节点需要加入到Akka集群,只需要在集群中任意一个成员节点上执行Join命令即可。

Akka集群中各个成员节点之间的状态关系,如下图所示:
这里写图片描述
Akka集群中任何一个成员节点都有可能成为集群的Leader,这是基于Gossip收敛(Convergence)过程得到的确定性结果,没有经过选举的过程。Leader只是一种角色,在各轮Gossip收敛过程中Leader是不断变化的。Leader的职责是使成员节点进入/离开集群。
一个成员节点开始于joining状态,一旦所有其节点都看到了该新加入Akka集群的节点,则Leader会设置这个节点的状态为up。
如果一个节点安全离开Akka集群,可预期地它的状态会变为leaving状态,当Leader看到该节点为leaving状态,会将其状态修改为exiting,然后当所有节点看到该节点状态为exiting,则Leader将该节点移除,状态修改为removed状态。
如果一个节点处于unreachable状态,基于Gossip协议Leader是无法执行任何操作收敛(Convergence)到该节点的,所以unreachable状态的节点的状态是必须被改变的,它必须变成reachable状态或者down状态。如果该节点想再次加入到Akka集群,它必须需要重新启动,并且重新加入集群(经由joining状态)。

利用Inbox收件箱给Actor发送消息

actor是消息驱动的。

修改HelloWorld:

 }else if(msg == Msg.CLOSE){
    logger.info(" stoping");
     getSender().tell(new Terminated(getSelf(),false,false), getSelf());
     //getSender().tell("STOP", getSelf());
     getContext().stop(getSelf());
 }else {
ActorSystem system = ActorSystem.create("helloWorld");
ActorRef helloWorld = system.actorOf(Props.create(HelloWorld.class), "helloWorld");

Inbox inbox = Inbox.create(system);
inbox.watch(helloWorld);//监听一个actor
inbox.send(helloWorld ,HelloWorld.Msg.Starting);
inbox.send(helloWorld ,HelloWorld.Msg.CLOSE);
Object receive = null;
for (; ; ) {
    try {
        receive = inbox.receive(Duration.create(1, TimeUnit.SECONDS));
        System.out.println(receive);
        if(receive instanceof  Terminated) {//中断 ,和线程一个概念
            System.out.println("================");
            system.shutdown();
            break;
        }
    } catch (TimeoutException e) {
        e.printStackTrace();
    }
}

负载均衡(路由策略)

通常在分布式任务调度系统中会有这样的需求:一组actor提供相同的服务,我们在调用任务的时候只需要选择其中一个actor进行处理即可。

public class RouterTest extends UntypedActor {
    public Router router;
    {
        ArrayList<Routee> routees = new ArrayList<>();
        for(int i = 0; i < 5; i ++) {
            //借用上面的 inboxActor
            ActorRef worker = getContext().actorOf(Props.create(HelloWorld.class), "worker_" + i);
            getContext().watch(worker);//监听
            routees.add(new ActorRefRoutee(worker));
        }
        /**
         * RoundRobinRoutingLogic: 轮询
         * BroadcastRoutingLogic: 广播
         * RandomRoutingLogic: 随机
         * SmallestMailboxRoutingLogic: 空闲
         */
        router = new Router(new RoundRobinRoutingLogic(), routees);
    }

    @Override
    public void onReceive(Object o) throws Throwable {
        if(o instanceof HelloWorld.Msg){
            router.route(o, getSender());//进行路由转发
        }else if(o instanceof Terminated){
            router = router.removeRoutee(((Terminated)o).actor());//发生中断,将该actor删除。当然这里可以参考之前的actor重启策略,进行优化,为了简单,这里仅进行删除处理
            System.out.println(((Terminated)o).actor().path() + " 该actor已经删除。router.size=" + router.routees().size());

            if(router.routees().size() == 0){//没有可用actor了
                System.out.print("没有可用actor了,系统关闭。");
                flag.compareAndSet(true, false);
                getContext().system().shutdown();
            }
        }else {
            unhandled(o);
        }

    }

    public  static AtomicBoolean flag = new AtomicBoolean(true);
    public static void main(String[] args) throws InterruptedException {
        ActorSystem system = ActorSystem.create("route");
        ActorRef routerTest = system.actorOf(Props.create(RouterTest.class), "RouterTest");

        int i = 1;
        while(flag.get()){
            routerTest.tell(HelloWorld.Msg.Starting, ActorRef.noSender());
            if(i % 10 == 0) routerTest.tell(HelloWorld.Msg.CLOSE, ActorRef.noSender());
            Thread.sleep(500);
            i ++;
        }
    }
}

日志:

[INFO] [04/15/2018 22:25:06.340] [route-akka.actor.default-dispatcher-6] [akka://route/user/RouterTest/worker_1] HelloWorld starting.
[INFO] [04/15/2018 22:25:06.340] [route-akka.actor.default-dispatcher-3] [akka://route/user/RouterTest/worker_2] HelloWorld starting.
[INFO] [04/15/2018 22:25:06.340] [route-akka.actor.default-dispatcher-3] [akka://route/user/RouterTest/worker_3] HelloWorld starting.
[INFO] [04/15/2018 22:25:06.340] [route-akka.actor.default-dispatcher-3] [akka://route/user/RouterTest/worker_4] HelloWorld starting.
[INFO] [04/15/2018 22:25:06.340] [route-akka.actor.default-dispatcher-2] [akka://route/user/RouterTest/worker_0] HelloWorld starting.
...
[INFO] [04/15/2018 22:25:10.839] [route-akka.actor.default-dispatcher-7] [akka://route/user/RouterTest/worker_0]  stoping
akka://route/user/RouterTest/worker_0 该actor已经删除。router.size=4
HelloWorld received msg :Starting
....
akka://route/user/RouterTest/worker_2 该actor已经删除。router.size=3
[INFO] [04/15/2018 22:25:15.841] [route-akka.actor.default-dispatcher-4] [akka://route/user/RouterTest/worker_2]  stoping
...
akka://route/user/RouterTest/worker_4 该actor已经删除。router.size=2
[INFO] [04/15/2018 22:25:20.842] [route-akka.actor.default-dispatcher-4] [akka://route/user/RouterTest/worker_4]  stoping
...
[INFO] [04/15/2018 22:25:25.843] [route-akka.actor.default-dispatcher-7] [akka://route/user/RouterTest/worker_3]  stoping
akka://route/user/RouterTest/worker_3 该actor已经删除。router.size=1
...
[INFO] [04/15/2018 22:25:30.845] [route-akka.actor.default-dispatcher-4] [akka://route/user/RouterTest/worker_1]  stoping
akka://route/user/RouterTest/worker_1 该actor已经删除。router.size=0
没有可用actor了,系统关闭。 

actor内置状态转换Procedure

public class ProcedureTest extends UntypedActor {
    public static enum Msg{
        PLAY, SLEEP;
    }
    private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    Procedure<Object> happy = new Procedure<Object>() {
        @Override
        public void apply(Object o) throws Exception {
            log.info("i am happy! " + o);
            if (o == Msg.PLAY) {
                getSender().tell("i am alrady happy!!", getSelf());
                log.info("i am alrady happy!!");
            } else if (o == Msg.SLEEP) {
                log.info("i do not like sleep!");
                getContext().become(angray);
            } else {
                unhandled(o);
            }
        }
    };
    Procedure<Object> angray = new Procedure<Object>() {
        @Override
        public void apply(Object o) throws Exception {
            log.info("i am angray! "+o);
            if(o ==Msg.SLEEP){
                getSender().tell("i am alrady angray!!", getSelf());
                log.info("i am alrady angray!!");
            } else if(o ==Msg.PLAY) {
                log.info("i like play.");
                getContext().become(happy);
            } else {
                unhandled(o);
            }
        }
    };

    @Override
    public void onReceive(Object o) throws Throwable {
        log.info("onReceive msg: " + o);
        if(o == Msg.SLEEP){
            getContext().become(angray);
        }else if(o == Msg.PLAY){
            getContext().become(happy);
        }else {
            unhandled(o);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ActorSystem system = ActorSystem.create("strategy", ConfigFactory.load("akka.config"));
        ActorRef procedureTest = system.actorOf(Props.create(ProcedureTest.class), "ProcedureTest");

        procedureTest.tell(Msg.PLAY, ActorRef.noSender());
        procedureTest.tell(Msg.SLEEP, ActorRef.noSender());
        procedureTest.tell(Msg.PLAY, ActorRef.noSender());
        procedureTest.tell(Msg.PLAY, ActorRef.noSender());

        procedureTest.tell(PoisonPill.getInstance(), ActorRef.noSender());
    }
}

日志:

[INFO].. [akka://strategy/user/ProcedureTest] onReceive msg: PLAY
[INFO].. [akka://strategy/user/ProcedureTest] i am happy! SLEEP
[INFO].. [akka://strategy/user/ProcedureTest] i do not like sleep!
[INFO].. [akka://strategy/user/ProcedureTest] i am angray! PLAY
[INFO].. [akka://strategy/user/ProcedureTest] i like play.
[INFO].. [akka://strategy/user/ProcedureTest] i am happy! PLAY
[INFO].. [akka://strategy/user/ProcedureTest] i am alrady happy!!

注意:

akka.ProcedureTest#onReceive这个方法只被调用一次,只有的切换均在procedure中处理,所以在实际开发过程中要注意状态切换的准确性。

Actor-Future

和java中的future挺像的,可以将一个actor的返回结果重定向到另一个actor中进行处理,主actor或者进程无需等待actor的返回结果。

阻塞方式

public class FutureBlockDemo {
    private static void block(){
        Callable<Integer> callable = new Callable<Integer>() {
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        };
        FutureTask<Integer> future = new FutureTask<Integer>(callable);
        new Thread(future).start();

        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

    }
    private static void block2(){
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        Future<Integer> future = threadPool.submit(new Callable<Integer>() {
            public Integer call() throws Exception {
                return new Random().nextInt(100);
            }
        });
        try {
            System.out.println(future.get());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        block();
        block2();
    }
}

非阻塞方式(回调方式)

通过onComplete,onSuccess,onFailure三个回调函数来异步执行Future任务,而后两者仅仅是第一项的特例。

public class WorkerActor extends UntypedActor {
    private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    @Override
    public void onReceive(Object o) throws Throwable {
        log.info("akka.future.WorkerActor.onReceive:" + o);

        if (o instanceof Integer) {
            Thread.sleep(1000);
            int i = Integer.parseInt(o.toString());
            getSender().tell(i, getSelf());
        }else  if (o instanceof String) {
            Thread.sleep(1000);
            int i = Integer.parseInt(o.toString());
            getSender().tell(i, getSelf());
        } else {
            unhandled(o);
        }
    }
}

public class FutureActor extends UntypedActor {
    private final LoggingAdapter log = Logging.getLogger(getContext().system(), this);
    @Override
    public void onReceive(Object o) throws Throwable {
        log.info("akka.future.FutureActor.onReceive:" + o);
        if (o instanceof Integer) {
            log.info("print:" + o);
        } else if (o instanceof String) {
            log.info("print:" + o);
        } else {
            unhandled(o);
        }
    }
}


public class FutureMain {
    public static void main(String[] args) throws Exception {
        ActorSystem system = ActorSystem.create("FutureMain" );
        ActorRef futureActor = system.actorOf(Props.create(FutureActor.class), "FutureActor");
        ActorRef workerActor = system.actorOf(Props.create(WorkerActor.class), "WorkerActor");

        //等等future返回
        Future<Object> future = Patterns.ask(workerActor, "1", 1000);
        int result = (int) Await.result(future, Duration.create(3, TimeUnit.SECONDS));
        System.out.println("result:" + result);

        //不等待返回值,直接重定向到其他actor,有返回值来的时候将会重定向到printActor
        Future<Object> future1 = Patterns.ask(workerActor, 3, 1000);
        Patterns.pipe(future1, system.dispatcher()).to(futureActor);
        workerActor.tell(PoisonPill.getInstance(), ActorRef.noSender()); //stop
    }
}

共享变量

akka集群

<dependency>
  <groupId>com.typesafe.akka</groupId>
  <artifactId>akka-cluster_2.11</artifactId>
  <version>2.4.16</version>
</dependency>

日志:

[INFO]..[akka.tcp://akkaClusterTest@127.0.0.1:2551] - Node [akka.tcp://akkaClusterTest@127.0.0.1:2551] is JOINING, roles []
[INFO]..[akka.tcp://akkaClusterTest@127.0.0.1:2551] - Leader is moving node [akka.tcp://akkaClusterTest@127.0.0.1:2551] to [Up]
[INFO] ..[akka://akkaClusterTest/user/simpleClusterListener] Member is Up: Member(address = akka.tcp://akkaClusterTest@127.0.0.1:2551, status = Up)
[INFO]..[akka.tcp://akkaClusterTest@127.0.0.1:2551] - Node [akka.tcp://akkaClusterTest@127.0.0.1:2552] is JOINING, roles []
[INFO].. [akka.tcp://akkaClusterTest@127.0.0.1:2551] - Leader is moving node [akka.tcp://akkaClusterTest@127.0.0.1:2552] to [Up]
[INFO].. [akka://akkaClusterTest/user/simpleClusterListener] Member is Up: Member(address = akka.tcp://akkaClusterTest@127.0.0.1:2552, status = Up)
[INFO].. [akka.tcp://akkaClusterTest@127.0.0.1:2551] - Node [akka.tcp://akkaClusterTest@127.0.0.1:2553] is JOINING, roles []
[INFO]..[akka.tcp://akkaClusterTest@127.0.0.1:2551] - Leader is moving node [akka.tcp://akkaClusterTest@127.0.0.1:2553] to [Up]
[INFO]..[akka://akkaClusterTest/user/simpleClusterListener] Member is Up: Member(address = akka.tcp://akkaClusterTest@127.0.0.1:2553, status = Up)

上面日志中可以看到Akka集群中各个节点的状态迁移信息,第一个种子节点正在加入自身创建的集群时的状态时JOINING,由于第一个种子节点将自己率先选举为Leader,因此它还将自己的状态改变为Up。后面它还将第二个种子节点和第三个节点从JOINING转换到Up状态。

现在把2553服务停止,看看日志输出:

[INFO] [04/15/2018 23:27:47.637] [akkaClusterTest-akka.actor.default-dispatcher-2] [akka://akkaClusterTest/user/simpleClusterListener] Member detected as unreachable: Member(address = akka.tcp://akkaClusterTest@127.0.0.1:2553, status = Up)
[WARN] [04/15/2018 23:27:47.869] [akkaClusterTest-akka.actor.default-dispatcher-40] [akka.tcp://akkaClusterTest@127.0.0.1:2551/system/cluster/core/daemon] Cluster Node [akka.tcp://akkaClusterTest@127.0.0.1:2551] - Marking node(s) as UNREACHABLE [Member(address = akka.tcp://akkaClusterTest@127.0.0.1:2553, status = Up)]. Node roles []
[WARN] [04/15/2018 23:27:48.892] [akkaClusterTest-akka.remote.default-remote-dispatcher-37] [akka.tcp://akkaClusterTest@127.0.0.1:2551/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FakkaClusterTest%40127.0.0.1%3A2553-4] Association with remote system [akka.tcp://akkaClusterTest@127.0.0.1:2553] has failed, address is now gated for [5000] ms. Reason: [Association failed with [akka.tcp://akkaClusterTest@127.0.0.1:2553]] Caused by: [拒绝连接: /127.0.0.1:2553]
[WARN] [04/15/2018 23:27:54.891] [akkaClusterTest-akka.remote.default-remote-dispatcher-37] [akka.tcp://akkaClusterTest@127.0.0.1:2551/system/endpointManager/reliableEndpointWriter-akka.tcp%3A%2F%2FakkaClusterTest%40127.0.0.1%3A2553-5] Association with remote system [akka.tcp://akkaClusterTest@127.0.0.1:2553] has failed, address is now gated for [5000] ms. Reason: [Association failed with [akka.tcp://akkaClusterTest@127.0.0.1:2553]] Caused by: [拒绝连接: /127.0.0.1:2553]
[INFO] [04/15/2018 23:27:57.649] [akkaClusterTest-akka.actor.default-dispatcher-40] [akka.cluster.Cluster(akka://akkaClusterTest)] Cluster Node [akka.tcp://akkaClusterTest@127.0.0.1:2551] - Leader is auto-downing unreachable node [akka.tcp://akkaClusterTest@127.0.0.1:2553]. Don't use auto-down feature of Akka Cluster in production. See 'Auto-downing (DO NOT USE)' section of Akka Cluster documentation.
[INFO] [04/15/2018 23:27:57.649] [akkaClusterTest-akka.actor.default-dispatcher-40] [akka.cluster.Cluster(akka://akkaClusterTest)] Cluster Node [akka.tcp://akkaClusterTest@127.0.0.1:2551] - Marking unreachable node [akka.tcp://akkaClusterTest@127.0.0.1:2553] as [Down]
[INFO] [04/15/2018 23:27:58.870] [akkaClusterTest-akka.actor.default-dispatcher-2] [akka.cluster.Cluster(akka://akkaClusterTest)] Cluster Node [akka.tcp://akkaClusterTest@127.0.0.1:2551] - Leader is removing unreachable node [akka.tcp://akkaClusterTest@127.0.0.1:2553]
[INFO] [04/15/2018 23:27:58.871] [akkaClusterTest-akka.actor.default-dispatcher-20] [akka://akkaClusterTest/user/simpleClusterListener] Member is Removed: Member(address = akka.tcp://akkaClusterTest@127.0.0.1:2553, status = Removed)

看到2553 状态为Removed

分布式实战

现在假如服务的生产者与消费者两个角色,模拟真实的服务调用:
消费者三个服务,端口为2552,2553,2551;生产者有两个:2554,2555
git:https://github.com/nick8sky/akka_mycat_nio/tree/master/akka

参考:https://blog.csdn.net/liubenlong007/article/details/53782966
https://akka.io/
http://shiyanjun.cn/archives/1168.html
https://blog.csdn.net/jasonding1354/article/details/50555383

查看评论

使用Akka构建集群(二)

在《使用Akka构建集群(一)》一文中通过简单集群监听器的例子演示了如何使用Akka搭建一个简单的集群,但是这个例子“也许”离我们的实际业务场景太远,你基本不太可能去做这样的工作,除非你负责运维、监控...
  • beliefer
  • beliefer
  • 2017-01-12 16:24:41
  • 5733

akka集群实战

关于akkaakka是JAVA虚拟机JVM平台上构建高并发、分布式和容错应用的工具包和运行时。Akka用Scala语言写成,同时提供了Scala和JAVA的开发接口。Akka处理并发的方法基于Acto...
  • Likeaboy_fire
  • Likeaboy_fire
  • 2017-09-05 09:20:03
  • 503

AKKA Cluster 原理及实战

Akka集群支持去中心化的基于P2P的集群服务,没有单点故障(SPOF)问题,它主要是通过Gossip协议和向量时钟(VECTOR CLOCKS)来实现。对于集群成员的状态,Akka提供了一种故障检测...
  • hohojiang
  • hohojiang
  • 2016-09-05 22:31:09
  • 3969

使用Akka构建集群(一)

Akka提供的非常吸引人的特性之一就是轻松构建自定义集群,这也是我要选择Akka的最基本原因之一。如果你不想敲太多代码,也可以通过简单的配置构建一个非常简单的集群。本文为说明Akka集群构建的学习成本...
  • beliefer
  • beliefer
  • 2017-01-09 15:56:18
  • 10339

使用Akka的远程调用

正如其它RPC或者RMI框架那样,Akka也提供了远程调用的能力。服务端在监听的端口上接收客户端的调用。本文将在《Spring与Akka的集成》一文的基础上介绍Akka的remote调用,本文很多代码...
  • beliefer
  • beliefer
  • 2017-01-06 15:01:25
  • 7410

AKKA路由策略的简单实现

AKKA路由策略的简单实现     AKKA的路由由router和众多的routees组成,router和routees都是actor,其它的理论知识可以参考AKKA的官方文档     htt...
  • mazihan0603
  • mazihan0603
  • 2017-11-24 15:03:17
  • 125

集群用法

集群用法 关于Akka集群概念的介绍请参阅集群规范。 为你的工程准备集群 Akka cluster是一个独立的jar文件。确保你的工程具有如下的依赖:   com.typesafe.akka   a...
  • wusandi
  • wusandi
  • 2017-10-18 21:25:49
  • 335

Akka Scala编程实践,轻松开发多线程、分布式以及集群式程序

Akka基础 参照: http://www.importnew.com/16479.html  Akka笔记之Actor简介     Akka中的Actor遵循Actor模型。你可以...
  • ZYC88888
  • ZYC88888
  • 2017-04-19 23:56:03
  • 1684

akka下的分片集群

  • 2015年12月27日 23:45
  • 1.01MB
  • 下载

Akka分片集群的实现

  • 2017年11月19日 13:30
  • 864KB
  • 下载
    个人资料
    持之以恒
    等级:
    访问量: 5075
    积分: 809
    排名: 6万+
    博客专栏
    文章存档
    最新评论