如何使用akka实现分布式定时任务

实现一个分布式定时任务系统可以使用 Akka 框架,Akka 是一个用于构建高并发、分布式和弹性消息驱动应用程序的工具包和运行时。以下是一个使用 Akka 实现分布式定时任务的示例。

1. 添加 Akka 依赖

pom.xml 文件中添加 Akka 的依赖:

xml复制

复制代码
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-actor-typed_2.13</artifactId>
    <version>2.6.18</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-cluster-typed_2.13</artifactId>
    <version>2.6.18</version>
</dependency>
<dependency>
    <groupId>com.typesafe.akka</groupId>
    <artifactId>akka-cluster-tools_2.13</artifactId>
    <version>2.6.18</version>
</dependency>

2. 配置 Akka 集群

application.conf 文件中配置 Akka 集群:

hocon复制

复制代码
akka {
  actor {
    provider = cluster
  }
  remote {
    artery {
      enabled = on
      transport = tcp
      canonical.hostname = "127.0.0.1"
      canonical.port = 2552
    }
  }
  cluster {
    seed-nodes = [
      "akka://ClusterSystem@127.0.0.1:2552"
    ]
    auto-down-unreachable-after = 10s
  }
}

3. 创建定时任务行为

创建一个 Akka 行为,用于执行定时任务:

java复制

复制代码
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.ActorRef;
import akka.actor.typed.ActorSystem;
import akka.actor.typed.javadsl.TimerScheduler;

import java.time.Duration;

public class TimerActor {
    public interface Command {}
    public static class Start implements Command {}
    public static class Tick implements Command {}

    public static Behavior<Command> create() {
        return Behaviors.withTimers(timer -> {
            timer.startTimerAtFixedRate(new Tick(), Duration.ofSeconds(1));
            return Behaviors.receive(Command.class)
                    .onMessage(Start.class, msg -> {
                        System.out.println("Timer started.");
                        return Behaviors.same();
                    })
                    .onMessage(Tick.class, msg -> {
                        System.out.println("Tick.");
                        return Behaviors.same();
                    })
                    .build();
        });
    }

    public static void main(String[] args) {
        ActorSystem<Command> system = ActorSystem.create(TimerActor.create(), "ClusterSystem");
        ActorRef<Command> timerActor = system.actorOf(TimerActor.create(), "timerActor");
        timerActor.tell(new Start());
    }
}

4. 集群化定时任务

为了实现分布式定时任务,可以将定时任务的行为部署到 Akka 集群中的多个节点上。使用 akka-cluster-tools 提供的 DistributedPubSub 来实现消息的广播和分发。

4.1 添加 DistributedPubSub 配置

application.conf 文件中添加 DistributedPubSub 的配置:

hocon复制

复制代码
akka {
  extension {
    akka.cluster.pub-sub = akka.cluster.pubsub.DistributedPubSub
  }
}
4.2 创建分布式定时任务行为

创建一个分布式定时任务行为,使用 DistributedPubSub 来广播消息:

java复制

复制代码
import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.TimerScheduler;
import akka.cluster.pubsub.DistributedPubSub;
import akka.cluster.pubsub.DistributedPubSubMediator;

import java.time.Duration;

public class DistributedTimerActor {
    public interface Command {}
    public static class Start implements Command {}
    public static class Tick implements Command {}

    public static Behavior<Command> create(ActorRef<DistributedPubSubMediator.Command> mediator) {
        return Behaviors.withTimers(timer -> {
            timer.startTimerAtFixedRate(new Tick(), Duration.ofSeconds(1));
            return Behaviors.receive(Command.class)
                    .onMessage(Start.class, msg -> {
                        System.out.println("Timer started.");
                        mediator.tell(new DistributedPubSubMediator.Send("/user/timerActor", new Start(), false));
                        return Behaviors.same();
                    })
                    .onMessage(Tick.class, msg -> {
                        System.out.println("Tick.");
                        mediator.tell(new DistributedPubSubMediator.Send("/user/timerActor", new Tick(), false));
                        return Behaviors.same();
                    })
                    .build();
        });
    }

    public static void main(String[] args) {
        ActorSystem<Void> system = ActorSystem.create(Behaviors.empty(), "ClusterSystem");
        ActorRef<DistributedPubSubMediator.Command> mediator = DistributedPubSub.get(system).mediator();
        ActorRef<Command> timerActor = system.actorOf(DistributedTimerActor.create(mediator), "timerActor");
        timerActor.tell(new Start());
    }
}

5. 启动多个节点

启动多个 Akka 节点,每个节点运行相同的定时任务行为。每个节点都会接收到广播的消息,并执行相应的任务。

5.1 启动第一个节点

bash复制

复制代码
java -jar your-application.jar --config.file=application1.conf
5.2 启动第二个节点

bash复制

复制代码
java -jar your-application.jar --config.file=application2.conf

6. 配置文件示例

application1.confapplication2.conf 文件内容可以类似如下:

hocon复制

复制代码
akka {
  remote {
    artery {
      canonical.port = 2552
    }
  }
}

hocon复制

复制代码
akka {
  remote {
    artery {
      canonical.port = 2553
    }
  }
}

通过上述步骤,你可以使用 Akka 实现一个分布式定时任务系统。每个节点都会接收到广播的消息,并执行相应的任务,从而实现分布式定时任务的功能。

相关推荐
PeterLi3 小时前
Redis 分布式锁架构全解析:从基础实现到生产级选型指南
redis·分布式
qq_435287924 小时前
第18章 闻仲西征:单体应用被分布式集群拖垮?十战十捷是回光返照
分布式·微服务·分布式架构·健康检查·单体应用·闻仲·垂直扩展
过期动态5 小时前
【RabbitMQ基础篇】RabbitMQ从入门到实战
java·jvm·数据库·分布式·spring·rabbitmq·intellij-idea
麟听科技6 小时前
HarmonyOS 6.0+ 跨端智能写作助手开发实战:多设备接续编辑与AI辅助创作落地
人工智能·分布式·华为·harmonyos·ai写作
Volunteer Technology7 小时前
Hadoop NameNode HA
大数据·hadoop·分布式
hyunbar7 小时前
ZooKeeper 未授权访问漏洞:你做的 ACL 加固可能只是“假动作”
分布式·zookeeper·云原生
卷毛的技术笔记8 小时前
双十一零点扛过10倍流量洪峰:Sentinel与Redis+Lua的分布式限流深度避坑指南
java·redis·分布式·后端·系统架构·sentinel·lua
Volunteer Technology8 小时前
Hadoop Federation 联邦
大数据·hadoop·分布式
书香门第8 小时前
系统设计练习 - 实时警员安全报警系统
分布式·系统架构·系统设计
该昵称用户已存在8 小时前
光储微网一体管控:MyEMS 开源平台打造分布式能源管理新底座
分布式·开源