Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我的Grpc客户端interceptor没有正确的反应器上下文?_Java_Spring Webflux_Project Reactor_Grpc Java - Fatal编程技术网

Java 为什么我的Grpc客户端interceptor没有正确的反应器上下文?

Java 为什么我的Grpc客户端interceptor没有正确的反应器上下文?,java,spring-webflux,project-reactor,grpc-java,Java,Spring Webflux,Project Reactor,Grpc Java,我试图理解反应堆上下文以及为什么会出现此错误: reactor.core.Exceptions$ErrorCallbackNotImplemented:java.util.NoTouchElementException:Context不包含密钥 我有一个WebFilter,可以编写一些上下文 public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { return chain.filte

我试图理解反应堆上下文以及为什么会出现此错误:

reactor.core.Exceptions$ErrorCallbackNotImplemented:java.util.NoTouchElementException:Context不包含密钥

我有一个WebFilter,可以编写一些上下文

public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
  return chain.filter(exchange)
      .contextWrite(Context.of("CONTEXT-HEADER", "foobar"));
}
我的grpc调用是通过控制器方法完成的

@GetMapping(path="test")
public Mono<String> test() {
  return Mono.just(grpcStub.call(RequestBuilder.build()));
}
@GetMapping(path=“test”)
公共单声道测试(){
返回Mono.just(grpcStub.call(RequestBuilder.build());
}
我在
context.get(“context-HEADER”)
调用中遇到上述错误。 我应该注意,当在控制器方法中调用时,从上下文获取头的相同代码可以很好地工作。但在调用调用ClientInterceptor的grpc方法后,反应堆管道似乎在某个点中断


是什么导致反应器链断裂?

反应器上下文通过订阅链从下到上传播

订阅从底部开始,订阅方在每一步都将其当前上下文提供给发布方。在下一步中,publisher成为订阅者并将上下文传播到下一个publisher,等等。请参见
reactor.core.CorePubliser
reactor.core.corepubscriber

例如,在下面的链中

1: Mono.just(...);
2:     .flatMap(
           ... 
3:         Mono.just(...).subscribe()
           ...
         )
4:     .contextWrite(...);
5:     .flatMap(...);
6:     .subscribe();
反应器操作员从反应流中接收发布者和订阅者

第1行的操作员是发布者,第6行的操作员是订阅者,第2、4、5行的操作员都是

第5、6行的上下文为空;在第4行填充,并且包含在1和2处的运算符可以使用填充的上下文

第3行看不到上下文,因为上下文“不订阅”。即使它位于操作符内部,也可以访问上下文

在您的拦截器中,就像第3行一样,您“手动”订阅,而您的订阅没有任何上下文

Mono.context(上下文->{
Metadata.KeyKey=
Metadata.Key.of(“CONTEXT-HEADER”,Metadata.ASCII\u STRING\u MARSHALLER);
headers.put(key,context.get(“context-HEADER”);
委托().start(responseListener,headers);
返回Mono.empty();
}).subscribe();

我不知道有哪种“开箱即用”的拦截器可以访问反应堆上下文,但在调用存根之前,您可以尝试在反应堆上下文和grpc上下文之间进行手动连接。这可能是使用grpc上下文的一个例子。

我认为这是一个很好的解释。感谢您简化了我的示例,并向我展示了问题所在
@GetMapping(path="test")
public Mono<String> test() {
  return Mono.just(grpcStub.call(RequestBuilder.build()));
}
1: Mono.just(...);
2:     .flatMap(
           ... 
3:         Mono.just(...).subscribe()
           ...
         )
4:     .contextWrite(...);
5:     .flatMap(...);
6:     .subscribe();