GRPC Java将数据从服务器拦截器传递到rpc服务调用

时间:2016-01-20 16:35:34

标签: java grpc

我们正在使用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());

然后在我们的服务电话中,我们像这样访问它:

LoggingContext loggingContext = LoggingContext.getCurrent()

但是当前的上下文在某些时候是空的。

然后我们尝试使用如下的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()

然后在服务电话中访问它,如:

LoggingContext context = LOGGING_CONTEXT_KEY.get(Context.current())

然而,这有时也是空的,如果我打印出内存地址,看起来上下文的早期始终是ROOT上下文而不管我是否在拦截器中附加,但是在几次调用之后上下文是正确的并且记录器数据是应该的。

因此,如果有人有任何想法或更好的方法将数据从拦截器传播到服务电话,我很乐意听到。

1 个答案:

答案 0 :(得分:3)

每个回调都可以在不同的线程上调用,因此必须为每个回调设置线程本地。您可能会意外地获得用于其他 RPC的上下文。

grpc-java 0.12.0应该在本周发布。 Context已部分集成在0.12.0中,我们还添加了Contexts.interceptCall(),这正是您所需要的:它为每个回调附加和分离上下文。

在0.12.0中,您现在应该看到为每个服务器调用(而不是ROOT)创建的新上下文以及从客户端调用传播到StreamObserver回调的上下文。

另外需要注意的是,与ThreadLocal Context不同的是...... attach()之后,通常应该尝试detach()