yangyang12138

导航

akka的简单demo

1.概述

  akka是actor模型的实现,可自行实现actor和beheavor。

2.简单demo

  

import akka.actor.typed.ActorRef;
import akka.actor.typed.ActorSystem;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.AbstractBehavior;
import akka.actor.typed.javadsl.ActorContext;
import akka.actor.typed.javadsl.Behaviors;
import akka.actor.typed.javadsl.Receive;

public class PrintMyActorRefActor extends AbstractBehavior<String> {

    static Behavior<String> create() {
        return Behaviors.setup(PrintMyActorRefActor::new);
    }

    private PrintMyActorRefActor(ActorContext<String> context) {
        super(context);
    }

    @Override
    public Receive<String> createReceive() {
        return newReceiveBuilder().onMessageEquals("printit", this::printIt).build();
    }

    private Behavior<String> printIt() {
        ActorRef<String> secondRef = getContext().spawn(Behaviors.empty(), "second-actor");
        System.out.println("Second: " + secondRef);
        return this;
    }

    public static void main(String[] args) {
        ActorRef<String> testSystem = ActorSystem.create(Main.create(), "testSystem");
        testSystem.tell("start");
    }
}


class Main extends AbstractBehavior<String> {

static Behavior<String> create() {
return Behaviors.setup(Main::new);
}

private Main(ActorContext<String> context) {
super(context);
}

@Override
public Receive<String> createReceive() {
return newReceiveBuilder().onMessageEquals("start", this::start).build();
}

private Behavior<String> start() {
ActorRef<String> firstRef = getContext().spawn(PrintMyActorRefActor.create(), "first-actor");

System.out.println("First: " + firstRef);
firstRef.tell("printit");
return Behaviors.same();
}
}
 

首先根节点的actor是testSystem,发送start消息后,根据消息匹配到start方法,start的方法是运行在新的actor中,路径是testSystem/start/first-actor,当需要向上游节点发送数据时需要将当前behavior添加actor参数。

 

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.javadsl.*;
import akka.actor.typed.receptionist.Receptionist;

//#frontend
public class Frontend extends AbstractBehavior<Frontend.Event> {

  interface Event {}
  private enum Tick implements Event {
    INSTANCE
  }
  private static final class WorkersUpdated implements Event {
    public final Set<ActorRef<Worker.TransformText>> newWorkers;
    public WorkersUpdated(Set<ActorRef<Worker.TransformText>> newWorkers) {
      this.newWorkers = newWorkers;
    }
  }
  private static final class TransformCompleted implements Event {
    public final String originalText;
    public final String transformedText;
    public TransformCompleted(String originalText, String transformedText) {
      this.originalText = originalText;
      this.transformedText = transformedText;
    }
  }
  private static final class JobFailed implements Event {
    public final String why;
    public final String text;
    public JobFailed(String why, String text) {
      this.why = why;
      this.text = text;
    }
  }

  public static Behavior<Event> create() {
    return Behaviors.setup(context ->
        Behaviors.withTimers(timers ->
          new Frontend(context, timers)
        )
    );
  }

  private final List<ActorRef<Worker.TransformText>> workers = new ArrayList<>();
  private int jobCounter = 0;

  private Frontend(ActorContext<Event> context, TimerScheduler<Event> timers) {
    super(context);
    ActorRef<Receptionist.Listing> subscriptionAdapter =
        context.messageAdapter(Receptionist.Listing.class, listing ->
          new WorkersUpdated(listing.getServiceInstances(Worker.WORKER_SERVICE_KEY)));
    context.getSystem().receptionist().tell(Receptionist.subscribe(Worker.WORKER_SERVICE_KEY, subscriptionAdapter));

    timers.startTimerWithFixedDelay(Tick.INSTANCE, Tick.INSTANCE, Duration.ofSeconds(2));
  }

  @Override
  public Receive<Event> createReceive() {
    return newReceiveBuilder()
        .onMessage(WorkersUpdated.class, this::onWorkersUpdated)
        .onMessage(TransformCompleted.class, this::onTransformCompleted)
        .onMessage(JobFailed.class, this::onJobFailed)
        .onMessageEquals(Tick.INSTANCE, this::onTick)
        .build();
  }


  private Behavior<Event> onTransformCompleted(TransformCompleted event) {
    getContext().getLog().info("Got completed transform of {}: {}", event.originalText, event.transformedText);
    return this;
  }

  private Behavior<Event> onJobFailed(JobFailed event) {
    getContext().getLog().warn("Transformation of text {} failed. Because: {}", event.text, event.why);
    return this;
  }

  private Behavior<Event> onTick() {
    if (workers.isEmpty()) {
      getContext().getLog().warn("Got tick request but no workers available, not sending any work");
    } else {
      // how much time can pass before we consider a request failed
      Duration timeout = Duration.ofSeconds(5);
      ActorRef<Worker.TransformText> selectedWorker = workers.get(jobCounter % workers.size());
      getContext().getLog().info("Sending work for processing to {}", selectedWorker);
      String text = "hello-" + jobCounter;
      getContext().ask(
          Worker.TextTransformed.class,
          selectedWorker,
          timeout,
          responseRef -> new Worker.TransformText(text, responseRef),
          (response, failure) -> {
            if (response != null) {
              return new TransformCompleted(text, response.text);
            } else {
              return new JobFailed("Processing timed out", text);
            }
          }
      );
      jobCounter++;
    }
    return this;
  }

  private Behavior<Event> onWorkersUpdated(WorkersUpdated event) {
    workers.clear();
    workers.addAll(event.newWorkers);
    getContext().getLog().info("List of services registered with the receptionist changed: {}", event.newWorkers);
    return this;
  }
}

public class Worker {

public static ServiceKey<Worker.TransformText> WORKER_SERVICE_KEY =
ServiceKey.create(TransformText.class, "Worker");

interface Command extends CborSerializable {}

public static final class TransformText implements Command {
public final String text;
public TransformText(String text, ActorRef<TextTransformed> replyTo) {
this.text = text;
this.replyTo = replyTo;
}
public final ActorRef<TextTransformed> replyTo;
}
public static final class TextTransformed implements CborSerializable {
public final String text;
@JsonCreator
public TextTransformed(String text) {
this.text = text;
}
}

public static Behavior<Command> create() {
return Behaviors.setup(context -> {
context.getLog().info("Registering myself with receptionist");
context.getSystem().receptionist().tell(Receptionist.register(WORKER_SERVICE_KEY, context.getSelf().narrow()));

return Behaviors.receive(Command.class)
.onMessage(TransformText.class, command -> {
command.replyTo.tell(new TextTransformed(command.text.toUpperCase()));
return Behaviors.same();
}).build();
});
}
}
 

 

posted on 2021-05-12 00:20  杨杨09265  阅读(800)  评论(0编辑  收藏  举报