我们将Java GRPC用于内部服务之一,并且有一个服务器端拦截器,可用于从标头中获取信息,并将其设置在内部使用ThreadLocal的日志记录上下文中。
因此,在拦截器中,我们执行以下操作:
LogMessageBuilder.setServiceName("some-service");
final String someHeaderWeWant = headers.get(HEADER_KEY);
final LoggerContext.Builder loggingContextBuilder = new LoggerContext.Builder()
.someFieldFromHeaders(someHeaderWeWant);
LoggerContext.setContext(loggingContextBuilder.build());
Run Code Online (Sandbox Code Playgroud)
然后,在我们的服务电话中,我们将像这样访问它:
LoggingContext loggingContext = LoggingContext.getCurrent()
Run Code Online (Sandbox Code Playgroud)
但是,当前上下文有时会为空。
然后,我们尝试使用GRPC Context类,如下所示:
LogMessageBuilder.setServiceName("some-service");
final String someHeaderWeWant = headers.get(HEADER_KEY);
final LoggerContext.Builder loggingContextBuilder = new LoggerContext.Builder()
.someFieldFromHeaders(someHeaderWeWant);
Context.current().withValue(LOGGING_CONTEXT_KEY, loggingContextBuilder.build()).attach()
Run Code Online (Sandbox Code Playgroud)
然后像在服务调用中那样访问它:
LoggingContext context = LOGGING_CONTEXT_KEY.get(Context.current())
Run Code Online (Sandbox Code Playgroud)
但是有时也为空,并且如果我打印出内存地址,则无论我是否附加在拦截器中,上下文的早期似乎始终是ROOT上下文,但是在几次调用之后,上下文是正确的,并且记录器数据在那里这应该。
因此,如果有人有任何想法或更好的方法将数据从拦截器传播到服务调用,我将很乐意听到它。
可以在不同的线程上调用每个回调,因此必须为每个回调设置线程本地。看来您可能不小心将上下文用于其他 RPC。
grpc-java 0.12.0应该在本周发布。上下文已部分集成到0.12.0中,并且我们还添加Contexts.interceptCall()了正是您所需要的内容:它为每个回调附加和分离上下文。
在0.12.0中,您现在应该看到为每个服务器调用(而不是ROOT)创建了新的上下文,以及从客户端调用传播到StreamObserver回调的上下文。
另一个要注意的ThreadLocal Context是,与之不同的是,我们打算将其严格限定范围:之后attach(),通常应尝试到detach()。
| 归档时间: |
|
| 查看次数: |
2409 次 |
| 最近记录: |