在过去,我们有ThreadLocal用于程序携带数据以及请求路径,因为所有请求处理都是在该线程上完成的,而像logback这样的东西用于MDC.put("requestId",getNewRequestId());
然后scala和函数式编程出现了,Futures出现了,随之而来的是Local.scala(至少我知道twitter Futures有这个类).Future.scala知道Local.scala并通过所有map/flatMap等等传递上下文功能,这样我仍然可以做Local.set("requestId",getNewRequestId()); 在经过多个线程之后再下游,我仍然可以使用Local.get(...)访问它
Soooo,我的问题是在java中,我可以使用LocalContext或某个对象(不确定名称)使用新的CompletableFuture做同样的事情,并且通过这种方式,我可以修改logback MDC上下文以将其存储在该上下文中而不是一个ThreadLocal,这样我就不会丢失请求ID,所有我的日志都会通过thenApply,thenAccept等等仍然可以正常工作,并且在logback配置中使用-XrequestId标志
编辑:
举个例子.如果您有请求进入并且您正在使用log4j或logback,则在过滤器中,您将设置MDC.put("requestId",requestId),然后在您的应用程序中,您将记录许多日志语句
log.info("request came in for url="+url);
log.info("request is complete");
Run Code Online (Sandbox Code Playgroud)
现在,它将在日志输出中显示
INFO {time}: requestId425 request came in for url=/mypath
INFO {time}: requestId425 request is complete
Run Code Online (Sandbox Code Playgroud)
这是使用ThreadLocal的技巧来实现这一点.在twitter上,我们在scala中使用scala和twitter Futures以及Local.scala类.Local.scala和Future.scala捆绑在一起,因为我们可以实现上面的场景仍然很好,我们所有的日志语句都可以记录请求ID,所以开发人员永远不必记住记录请求ID,你可以追踪单个客户请求具有该ID的响应周期.
我在java中没有看到这个:(这是非常不幸的,因为有很多用例.也许有些东西我看不到?
我正在学习 CompletableFuture API,有一个例子:
CompletableFuture.completedFuture(url)
.thenComposeAsync(this::readPage, executor)
.thenApply(this::getImageURLs)
.thenApply(this::saveFoundImages)
.....
Run Code Online (Sandbox Code Playgroud)
我有一个问题:如果我将thenComposeAsync(...)方法作为第一个调用,链中的其他方法会在executor我通过参数传递的方法中执行,还是应该使用async调用其他方法以在特定执行程序中异步执行?
java concurrency multithreading asynchronous completable-future