ProtobufRpcEngine 目前是作为Hadoop RPC 引擎唯一的实现方式.
WritableRpcEngine 在3.2.1版本已经标识为废弃,但依旧是默认实现的RPC引擎.
接下来,我们说一下如何使用, 过程比WritableRpcEngine 的使用要麻烦很多.
主要是在接口的定义和实现的写法上有区别.
1. 定义协议
1.1.定义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;
}
1.2.根据定义好的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导入到项目中, 存放路径与定义好的路径一样.
2.根据定义好的proto协议定义接口
创建一个接口,集成生成JAVA类中的CustomProtos.MetaInfo.BlockingInterface接口.
// 接口信息 供server 和client 端使用
@ProtocolInfo(
protocolName = "org.apache.hadoop.rpc.CustomProtos$MetaInfoProtocol",
protocolVersion = 1)
public interface MetaInfoProtocol
extends CustomProtos.MetaInfo.BlockingInterface {
}
3.实现接口协议
创建一个类,实现刚刚定义好的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();
}
}
4.创建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();
}
5.创建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());
}