gpt4 book ai didi

java - Akka:在参与者之间通信和处理特殊状态(非错误)

转载 作者:行者123 更新时间:2023-11-30 08:14:41 25 4
gpt4 key购买 nike

我是 Akka(Java lib,v2.3.9)的新手,正在尝试了解 Actor 依赖性和回退/容错。

假设我有两个 Actor ,StormTrooperDarthVader:

// Groovy pseudo-code
class StatusReport {
private final Report report

StatusReport(Input report) {
super()
this.report = deepClone(report)
}

Input getReport() {
deepClone(this.report)
}
}

class StormTrooper extends UntypedActor {
ActorRef lordVader // Injected with reference to DarthVader

@Override
void onReceive(Object message) {
if(message instanceof PerformReport) {
PerformReport pr = message as PerformReport
Report report = ReportUtils.generateReport(pr.config)
StatusReport statusReportMsg = new StatusReport(report)
lordVader.tell(statusReportMessage, ...)
}
}
}

class DarthVader extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof StatusReport) {
// Do something meaningful with the status report.
}
}
}

在某些情况下,DarthVader 本质上是 NULL,应该是无操作。也就是说:当 StormTrooper 决定向 DarthVader 发送 StatusReport 消息时,他:

  1. 可能已配置为 Activity 且正常运行,在这种情况下,DarthVader 将正确响应状态报告;或
  2. 用户可能已采取操作(通过配置),使得 DarthVader 必须故意离线/无响应/无操作

在后一种情况下,当DarthVader假定时(我强调这一点是为了将其与DarthVader应该活着的用例区分开来/功能正常,但处于故障/错误状态)为无操作,我不确定如何将其传达给 StormTrooper,后者必须简单地调用 fizzBu​​zz#derp() 如果 DarthVader 没有操作。

解决方案#1:基于状态的空操作检测

class StormTrooper extends UntypedActor {
ActorRef lordVader // Injected with reference to DarthVader

@Override
void onReceive(Object message) {
if(message instanceof PerformReport) {
if(lordVader.isNoOp) {
fizzBuzz.derp()
} else {
PerformReport pr = message as PerformReport
Report report = ReportUtils.generateReport(pr.config)
StatusReport statusReportMsg = new StatusReport(report)
lordVader.tell(statusReportMessage, ...)
}
}
}
}

class DarthVader extends UntypedActor {
boolean isNoOpMode = false

@Override
void onReceive(Object message) {
if(message instanceof StatusReport) {
if(!isNoOpMode) {
// Do something meaningful with the status report.
}

// Obviosuly, if we are in no-op mode, do nothing.
}
}
}

我的不确定性是 DarthVader Actor /线程的所有实例都必须处于相同的状态(无操作模式开/关普遍适用于所有实例),所以我不确定这个解决方案是否可行,是否符合 Akka 最佳实践。

解决方案#2:抛出专门的异常

class StormTrooper extends UntypedActor {
ActorRef lordVader // Injected with reference to DarthVader

@Override
void onReceive(Object message) {
if(message instanceof PerformReport) {
try {
PerformReport pr = message as PerformReport
Report report = ReportUtils.generateReport(pr.config)
StatusReport statusReportMsg = new StatusReport(report)
lordVader.tell(statusReportMessage, ...)
} catch(DarthVaderNoOpException dvnoExc) {
fizzBuzz.derp()
}
}
}
}

class DarthVader extends UntypedActor {
boolean isNoOpMode = false

@Override
void onReceive(Object message) {
if(message instanceof StatusReport) {
if(!isNoOpMode) {
// Do something meaningful with the status report.
} else {
throw new DarthVaderNoOpException()
}
}
}
}

但是使用异常来控制流程是一种普遍的禁忌,甚至可能会触发内置的 Akka Supervisor 行为(对异常使用react可能会导致 Akka 重新启动 StormTrooper 等)。

解决方案#3:发回响应消息

class StormTrooper extends UntypedActor {
ActorRef lordVader // Injected with reference to DarthVader

@Override
void onReceive(Object message) {
if(message instanceof PerformReport) {
PerformReport pr = message as PerformReport
Report report = ReportUtils.generateReport(pr.config)
StatusReport statusReportMsg = new StatusReport(report)
lordVader.tell(statusReportMessage, ...)
} else if(message instanceof DarthVaderNoOp) {
fizzbuzz.derp()
}
}
}

class DarthVader extends UntypedActor {
ActorRef stormTrooper
boolean isNoOpMode = false

@Override
void onReceive(Object message) {
if(message instanceof StatusReport) {
if(!isNoOpMode) {
// Do something meaningful with the status report.
} else {
DarthVaderNoOp noOpMsg = new DarthVaderNoOp()
stormTrooper.tell(noOpMsg, ...)
}
}
}
}

但这似乎是一个麻烦且啰嗦的解决方案。

所以我问:DarthVaderStormTrooper 指示它处于无操作模式的最佳方式是什么,以便 StormTrooper 知道调用fizzBu​​zz.derp()?请记住,如果 DarthVader 处于无操作模式,则 DarthVader 的所有实例/参与者/线程都处于无操作模式,而不仅仅是一个特定实例。

最佳答案

几乎没有可能的解决方案。首先,您想阅读 if DarthVader位于NoOp从配置中选择模式,然后创建参与者(类型安全配置将正常工作)。

Config vader = conf.getConfig("vader");
bool isNoOpMode = vader.getBoolean("state");

因此您可以为应用程序通用地设置它。

对于DarthVader他本人,正如您所说,您可以做聊天解决方案(回复 StormTrooper ),或者利用您的第一种方法与 Ask 结合使用。图案。您将报告发送至DarthVader并将返回 Future,等待 DarthVader回应。

Timeout timeout = new Timeout(Duration.create(5, "seconds"));
Future<Object> future = Patterns.ask(lordVader, statusReportMsg, timeout);

请注意,您不想调用Await方法,但要处理 onComplete 内的响应,例如:

final ExecutionContext ec = system.dispatcher();

future.onComplete(new OnComplete<VaderResponse>() {
public void onComplete(Throwable failure, VaderResponse result) {
if (failure != null) {
// Derp
} else {
// Report acknowledged
}
}
}, ec);

关于java - Akka:在参与者之间通信和处理特殊状态(非错误),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29827232/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com