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 -l
total 8
-rw-r--r--@ 1 sysadmin staff 526 4 20 09:56 CustomProtocol.proto
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$ protoc --java_out=. CustomProtocol.proto
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$ ls -l
total 8
-rw-r--r--@ 1 sysadmin staff 526 4 20 09:56 CustomProtocol.proto
drwxr-xr-x 3 sysadmin staff 96 4 20 11:53 org
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$
MacBook-Pro:proto sysadmin$ cd org/apache/hadoop/rpc/protobuf
MacBook-Pro:protobuf sysadmin$
MacBook-Pro:protobuf sysadmin$ ls -l
total 104
-rw-r--r-- 1 sysadmin staff 49880 4 20 11:53 CustomProtos.java
MacBook-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 MetaInfoProtocol
extends CustomProtos.MetaInfo.BlockingInterface {
}
实现接口协议
创建一个类,实现刚刚定义好的MetaInfoProtocol
接口,并且实现里面的方法。这个需要自己去写代码逻辑。注意返回值和返回对象的写法不太一样
// 实现类
public static class MetaInfoServer implements MetaInfoProtocol {
@Override
public CustomProtos.GetMetaInfoResponseProto getMetaInfo(RpcController controller,
CustomProtos.GetMetaInfoRequestProto request) throws
ServiceException {
//获取请求参数
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为ProtobufRpcEngine
RPC.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为ProtobufRpcEngine
RPC.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());
}