armeria - 如何将 ServiceRequestContext 传播到我的自定义线程池
问题描述
我有一个场景,它处理 armeria 请求,并将一些事件发送到guava
's EventBus
。问题是我在 EventBus 处理程序中处理事件时丢失了上下文。我想知道有没有办法让事件处理器访问ServiceRequestContext
。
class EventListener {
@Subscribe
public void process(SomeCustomizedClass event) {
final ServiceRequestContext context = ServiceRequestContext.currentOrNull();
log.info("process ServiceRequestContext context={}", context);
}
}
注册事件处理程序。
EventBus eventBus = new AsyncEventBus(ThreadPoolTaskExecutor());
eventBus.register(new EventListener());
这是我的Armeria
服务
@Slf4j
public class NameAuthRestApi {
final NameAuthService nameAuthService;
@Post("/auth")
@ProducesJson
public Mono<RealNameAuthResp> auth(RealNameAuthReq req) {
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handle((result, sink) -> {
if (result.isSuccess()) {
// I post an event here, but the event process couldn't access the ServiceRequestContext
// that's would be the problem.
eventBus.post(new SomeCustomizedClass(result));
final RealNameAuthResp realNameAuthResp = new RealNameAuthResp();
realNameAuthResp.setTradeNo(result.getTradeNo());
realNameAuthResp.setSuccess(true);
sink.next(realNameAuthResp);
sink.complete();
} else {
sink.error(new SystemException(ErrorCode.API_ERROR, result.errors()));
}
});
}
}
解决方案
你需要做:
public Mono<RealNameAuthResp> auth(ServiceRequestContxt ctx, RealNameAuthReq req) {
// Executed by an EventLoop 1.
// This thread has the ctx in its thread local.
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handle((result, sink) -> {
// Executed by another EventLoop 2.
// But this doens't.
try (SafeCloseable ignord = ctx.push()) {
if (result.isSuccess()) {
...
} else {
...
}
}
});
}
问题是句柄方法是由另一个线程执行的,该线程在其本地线程中没有 ctx。所以,你应该手动设置 ctx.
您可以使用xAsync
以下方法实现相同的效果ctx.eventLoop()
:
public Mono<RealNameAuthResp> auth(ServiceRequestContxt ctx, RealNameAuthReq req) {
return nameAuthService.auth(NameAuthConverter.CONVERTER.toDto(req))
.handleAsync((result, sink) -> {
if (result.isSuccess()) {
...
} else {
...
}
}, ctx.eventLoop());
}
推荐阅读
- cordova - 插件不支持此项目的 cordova 版本。科尔多瓦:8.1.1,失败的版本要求:> = 9.0.0
- node.js - 多次调用后没有 Access-Control-Allow-Origin 编辑 > Axios 网络错误捕获
- python - 删除时从子模型中删除文件对象
- autohotkey - AutoHotkey - 脚本在一段时间后停止工作
- typescript - Vue:无效的道具:类型
- java - 更改枢轴评估位置会导致快速排序失败
- java - 从 thymelaf 表单输入值创建 ArrayList
- java - 如何生成多合一的 Gradle 项目?
- modula-2 - 致命错误 (13):XDS Modula-2 没有程序入口点?
- python - 为什么使用 datetime 模块解析日期时格式代码“%-m”和“%-d”不起作用?