GRPC Java 将数据从服务器拦截器传递给rpc服务调用
GRPC Java pass data from server interceptor to rpc service call
我们正在为我们的一项内部服务使用 Java GRPC,我们有一个服务器端拦截器,我们用它从 headers 获取信息并将它们设置在日志记录上下文中在内部使用 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());
然后在我们的服务调用中,我们像这样访问它:
LoggingContext loggingContext = LoggingContext.getCurrent()
然而,当前上下文有时为空。
然后我们尝试使用 GRPC 上下文 class,如下所示:
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()
然后在服务调用中访问它,如:
LoggingContext context = LOGGING_CONTEXT_KEY.get(Context.current())
然而,这有时也是空的,如果我打印出内存地址,那么无论我在拦截器中附加什么,上下文的早期似乎总是 ROOT 上下文,但是在几次调用之后上下文是正确的并且记录器数据就在那里。
因此,如果有人有任何想法或更好的方法将数据从拦截器传播到服务调用,我很想听听。
每个回调都可以在不同的线程上调用,因此必须为每个回调设置 thread-local。看来您可能不小心获得了用于 other RPC 的上下文。
grpc-java 0.12.0 应该会在本周发布。 0.12.0 已经部分集成了上下文,我们还添加了 Contexts.interceptCall()
这正是您所需要的:它为每个回调附加和分离上下文。
在 0.12.0 中,您现在应该会看到为每个服务器调用(而不是 ROOT)创建的新上下文以及从客户端调用传播到 StreamObserver
回调的上下文。
作为另一个注意事项,与 ThreadLocal
不同,Context
旨在限制范围:在 attach()
之后,您通常应该有一个 try-finally 到 detach()
.
我们正在为我们的一项内部服务使用 Java GRPC,我们有一个服务器端拦截器,我们用它从 headers 获取信息并将它们设置在日志记录上下文中在内部使用 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());
然后在我们的服务调用中,我们像这样访问它:
LoggingContext loggingContext = LoggingContext.getCurrent()
然而,当前上下文有时为空。
然后我们尝试使用 GRPC 上下文 class,如下所示:
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()
然后在服务调用中访问它,如:
LoggingContext context = LOGGING_CONTEXT_KEY.get(Context.current())
然而,这有时也是空的,如果我打印出内存地址,那么无论我在拦截器中附加什么,上下文的早期似乎总是 ROOT 上下文,但是在几次调用之后上下文是正确的并且记录器数据就在那里。
因此,如果有人有任何想法或更好的方法将数据从拦截器传播到服务调用,我很想听听。
每个回调都可以在不同的线程上调用,因此必须为每个回调设置 thread-local。看来您可能不小心获得了用于 other RPC 的上下文。
grpc-java 0.12.0 应该会在本周发布。 0.12.0 已经部分集成了上下文,我们还添加了 Contexts.interceptCall()
这正是您所需要的:它为每个回调附加和分离上下文。
在 0.12.0 中,您现在应该会看到为每个服务器调用(而不是 ROOT)创建的新上下文以及从客户端调用传播到 StreamObserver
回调的上下文。
作为另一个注意事项,与 ThreadLocal
不同,Context
旨在限制范围:在 attach()
之后,您通常应该有一个 try-finally 到 detach()
.