当前位置: 首页 > 知识库问答 >
问题:

从一个演员开始运行一个完整的未来

陶修洁
2023-03-14

[信息][05/05/2017 13:12:25.650][Akka-Spring-demo-Akka.actor.default-dispatcher-5][Akka://Akka-spring-demo/deadletters]从演员[Akka://Akka-spring-demo/deadletters]到演员[Akka://Akka-spring-demo/deadletters]的消息[java.lang.string]没有传递。[1]遇到的一纸空文。可以通过配置设置'Akka.log-dead-letters'和'Akka.log-dead-letters-dhider-shutdown'关闭或调整此日志记录。

这是我的代码。这是调用参与者的控制器:

@Component
@Produces(MediaType.TEXT_PLAIN)
@Path("/")
public class AsyncController {
    @Autowired
    private ActorSystem system;

    private ActorRef getGreetingActorRef() {
        ActorRef greeter = system.actorOf(SPRING_EXTENSION_PROVIDER.get(system)
                  .props("greetingActor"));

        return greeter;
    }

    @GET
    @Path("/foo")
    public void test(@Suspended AsyncResponse asyncResponse, @QueryParam("echo") String echo) {
        ask(getGreetingActorRef(), new Greet(echo), 1000)
            .thenApply((greet) -> asyncResponse.resume(Response.ok(greet).build()));
    }
}

以下是服务:

@Component
public class GreetingService {
    public CompletableFuture<String> greetAsync(String name) {
        return CompletableFuture.supplyAsync(() -> "Hello, " + name);
    }
}
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class GreetingActor extends AbstractActor {
    @Autowired
    private GreetingService greetingService;

    @Autowired
    private ActorSystem system;

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(Greet.class, this::onGreet)
                .build();
    }

    private void onGreet(Greet greet) {
        greetingService.greetAsync(greet.getMessage())
            .thenAccept((greetingResponse) -> getSender().tell(greetingResponse, getSelf()));
    }

}

警告当使用将来的回调时,在actor内部,您需要小心地避免关闭包含actor的引用,即不要从回调中调用方法或访问封闭actor上的可变状态。这将破坏actor封装,并可能引入同步bug和争用条件,因为回调将同时调度到封装actor。不幸的是,还没有一种方法可以在编译时检测这些非法访问。另请参见:参与者和共享的可变状态

因此,我认为这个想法是将结果传输到self(),之后可以执行getSender().tell(response,getSelf())。

因此,我将代码修改为:

@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class GreetingActor extends AbstractActor {
    @Autowired
    private GreetingService greetingService;

    @Autowired
    private ActorSystem system;

    @Override
    public Receive createReceive() {
        return receiveBuilder()
                .match(Greet.class, this::onGreet)
                .match(String.class, this::onGreetingCompleted)
                .build();
    }

    private void onGreet(Greet greet) {
        pipe(greetingService.greetAsync(greet.getMessage()), system.dispatcher()).to(getSelf());
    }

    private void onGreetingCompleted(String greetingResponse) {
        getSender().tell(greetingResponse, getSelf());
    }

}
@Component
public class GreetingService {
    public String greet(String name) {
        return "Hello, " + name;
    }
}
private void onGreet(Greet greet) {
    getSender().tell(greetingService.greet(greet.getMessage()), getSelf());
}

那一切都很好。因此,我似乎已经正确地设置了基本的Java/Spring/Akka,只是当试图从我的演员中调用一个完整的未来时,问题就开始了。

如有任何帮助,不胜感激,谢谢!

共有1个答案

戚侯林
2023-03-14

getSender方法只在同步处理消息期间可靠地返回发送方的引用。

在第一种情况下,您有:

 greetingService.greetAsync(greet.getMessage())
        .thenAccept((greetingResponse) -> getSender().tell(greetingResponse, getSelf()));

这意味着一旦future完成,getSender()就会被异步调用。不再可靠了。您可以将其更改为:

 ActorRef sender = getSender();
 greetingService.greetAsync(greet.getMessage())
        .thenAccept((greetingResponse) -> sender.tell(greetingResponse, getSelf()));
pipe(greetingService.greetAsync(greet.getMessage()), system.dispatcher()).to(getSelf());
pipe(greetingService.greetAsync(greet.getMessage()), system.dispatcher()).to(getSender());
 类似资料:
  • 我想要一个完整的未来,只发出完成的信号(例如,我没有返回值)。 我可以将CompletableFuture实例化为: 但是我应该向完整的方法提供什么呢?例如,我不能做

  • 我希望有几个参与者(它们表示基于Akka IO部分的TCP连接)。这些参与者应更新通用模型(内存中)。此模型保存在管理此模型的其他参与者中。 我的问题是,我如何设置这个结构?有没有办法告诉akka某个演员只有一个实例? 另一种选择是:我已经有了一个actor,它接受新的TCP/IP连接并将它们传递给新的actor。现在我可以在连接接收器中创建这个“模型管理器角色”,并将这个角色传递给新创建的每个连

  • 是否有一种方法可以尝试等待一段时间,然后返回不同的结果,而不取消超时后的未来? 我有一个服务(我们称之为),它跑出去做自己的事情。它返回一个结果: 我愿意[阻止并]等待它一小段时间(比方说2秒)。如果它没有完成,我希望返回一个不同的结果,但我希望服务继续做它自己的事情。然后查询服务是否完成(例如,通过websockets或其他方式)将是客户端的工作。 即。我们有以下几个案例: 花费%1 s并完成其

  • 本文向大家介绍说一下一个产品从开始到上线的整个过程?相关面试题,主要包含被问及说一下一个产品从开始到上线的整个过程?时的应答技巧和注意事项,需要的朋友参考一下 此问题考察项目管理及从0到1的项目上线能力。主要包括以下几个环节,每个环节都可以展开来说: 想法形成-市场调研-需求分析-产品规划-需求落地-开发测试-问题跟进与解决-验收产品-内测体验-发布上线-数据跟踪反馈、用户问题收集-迭代优化。

  • 5.6 一个完整的流程 到之前为止,我们了解了URL和抽取相关API,一个爬虫已经基本编写完成了。 @TargetUrl("https://github.com/\\w+/\\w+") @HelpUrl("https://github.com/\\w+") public class GithubRepo { @ExtractBy(value = "//h1[@class='entry-t

  • 本文向大家介绍取一个整数a从右端开始的4~7位。相关面试题,主要包含被问及取一个整数a从右端开始的4~7位。时的应答技巧和注意事项,需要的朋友参考一下 【参考答案】