ProtobufRpcEngine目前是作为 Hadoop RPC 引擎唯一的实现方式;WritableRpcEngine在 3.2.1 版本已经标识为废弃,但依旧是默认实现的 RPC 引擎
和 WritableRpcEngine 相比,ProtobufRpcEngine 的使用要麻烦的多,主要是在接口的定义和实现的写法上有区别
定义协议
定义Proto协议
根据 Protocol 的语法,定义一个服务MetaInfo,通过该服务的getMetaInfo接口,可以获取到元数据的信息
/*** 生成java代码指令* protoc --java_out=. CustomProtocol.proto**/option java_package = "org.apache.hadoop.rpc.protobuf";option java_outer_classname = "CustomProtos";option java_generic_services = true;option java_generate_equals_and_hash = true;package hadoop.common;service MetaInfo {rpc getMetaInfo(GetMetaInfoRequestProto) returns (GetMetaInfoResponseProto);}message GetMetaInfoRequestProto {required string path = 1;}message GetMetaInfoResponseProto {required string info = 1;}
[
](https://blog.csdn.net/zhanglong_4444/article/details/105630023)
根据定义好的proto协议生成java类,导入项目
将定义好的协议保存成文件,命名为 CustomProtocol.proto 。在该文件的目录下执行命令
MacBook-Pro:proto sysadmin$ ls -ltotal 8-rw-r--r--@ 1 sysadmin staff 526 4 20 09:56 CustomProtocol.protoMacBook-Pro:proto sysadmin$MacBook-Pro:proto sysadmin$MacBook-Pro:proto sysadmin$ protoc --java_out=. CustomProtocol.protoMacBook-Pro:proto sysadmin$MacBook-Pro:proto sysadmin$MacBook-Pro:proto sysadmin$ ls -ltotal 8-rw-r--r--@ 1 sysadmin staff 526 4 20 09:56 CustomProtocol.protodrwxr-xr-x 3 sysadmin staff 96 4 20 11:53 orgMacBook-Pro:proto sysadmin$MacBook-Pro:proto sysadmin$MacBook-Pro:proto sysadmin$MacBook-Pro:proto sysadmin$ cd org/apache/hadoop/rpc/protobufMacBook-Pro:protobuf sysadmin$MacBook-Pro:protobuf sysadmin$ ls -ltotal 104-rw-r--r-- 1 sysadmin staff 49880 4 20 11:53 CustomProtos.javaMacBook-Pro:protobuf sysadmin$MacBook-Pro:protobuf sysadmin$
这时在该目录下,会有一个文件目录生成,层级为我们定义好的org.apache.hadoop.rpc.protobuf路径,将里面生成的 java 文件 CustomProtos.java 导入到项目中,存放路径与定义好的路径一样
根据定义好的proto协议定义接口
创建一个接口,集成生成JAVA类中的CustomProtos.MetaInfo.BlockingInterface接口
// 接口信息供server和client端使用@ProtocolInfo(protocolName = "org.apache.hadoop.rpc.CustomProtos$MetaInfoProtocol",protocolVersion = 1)public interface MetaInfoProtocolextends CustomProtos.MetaInfo.BlockingInterface {}
实现接口协议
创建一个类,实现刚刚定义好的MetaInfoProtocol接口,并且实现里面的方法。这个需要自己去写代码逻辑。注意返回值和返回对象的写法不太一样
// 实现类public static class MetaInfoServer implements MetaInfoProtocol {@Overridepublic CustomProtos.GetMetaInfoResponseProto getMetaInfo(RpcController controller,CustomProtos.GetMetaInfoRequestProto request) throwsServiceException {//获取请求参数final String path = request.getPath();return CustomProtos.GetMetaInfoResponseProto.newBuilder().setInfo(path + ":3 - {BLOCK_1,BLOCK_2,BLOCK_3....").build();}}
创建Server服务,注册协议,并启动RPC服务
public static void main(String[] args) throws Exception{//1. 构建配置对象Configuration conf = new Configuration();//2. 协议对象的实例MetaInfoServer serverImpl = new MetaInfoServer();BlockingService blockingService =CustomProtos.MetaInfo.newReflectiveBlockingService(serverImpl);//3. 设置协议的RpcEngine为ProtobufRpcEngineRPC.setProtocolEngine(conf, MetaInfoProtocol.class,ProtobufRpcEngine.class);//4. 构建RPC框架RPC.Builder builder = new RPC.Builder(conf);//5. 绑定地址builder.setBindAddress("localhost");//6. 绑定端口builder.setPort(7777);//7. 绑定协议builder.setProtocol(MetaInfoProtocol.class);//8. 调用协议实现类builder.setInstance(blockingService);//9. 创建服务RPC.Server server = builder.build();//10. 启动服务server.start();}
创建Client服务,请求数据接口
public static void main(String[] args) throws Exception {//1. 构建配置对象Configuration conf = new Configuration();//2. 设置协议的RpcEngine为ProtobufRpcEngineRPC.setProtocolEngine(conf, Server.MetaInfoProtocol.class,ProtobufRpcEngine.class);//3. 拿到RPC协议Server.MetaInfoProtocol proxy = RPC.getProxy(Server.MetaInfoProtocol.class, 1L,new InetSocketAddress("localhost", 7777), conf);//4. 发送请求CustomProtos.GetMetaInfoRequestProto obj =CustomProtos.GetMetaInfoRequestProto.newBuilder().setPath("/meta").build();CustomProtos.GetMetaInfoResponseProto metaData = proxy.getMetaInfo(null, obj);//5. 打印元数据System.out.println(metaData.getInfo());}
