What is the right way to use ThreadLocal in grpc interceptor?

182 views
Skip to first unread message

Chen Song

unread,
Jun 30, 2019, 10:55:29 PM6/30/19
to grpc.io
We have a gPRC service that needs to set auth/identity information in a ThreadLocal variable in a class for it to correctly call another service. The gPRC service gets the auth/identiy information from request so I am thinking to use interceptor.

To start, I have some code looking as follows.

public class ImpersonationInterceptor {
    public <ReqT, RespT> interceptCall(
        ServerCall<ReqT, RespT> serverCall, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
        Principal principal = ... // get the identify from the request
        
        AuthContext.setPrincipal(principal); // underneath it uses a ThreadLocal.

        return next.startCall(
            new SimpleForwardingServerCall<>(call) {
                public void close(Status status, Metadata trailers) {
                    AuthContext.setPrincipal(null); // clear the identity
                }
            }
        )
    }
}

Questions.

* The execution of the service method itself may not lie on the same thread to execute the interceptor, is that right?
* If true, the above is not gonna work, then the question is, what is the canonical way to set ThreadLocal variable in gRPC world? I know gRPC has Context support since 0.12, but in my case, I have to use the AuthContext's ThreadLocal mechanism.

Thanks very much in advance.

Chen

Penn (Dapeng) Zhang

unread,
Jul 3, 2019, 3:06:31 PM7/3/19
to grpc.io
>The execution of the service method itself may not lie on the same thread to execute the interceptor, is that right?
Yes.

I only see you set the principal, but don't see where/in what thread you read the principal, so I can not give you an answer. What's not possible for you to achieve your goal with ThreadLocal<AtomicReference<Principal>> as below?


static final ThreadLocal<AtomicReference<Principal>> threadLocal = new ThreadLocal<>();

public <ReqT, RespT> interceptCall(
        ServerCall<ReqT, RespT> serverCall, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
    Principal principal = ... // get the identify from the request
    final AtomicReference<Principal> principalRef = new AtomicReference<Principal>(principal);
    threadLoacal.set(
principalRef);
  return next.startCall(
      
new SimpleForwardingServerCall<>(call) {
          
public void close(Status status, Metadata trailers) {

            
principalRef.set(null); // clear the identity
          
}
      
},
      headers
);
}

Derek Perez

unread,
Jul 3, 2019, 3:32:29 PM7/3/19
to Penn (Dapeng) Zhang, grpc.io
My understanding is that a request and all associated interceptors are executed on the same thread, per request. 

--
You received this message because you are subscribed to the Google Groups "grpc.io" group.
To unsubscribe from this group and stop receiving emails from it, send an email to grpc-io+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/grpc-io/1eab44e6-5657-4a35-9e1c-8350daab6c8c%40googlegroups.com.
Reply all
Reply to author
Forward
0 new messages