当前位置: 首页 > article >正文

Spring Boot集成Akka Cluster实现在分布式节点中执行任务

1.写在前面

前面已经写过akka的很多文章了,具体如下:

  • Spring Boot集成akka actor快速入门Demo
  • Spring Boot集成Akka Stream快速入门Demo
  • Spring Boot集成Akka remoting快速入门Demo
  • Spring Boot集成Akka Cluster快速入门Demo

今天主要讲一下如何在一个akka集群环境中提交任务并在集群中执行

2.代码工程

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springboot-demo</artifactId>
        <groupId>com.et</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>akka</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>


    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-actor_2.13</artifactId>
            <version>2.6.0</version>
        </dependency>

        <!-- Akka Streams -->
        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-stream_2.13</artifactId>
            <version>2.6.0</version>
        </dependency>
        <!-- Akka Actor dependency -->
        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-actor-typed_2.13</artifactId>
            <version>2.6.0</version>
        </dependency>

        <!-- Akka Remote dependency -->
        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-remote_2.13</artifactId>
            <version>2.6.0</version>
        </dependency>
        <!-- Akka Cluster dependency -->
        <dependency>
            <groupId>com.typesafe.akka</groupId>
            <artifactId>akka-cluster-typed_2.13</artifactId>
            <version>2.6.0</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

MasterActor

 

  • 作用MasterActor 是系统中的主控制器或协调者。它负责管理和分配任务,监控工作进度,以及处理系统的全局状态。
  • 功能
    • 任务分配:接收任务请求并将这些任务分发给工作节点(WorkActor)。
    • 协调工作:协调多个 WorkActor 的工作,确保任务按预期执行。
    • 结果汇总:汇总来自 WorkActor 的结果,可能还会对结果进行处理或存储。
    • 监控与容错:监控 WorkActor 的状态,处理异常情况,进行故障恢复等。

 

package com.et.akka.cluster;

import akka.actor.AbstractActor;
import akka.actor.Props;
import akka.actor.ActorRef;
import akka.event.Logging;
import akka.event.LoggingAdapter;

import java.util.HashMap;
import java.util.Map;

public class MasterActor extends AbstractActor {
    private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);
    private final ActorRef workerRouter;

    // Constructor to initialize the worker router
    public MasterActor(ActorRef workerRouter) {
        this.workerRouter = workerRouter;
    }

    public static Props props(ActorRef workerRouter) {
        return Props.create(MasterActor.class, workerRouter);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(TaskMessage.class, msg -> {
                    log.info("Received task message: {}", msg.task);
                    workerRouter.tell(msg, getSelf()); // Forward task to worker router
                })
                .build();
    }
}

WorkerRouterActor

 

  • 作用WorkerRouterActor 是一个路由器,负责将任务分发给多个 WorkActor 实例。它通常用于负载均衡和高效地管理工作负载。
  • 功能
    • 任务路由:根据路由策略将任务分发给一个或多个 WorkActor 实例。常见的路由策略包括轮询、随机、最少工作量等。
    • 负载均衡:确保工作负载在所有 WorkActor 实例中均匀分布。
    • 动态调整:可以根据系统负载动态调整 WorkActor 的数量,进行扩展或收缩。

 

package com.et.akka.cluster;

import akka.actor.AbstractActor;
import akka.actor.ActorRef;
import akka.actor.Props;
import akka.actor.Terminated;
import akka.routing.RoundRobinPool;
import akka.routing.Router;

public class WorkerRouterActor extends AbstractActor {
    private final ActorRef router;

    public WorkerRouterActor(int numberOfWorkers) {
        this.router = getContext().actorOf(new RoundRobinPool(numberOfWorkers).props(WorkerActor.props()), "workerRouter");
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(TaskMessage.class, msg -> router.tell(msg, getSelf()))
                .match(Terminated.class, t -> getContext().stop(getSelf()))
                .build();
    }

    public static Props props(int numberOfWorkers) {
        return Props.create(WorkerRouterActor.class, numberOfWorkers);
    }
}

WorkActor

 

  • 作用WorkActor 是实际执行任务的工作单元。它负责处理具体的工作负载,并返回结果给 MasterActor 或通过 WorkerRouterActor 进行汇总。
  • 功能
    • 执行任务:接收任务并执行相关操作,如计算、数据处理等。
    • 报告结果:完成任务后,将结果发送回 MasterActor 或其他负责汇总结果的组件。
    • 错误处理:处理任务执行过程中可能出现的错误或异常情况。

 

package com.et.akka.cluster;

import akka.actor.AbstractActor;
import akka.actor.Props;
import akka.event.Logging;
import akka.event.LoggingAdapter;

public class WorkerActor extends AbstractActor {
    private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this);

    public static Props props() {
        return Props.create(WorkerActor.class);
    }

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(TaskMessage.class, msg -> {
                    log.info("Processing task: {}", msg.task);
                    // Simulate task processing
                    Thread.sleep(1000);
                    log.info("Task completed: {}", msg.task);
                })
                .build();
    }
}

ClusterApp2

package com.et.akka.cluster;

import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.cluster.Cluster;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;

public class ClusterApp2 {

    public static void main(String[] args) {
        // Load configuration
        Config config = ConfigFactory.load();
        ActorSystem system = ActorSystem.create("ClusterSystem", config);

        // Create WorkerRouterActor with 5 workers
        ActorRef workerRouter = system.actorOf(WorkerRouterActor.props(5), "workerRouter");

        // Create MasterActor
        ActorRef masterActor = system.actorOf(MasterActor.props(workerRouter), "masterActor");

        // Log cluster membership
        Cluster cluster = Cluster.get(system);
        System.out.println("Cluster initialized with self member: " + cluster.selfAddress());

        // Submit tasks
        masterActor.tell(new TaskMessage("Task 1"), ActorRef.noSender());
        masterActor.tell(new TaskMessage("Task 2"), ActorRef.noSender());
        masterActor.tell(new TaskMessage("Task 3"), ActorRef.noSender());

        // Keep system alive for demonstration purposes
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        system.terminate();
    }
}

只是一些关键代码,所有代码请参见下面代码仓库

代码仓库

  • GitHub - Harries/springboot-demo: a simple springboot demo with some components for example: redis,solr,rockmq and so on.(akka)

3.测试

启动ClusterApp2类之中的main方法,查看日志,发现任务执行成功

Cluster initialized with self member: akka://ClusterSystem@127.0.0.1:2551
22:03:04.948 [ClusterSystem-akka.actor.default-dispatcher-15] INFO com.et.akka.cluster.MasterActor - Received task message: Task 1
22:03:04.949 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.WorkerActor - Processing task: Task 1
22:03:04.949 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.MasterActor - Received task message: Task 2
22:03:04.949 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.MasterActor - Received task message: Task 3
22:03:04.950 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.WorkerActor - Processing task: Task 2
22:03:04.950 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.WorkerActor - Processing task: Task 3
22:03:05.951 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.WorkerActor - Task completed: Task 3
22:03:05.952 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.WorkerActor - Task completed: Task 2
22:03:05.952 [ClusterSystem-akka.actor.default-dispatcher-16] INFO com.et.akka.cluster.WorkerActor - Task completed: Task 1

4.引用

  • https://doc.akka.io/docs/akka/current/common/cluster.html#gossip

http://www.kler.cn/a/307217.html

相关文章:

  • Elasticsearch 实战应用:高效搜索与数据分析
  • odoo 17 后端路由接口认证自定义
  • 免费,WPS Office教育考试专用版
  • vivo 游戏中心包体积优化方案与实践
  • Vue 3 介绍及应用
  • Rust 所有权机制
  • Android中如何处理运行时权限?
  • 02 信念·组织力·战略 - 目标管理
  • [OpenCV] 数字图像处理 C++ 学习——15像素重映射(cv::remap) 附完整代码
  • 数据中台建设(六)—— 数据资产管理
  • uniapp 携带网址跳转webview页面报错解决
  • tp6.0.8反序列化漏洞的一些看法
  • Redis详细解析
  • (c++)猜数字(含根据当前时间生成伪随机数代码)
  • C++ Primer Plus(速记版)-面向对象与泛型编程
  • 浅谈 React Fiber
  • 关于less的基本使用
  • 【 html+css 绚丽Loading 】000050 乾坤合璧轮
  • 常用 Git 命令
  • c++ #include <string> 介绍
  • Java 之 IO流
  • Java读取寄存器数据的方法
  • memo和useMemo的区别
  • Js中的pick函数
  • 【Python基础】Python 装饰器(优雅的代码增强工具)
  • 如何通过Chrome浏览器轻松获取视频网站的TS文件