采用Grpc调用远程服务(博主的服务是注册在eureka上的),一般是通过grpc的stub对象去调用,如果需要向服务端传递参数,比如日志追踪用到的traceId,这个时候可以使用grpc的拦截器去实现。实现步骤如下
1.客户端
1.1 客户端先新建拦截器,实现ClientInterceptor接口,代码如下
package cn.swiftpass.upay.payment.ags.interceptor.grpc;
import io.grpc.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.UUID;
/**
* grpc客户端拦截器
* @author *********
* @date 2022/1/13 14:34
* @Description
*/
@GrpcGlobalClientInterceptor
@Slf4j
@Component
public class GrpcClientInterceptor implements ClientInterceptor {
//客户端header的ORDER_TRACE
static final Metadata.Key<String> ORDER_TRACE = Metadata.Key.of(SysParamConstant.ORDER_TRACE, Metadata.ASCII_STRING_MARSHALLER);
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) {
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
// 将订单追踪对象放入header中,供下一步应用使用
addOrderTrace(headers);
// 继续下一步
super.start(new ForwardingClientCallListener.SimpleForwardingClientCallListener<RespT>(responseListener) {
@Override
public void onHeaders(Metadata headers) {
//服务端传递回来的header
log.info("header received from server {}", headers);
super.onHeaders(headers);
}
}, headers);
}
};
}
/**
* 将订单追踪对象放入header中
* @param headers
*/
private void addOrderTrace(Metadata headers) {
RequestHolder holder = RequestHolder.getFromRequestContext();
//放入客户端的header
headers.put(ORDER_TRACE, JsonUtil.obj2String(holder.getOrderTrace()));
}
}
1.2 改造服务调用时的stub,具体如下,stub是通过自动注入获取的
Channel channel = ClientInterceptors.intercept(stub.getChannel(), new GrpcClientInterceptor());
stub= *****grpc.newFutureStub(channel);
2.改造服务端,实现ServerInterceptor接口,代码如下
package cn.swiftpass.upay.payment.config;
import io.grpc.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.UUID;
/**
* @author *****
* @date 2022/1/13 15:22
* @Description
*/
@GrpcGlobalServerInterceptor
@Slf4j
@Component
public class GrpcServerInterceptor implements ServerInterceptor {
//客户端header的traceId
static final Metadata.Key<String> ORDER_TRACE = Metadata.Key.of(SysParamConstant.ORDER_TRACE, Metadata.ASCII_STRING_MARSHALLER);
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(
ServerCall<ReqT, RespT> call,
final Metadata requestHeaders,
ServerCallHandler<ReqT, RespT> next) {
// @1 从客户端设置的header信息-traceid
log.info("grpc header received from client:" + requestHeaders);
OrderTrace orderTrace = JsonUtil.string2Obj(requestHeaders.get(ORDER_TRACE),OrderTrace.class);
log.info("订单追踪orderTrace = {}",orderTrace);
// 继续
return next.startCall(new ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(call) {
@Override
public void sendHeaders(Metadata responseHeaders) {
// @2 响应客户端设置服务端Header信息
super.sendHeaders(responseHeaders);
}
@Override
public void close(Status status, Metadata trailers) {
super.close(status, trailers);
}
}, requestHeaders);
}
}
3.结果