【发布时间】:2018-12-20 12:22:35
【问题描述】:
对于一个由 proto 文件定义的简单 gRPC 服务:
service HelloService {
rpc sayHello() returns (stream string)
}
在我开始处理来自服务器的响应之前,如何在客户端先等待标头到达?我尝试使用 ClientInterceptor 并覆盖 onHeaders() 方法,但是在对 sayHello() 的调用已经完成后会调用它。如何验证 sayHello 客户端中的特定标头并根据标头的有效性继续调用?
public class SomeHeaderInterceptor implements ClientInterceptor {
private static final String FULL_METHOD_NAME = "sayHello";
public static CallOptions.Key<String> someHeader = CallOptions.Key.of("some_header_active", "false");
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> methodDescriptor,
CallOptions callOptions, Channel channel) {
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(channel.newCall(methodDescriptor, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
super.start(new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(responseListener) {
@Override
public void onHeaders(Metadata headers) {
Metadata.Key<String> SAYHELLO_ACTIVE_HEADER = Metadata.Key.of("some_header_active",
Metadata.ASCII_STRING_MARSHALLER);
if (methodDescriptor.getFullMethodName().equals(FULL_METHOD_NAME)) {
if (!headers.containsKey(SAYHELLO_ACTIVE_HEADER)) {
LOGGER.logError("some_header activation missing from header: " + headers);
} else {
callOptions.withOption(someHeader, "true");
Context.current().withValue(Context.key("test"), "testvalue");
}
}
super.onHeaders(headers);
}
}, headers);
}
};
}
sayHello 的代码如下:
public Iterator<String> sayHello() {
Iterator<String> stream = blockingStub.sayHello();
// wait for the sayhello active header
boolean isActive = Boolean.parseBoolean(blockingStub.getCallOptions().getOption(SomeHeaderInterceptor. someHeader));
System.out.println("the some_header header value is: " + isActive);
System.out.println("the context key : " + Context.key("test").get(Context.current()));
return stream;
}
在上面的 sayHello() 代码中,它不等待标头到达并在 onHeaders() 中设置上下文。我怎样才能做到这一点?在我验证服务器发送的流中存在 some_header 后,我只想将流返回给客户端调用者。
【问题讨论】: