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());
}
6.測試結果