grpc java异步调用服务器侦听器
我有一个GRPCJava服务器,需要在处理请求之前对身份验证服务进行异步调用。我认为这应该在拦截器中完成,但它需要从interceptCall()同步返回侦听器 类AuthInterceptor实现ServerInterceptor{ @凌驾 publicservercall.listenerinterceptcall( 服务器呼叫, 元数据头, ServerCallHandler下一步 ) { String token=”“;//从标头获取标记 authService.authorize(令牌).subscribe( 确定->//处理请求 错误->调用.关闭(Status.UNAUTHENTICATED,标题) ); //这里我们需要返回一个侦听器,但我们还没有开始调用 } }grpc java异步调用服务器侦听器,java,asynchronous,authorization,interceptor,grpc,Java,Asynchronous,Authorization,Interceptor,Grpc,我有一个GRPCJava服务器,需要在处理请求之前对身份验证服务进行异步调用。我认为这应该在拦截器中完成,但它需要从interceptCall()同步返回侦听器 类AuthInterceptor实现ServerInterceptor{ @凌驾 publicservercall.listenerinterceptcall( 服务器呼叫, 元数据头, ServerCallHandler下一步 ) { String token=”“;//从标头获取标记 authService.authorize(令牌
因此,问题是:如何从ServerInterceptor进行异步调用,如果无法完成,那么什么是对请求进行异步身份验证的正确方法?我知道这可以通过StreamObservators直接在grpc服务中完成,但请求授权是一个交叉问题,拦截器似乎是一个完美的地方。您确实需要返回一个
ServerCall.Listener
。但是,由于您不知道要委托给的侦听器
,因此可以重写侦听器
中的每个方法以将回调添加到队列中。身份验证完成后,排空队列
class DelayedListener<ReqT> extends Listener<ReqT> {
private Listener<ReqT> delegate;
private List<Runnable> events = new ArrayList<Runnable>();
@Override public synchronized void onMessage(ReqT message) {
if (delegate == null) {
events.add(() -> delegate.onMessage(message));
} else {
delegate.onMessage(message);
}
}
...
public synchronized void setDelegate(Listener<ReqT> delegate) {
this.delegate = delegate;
for (Runnable runnable : events) {
runnable.run();
}
events = null;
}
}
类DelayedListener扩展了Listener{
私人听众代表;
私有列表事件=新的ArrayList();
@覆盖公共同步void onMessage(请求消息){
if(委托==null){
添加(()->delegate.onMessage(message));
}否则{
onMessage(消息);
}
}
...
公共同步的void setDelegate(侦听器委托){
this.delegate=委托;
for(可运行:事件){
runnable.run();
}
事件=空;
}
}
很好的解决方案。它是否适用于ConcurrentLinkedQueue而不是回调和setDelegate()上的同步?您的解决方案非常有效,解决了一般问题。我找到了另一个可能的解决方案:一个像往常一样转发所有回调并且只延迟
onHalfClosed()
回调的SimpleForwardingServerCallListener
似乎也适用于我。或者此解决方案存在线程问题?在直接转发新事件之前,您需要确保“耗尽”所有排队事件。如果您只是使用ConcurrentLinkedQueue+volatile delegate,那么您有两个竞争:1)此.delegate=delegate位于setDelegate()
的开头,让新事件在旧事件之前“竞争”,或2)此.delegate=delegate位于setDelegate()
的末尾,事件可能会“卡住”在队列中。排队时你真的需要一把锁。如果委托!=null
和调用runnable.run()
时,但它更复杂。请参阅GRPC中的DelayedStream一元流和服务器流的存根调用延迟调用应用程序,直到onHalfClosed()
。但是,1)其他拦截器仍将运行,2)客户端流和bidi流不是这样,3)生态系统中有一些备用服务器存根浮动,它们的行为可能不同。@AbhijitSarkar,是的。它在等待授权完成时排队,然后您使用setDelegate()排空队列。您是否可以更新您的问题,显示您使用DelayedListener
的结果?我不清楚如何把这些点连接起来。
class DelayedListener<ReqT> extends Listener<ReqT> {
private Listener<ReqT> delegate;
private List<Runnable> events = new ArrayList<Runnable>();
@Override public synchronized void onMessage(ReqT message) {
if (delegate == null) {
events.add(() -> delegate.onMessage(message));
} else {
delegate.onMessage(message);
}
}
...
public synchronized void setDelegate(Listener<ReqT> delegate) {
this.delegate = delegate;
for (Runnable runnable : events) {
runnable.run();
}
events = null;
}
}