您好,登錄后才能下訂單哦!
這篇文章主要講解了“gRPC之proto及Maven插件怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“gRPC之proto及Maven插件怎么使用”吧!
protobuf 是 gRPC 中生成 API Service 的方式,在 Maven 編譯時就可以快速生成對應的Class類。
以 Maven 為例,在 gRPC 中通常使用 protobuf-maven-plugin 插件,根據一個 .proto 文件生成對應的 Java 代碼。 其本身是基于 Google 的 Protocol Buffers 工具鏈實現的。
S1 : 創建一個 .proto 文件,按照規范要求定義元數據內容
S2 : 通過 protobuf-maven-plugin
插件進行 compile 操作
S3 : protobuf-maven-plugin
調用 protoc
命令行工具,生成對應的 Java 代碼
S4 : 生成的 Java 代碼會被編譯,并打包成 Jar 包 , 最終生成可執行文件給項目使用
.proto 文件格式
syntax = "proto3"; // 定義使用的語法版本,這里是proto3 package com.example.grpc; // 定義package,用于在其他文件中引用該文件定義的類型 // 定義配置項 // - java_package :定義生成的Java類的包名 // - java_outer_classname : 定義生成的Java類的類名 option java_multiple_files = true; // 接口類 service UserService { rpc query (UserRequest) returns (UserResponse); } // 定義消息類型 message UserRequest { string name = 1; // 字段類型和名稱,以及字段標識符,用于序列化和反序列化 } // 這里的消息類型是返回值 message UserResponse { string name = 1; int32 age = 2; string address = 3; // 這里定義一個枚舉 enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } // 這里定義一個內部對象 repeated PhoneNumber phones = 4; message PhoneNumber { string number = 1; PhoneType type = 2; } }
通常一個 proto 文件中會包含以下主要內容
package: 包名,用于區分不同模塊的數據結構定義。
message: 消息體,包含多個字段,每個字段都有一個名稱和類型。
enum: 枚舉類型,定義多個枚舉值。
service: 定義 RPC 服務接口,包含多個方法,每個方法都有一個請求消息和一個響應消息。
生成一個 .class 文件
這里就可以看到,其實生成了很多文件,最重要的包括 :UserServiceGrpc ,HelloRequest 和 HelloResponse 這幾個。
使用文件
使用文件和平時使用 Class 是一致的,引入 Maven 依賴然后直接調用就行了
@Resource UserServiceGrpc.UserServiceBlockingStub userService; UserRequest userRequest = UserRequest.newBuilder().setName("test").build(); UserResponse user = userService.query(userRequest);
上面看了插件的使用,后面就來詳細看看它生成的幾個 Class 到底包含了什么 :
以 UserServiceGrpc 為例 ,整個類包含這些核心方法 :
getQueryMethod : 這個對應 proto 文件中的 query 方法
// 注解中就標注了請求的路徑和請求體,返回體 // 沒看 grpc 源碼,但是猜測里面會通過這個注解構建請求 @io.grpc.stub.annotations.RpcMethod( fullMethodName = SERVICE_NAME + '/' + "query", // 這個就對應著 .proto 中配置的 message 對象 requestType = com.example.grpc.UserRequest.class, responseType = com.example.grpc.UserResponse.class, methodType = io.grpc.MethodDescriptor.MethodType.UNARY) // 這里返回的實際上是一個 MethodDescriptor 對象 public static io.grpc.MethodDescriptor getQueryMethod() { io.grpc.MethodDescriptor getQueryMethod; // Spring 注入的時候應該是沒有多線程風險的,這個可能是為了其他加載方式準備,上了一把鎖 // PS : 這里是一個經典的單例模式,不過代碼太長被我屏蔽了 synchronized (UserServiceGrpc.class) { // 省略具體的build邏輯,這里設置了很多內部參數,方法名等等 UserServiceGrpc.getQueryMethod = getQueryMethod = io.grpc.MethodDescriptor.<....>newBuilder() // ... 省略 .build(); } return getQueryMethod; }
MethodDescriptor 是 gRPC 中的專屬對象,用于表示一個gRPC方法的描述。 其中包含了方法名,輸入輸出,請求流和響應流等信息。
后續很多流程中都會通過該對象進行請求Client的創建,和RPC方法的注冊。
除了核心方法,其他比較主要的就是 stub 對象了。stub 對象用于向服務端發起 RPC 調用。
使用 gRPC 時,客戶端通過創建一個與服務端相同的 stub 對象來發起遠程調用,封裝了底層的網絡通信細節。
UserServiceGrpc 中有一個 newStub 方法,同時對應的還有 newBlockingStub 和 newFutureStub 。這些對象用于創建阻塞,異步回調的請求類型。
// 對應的class對象里面方法大同小異 public static final class UserServiceStub extends io.grpc.stub.AbstractAsyncStub<UserServiceStub> { // 簡單的構造器,這里傳入了一個 channel ,表示與服務端通信的通道 private UserServiceStub( io.grpc.Channel channel, io.grpc.CallOptions callOptions) { super(channel, callOptions); } // 調用 new 完成 build protected UserServiceStub build // 發起具體的 query 請求 public void query(com.example.grpc.UserRequest request, io.grpc.stub.StreamObserver<com.example.grpc.UserResponse> responseObserver)
這里倒沒太多東西,主要是 DTO 和 DTOOrBuilder 。
DTO 類 (HelloRequest)
這個類比我們想的要大的多,一般我們認為 DTO 里面主要是 Getter / Setter 這些方法 ,但是 proto 生成的 DTO 要復雜得多
// 容易讓人迷惑的方法 :
- getUnknownFields : 獲取消息中的未知字段 (解析器未知的字段)
- internalGetFieldAccessorTable : 獲取特定protobuf消息類型的字段訪問器表格
- isInitialized : 用于判斷一個對象是否已經被完全初始化的方法 (避免字段未被初始化完全)
- getSerializedSize : 用于計算當前消息的序列化后的大小 , 用于預留緩沖空間
- parseFrom : 用于將二進制數據解析成 Protobuf 消息對象
- parseFrom(byte[] data):從字節數組解析 Protobuf 消息對象
- parseFrom(byte[] data, int off, int len):從字節數組的指定位置和長度解析 Protobuf 消息對象
- parseFrom(InputStream input):從輸入流解析 Protobuf 消息對象
- parseFrom(CodedInputStream input):從 CodedInputStream 對象解析 Protobuf 消息對象
- newBuilderForType : 創建當前消息類型的 Builder 對象,用于構建該類型的消息
- toBuilder :用于返回一個可以修改消息的構建器對象 , 配合 newBuilder 一起使用
- parser : 接收一個字節數組或者一個輸入流作為參數,并返回一個對應的消息對象
DTOOrBuilder (HelloRequestOrBuilder)
在不需要修改消息屬性的場景下,提供一種更輕量級的消息訪問方式
public interface UserRequestOrBuilder extends // @@protoc_insertion_point(interface_extends:com.example.grpc.UserRequest) com.google.protobuf.MessageOrBuilder { /** * <code>string name = 1;</code> */ java.lang.String getName(); /** * <code>string name = 1;</code> */ com.google.protobuf.ByteString getNameBytes(); }
UserServiceOuterClass
OuterClass 是 proto 文件中定義的一個特殊類,用于包含所有其他消息和服務定義,可以作為訪問對應類的入口點。
example.OuterClass.Person person = example.OuterClass.Person.newBuilder() .setName("Alice") .setId(123) .build();
感謝各位的閱讀,以上就是“gRPC之proto及Maven插件怎么使用”的內容了,經過本文的學習后,相信大家對gRPC之proto及Maven插件怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。