In the process of replacing an old legacy service by a new one we want to temporarily forward the requests reaching the new service to the legacy one. For HTTP requests we achieve this with a custom HttpFilter:
@Filter("/**/legacy-service/**")
public class LegacyHttpProxyFilter implements HttpFilter {
@Inject
@Named("legacy-http-client")
private ProxyHttpClient httpClient;
@Override
public Publisher<? extends HttpResponse<?>> doFilter(HttpRequest<?> request, FilterChain chain) {
return httpClient.proxy(request);
}
}
The analogous approach for GRPC would be something similar to this with a ServerInterceptor:
@Singleton
public class LegacyGrpcProxyInterceptor implements ServerInterceptor {
@Inject
@Named("legacy-grpc-client")
MyLegacyServiceGrpc.MyLegacyServiceStub legacyServiceStub;
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
return null; // How to handle GRPC requests in a generic way?
}
}
The difference is that with a ProxyHttpClient we can forward any HTTP request, while this doesn't seem to be possible with MyLegacyServiceStub GRPC stub. It looks like the right approach is to implement a custom ServerCallHandler but I don't really see how, any example would be highly appreciated.
How can I forward any incoming GRPC request?
There is such an example in grpc-java.
You are right that the core of it should be to implement a ServerCallHandler
. You will also need a MethodDescriptor
and to package them together into a ServerMethodDefinition
.
The example uses a fallback HandlerRegistry
to proxy all methods, but if you only need static proxying you could create a ServerServiceDefinition
(essentially a set of ServerMethodDefinitions
for one service) for each service you want proxied and add it to the ServerBuilder
as normal: serverBuilder.addService()
.
The rest of the example is gluing the client and server calls together, with proper flow control for streaming RPCs.