在一次rpc请求过程中我们可能不仅仅要使用req里的数据,可能也需要在metadata中放入一些通用数据,比如token、客户端上报的经纬度等信息
grpc-java采用拦截器的方式发送metedata
public class PayClientInterceptor implements ClientInterceptor {
@Override
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel channel) {
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(channel.newCall(method, callOptions)) {
@Override
public void start(Listener<RespT> responseListener, Metadata headers) {
headers.put(Metadata.Key.of("token", ASCII_STRING_MARSHALLER), UUID.randomUUID().toString().replaceAll("-",""));
super.start(responseListener, headers);
}
};
}
}
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package com.example.payservice;
import io.grpc.*;
import io.grpc.stub.MetadataUtils;
import java.util.UUID;
public class App {
public static void main(String[] args) {
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost",10083)
.usePlaintext()
.build();
Metadata metadata = new Metadata();
metadata.put( Metadata.Key.of("token",Metadata.ASCII_STRING_MARSHALLER), UUID.randomUUID().toString().replaceAll("-",""));
Channel headChannel = ClientInterceptors.intercept(channel, MetadataUtils.newAttachHeadersInterceptor(metadata));
PayServiceGrpc.PayServiceBlockingStub payServiceBlockingStub = PayServiceGrpc.newBlockingStub(headChannel);
PayServicePbEntity.payOrderRes res = payServiceBlockingStub.payOrder(PayServicePbEntity.payOrderReq.newBuilder().setOrderId("order_1")
.build());
System.out.println("resCode:"+res.getRetCode()+"\\tresMsg:"+res.getRetMsg());
}
}
服务端也需要使用拦截器接收数据
/*
* This Java source file was generated by the Gradle 'init' task.
*/
package com.example.payservice;
import com.example.payservice.impl.PayServiceImpl;
import com.example.payservice.interceptor.MetadataInterceptor;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
public class App {
public static void main(String[] args) throws IOException, InterruptedException {
Server server = ServerBuilder.forPort(10083)
.addService(new PayServiceImpl())
.intercept(new MetadataInterceptor())
.build();
server.start();
server.awaitTermination();
}
}
package com.example.payservice.impl;
import com.example.payservice.PayServiceGrpc;
import com.example.payservice.PayServicePbEntity;
import io.grpc.stub.StreamObserver;
public class PayServiceImpl extends PayServiceGrpc.PayServiceImplBase {
@Override
public void payOrder(PayServicePbEntity.payOrderReq request, StreamObserver<PayServicePbEntity.payOrderRes> responseObserver) {
System.out.println("payOrder,order_Id:"+request.getOrderId());
responseObserver.onNext(PayServicePbEntity.payOrderRes.newBuilder().setRetCode(0)
.setRetMsg("支付成功")
.build());
responseObserver.onCompleted();
}
}
package com.example.payservice.interceptor;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
public class MetadataInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
String token = headers.get(Metadata.Key.of("token", Metadata.ASCII_STRING_MARSHALLER));
System.out.println("token:"+token);
return next.startCall(call, headers);
}
}
相比Java来说,go语言显得更清晰、简洁