欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

gRPC實(shí)踐之proto及Maven插件概念及使用詳解

 更新時間:2023年04月19日 09:36:48   作者:AntBlack  
這篇文章主要為大家介紹了gRPC實(shí)踐之proto及Maven插件概念及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一. 前言

文章合集 : ??http://shouce.jb51.net/java/jdk1.6/

Github : ?? github.com/black-ant

CASE 備份 : ?? gitee.com/antblack/ca…

這一塊在學(xué)習(xí)的初期沒專門去看,導(dǎo)致寫Demo的時候一度遇到了很多的困難。

protobuf 是 gRPC 中生成 API Service 的方式,在 Maven 編譯時就可以快速生成對應(yīng)的Class類。

二. proto 的概念和使用

以 Maven 為例,在 gRPC 中通常使用 protobuf-maven-plugin 插件,根據(jù)一個 .proto 文件生成對應(yīng)的 Java 代碼。 其本身是基于 Google 的 Protocol Buffers 工具鏈實(shí)現(xiàn)的。

2.1 具體的執(zhí)行流程

  • S1 : 創(chuàng)建一個 .proto 文件,按照規(guī)范要求定義元數(shù)據(jù)內(nèi)容
  • S2 : 通過 protobuf-maven-plugin 插件進(jìn)行 compile 操作
  • S3 : protobuf-maven-plugin 調(diào)用 protoc 命令行工具,生成對應(yīng)的 Java 代碼
  • S4 : 生成的 Java 代碼會被編譯,并打包成 Jar 包 , 最終生成可執(zhí)行文件給項(xiàng)目使用

.proto 文件格式

syntax = "proto3"; // 定義使用的語法版本,這里是proto3
package com.example.grpc; // 定義package,用于在其他文件中引用該文件定義的類型
// 定義配置項(xiàng) 
// - java_package :定義生成的Java類的包名
// - java_outer_classname  : 定義生成的Java類的類名
option java_multiple_files = true;
// 接口類
service UserService {
  rpc query (UserRequest) returns (UserResponse);
}
// 定義消息類型
message UserRequest {
  string name = 1; // 字段類型和名稱,以及字段標(biāo)識符,用于序列化和反序列化
}
// 這里的消息類型是返回值
message UserResponse {
  string name = 1;
  int32 age = 2;
  string address = 3;
  // 這里定義一個枚舉
  enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } 
  // 這里定義一個內(nèi)部對象
  repeated PhoneNumber phones = 4;
  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }
}

通常一個 proto 文件中會包含以下主要內(nèi)容

  • package: 包名,用于區(qū)分不同模塊的數(shù)據(jù)結(jié)構(gòu)定義。
  • message: 消息體,包含多個字段,每個字段都有一個名稱和類型。
  • enum: 枚舉類型,定義多個枚舉值。
  • service: 定義 RPC 服務(wù)接口,包含多個方法,每個方法都有一個請求消息和一個響應(yīng)消息。

生成一個 .class 文件

這里就可以看到,其實(shí)生成了很多文件,最重要的包括 :UserServiceGrpc ,HelloRequest 和 HelloResponse 這幾個。

使用文件

使用文件和平時使用 Class 是一致的,引入 Maven 依賴然后直接調(diào)用就行了

@Resource
UserServiceGrpc.UserServiceBlockingStub userService;
UserRequest userRequest = UserRequest.newBuilder().setName("test").build();
UserResponse user = userService.query(userRequest);

三. 生成Java文件的核心類

上面看了插件的使用,后面就來詳細(xì)看看它生成的幾個 Class 到底包含了什么 :

3.1 grpc 類

以 UserServiceGrpc 為例 ,整個類包含這些核心方法 :

getQueryMethod : 這個對應(yīng) proto 文件中的 query 方法

// 注解中就標(biāo)注了請求的路徑和請求體,返回體
// 沒看 grpc 源碼,但是猜測里面會通過這個注解構(gòu)建請求
@io.grpc.stub.annotations.RpcMethod(
    fullMethodName = SERVICE_NAME + '/' + "query",
    // 這個就對應(yīng)著 .proto 中配置的 message 對象
    requestType = com.example.grpc.UserRequest.class,
    responseType = com.example.grpc.UserResponse.class,
    methodType = io.grpc.MethodDescriptor.MethodType.UNARY)
// 這里返回的實(shí)際上是一個 MethodDescriptor 對象
public static io.grpc.MethodDescriptor getQueryMethod() {
  io.grpc.MethodDescriptor getQueryMethod;
  // Spring 注入的時候應(yīng)該是沒有多線程風(fēng)險的,這個可能是為了其他加載方式準(zhǔn)備,上了一把鎖
  // PS : 這里是一個經(jīng)典的單例模式,不過代碼太長被我屏蔽了
  synchronized (UserServiceGrpc.class) {
      // 省略具體的build邏輯,這里設(shè)置了很多內(nèi)部參數(shù),方法名等等
      UserServiceGrpc.getQueryMethod = getQueryMethod =
            io.grpc.MethodDescriptor.<....>newBuilder()
            // ... 省略
            .build();
      }
  return getQueryMethod;
}

MethodDescriptor 是 gRPC 中的專屬對象,用于表示一個gRPC方法的描述。 其中包含了方法名,輸入輸出,請求流和響應(yīng)流等信息。

后續(xù)很多流程中都會通過該對象進(jìn)行請求Client的創(chuàng)建,和RPC方法的注冊。

其他 stub 對象

除了核心方法,其他比較主要的就是 stub 對象了。stub 對象用于向服務(wù)端發(fā)起 RPC 調(diào)用。

使用 gRPC 時,客戶端通過創(chuàng)建一個與服務(wù)端相同的 stub 對象來發(fā)起遠(yuǎn)程調(diào)用,封裝了底層的網(wǎng)絡(luò)通信細(xì)節(jié)。

UserServiceGrpc 中有一個 newStub 方法,同時對應(yīng)的還有 newBlockingStub 和 newFutureStub 。這些對象用于創(chuàng)建阻塞,異步回調(diào)的請求類型。

//  對應(yīng)的class對象里面方法大同小異
public static final class UserServiceStub extends io.grpc.stub.AbstractAsyncStub<UserServiceStub> {
  // 簡單的構(gòu)造器,這里傳入了一個 channel ,表示與服務(wù)端通信的通道  
  private UserServiceStub(
      io.grpc.Channel channel, io.grpc.CallOptions callOptions) {
    super(channel, callOptions);
  }
  // 調(diào)用 new 完成 build
  protected UserServiceStub build
  // 發(fā)起具體的 query 請求
  public void query(com.example.grpc.UserRequest request,
      io.grpc.stub.StreamObserver<com.example.grpc.UserResponse> responseObserver)

3.2 DTO 和 Build 類

這里倒沒太多東西,主要是 DTO 和 DTOOrBuilder 。

DTO 類 (HelloRequest)

這個類比我們想的要大的多,一般我們認(rèn)為 DTO 里面主要是 Getter / Setter 這些方法 ,但是 proto 生成的 DTO 要復(fù)雜得多

// 容易讓人迷惑的方法 :
- getUnknownFields : 獲取消息中的未知字段 (解析器未知的字段)
- internalGetFieldAccessorTable : 獲取特定protobuf消息類型的字段訪問器表格
- isInitialized : 用于判斷一個對象是否已經(jīng)被完全初始化的方法 (避免字段未被初始化完全)
- getSerializedSize : 用于計(jì)算當(dāng)前消息的序列化后的大小 , 用于預(yù)留緩沖空間
- parseFrom : 用于將二進(jìn)制數(shù)據(jù)解析成 Protobuf 消息對象
    - parseFrom(byte[] data):從字節(jié)數(shù)組解析 Protobuf 消息對象
    - parseFrom(byte[] data, int off, int len):從字節(jié)數(shù)組的指定位置和長度解析 Protobuf 消息對象
    - parseFrom(InputStream input):從輸入流解析 Protobuf 消息對象
    - parseFrom(CodedInputStream input):從 CodedInputStream 對象解析 Protobuf 消息對象
- newBuilderForType : 創(chuàng)建當(dāng)前消息類型的 Builder 對象,用于構(gòu)建該類型的消息
- toBuilder :用于返回一個可以修改消息的構(gòu)建器對象 , 配合 newBuilder 一起使用
- parser : 接收一個字節(jié)數(shù)組或者一個輸入流作為參數(shù),并返回一個對應(yīng)的消息對象

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 文件中定義的一個特殊類,用于包含所有其他消息和服務(wù)定義,可以作為訪問對應(yīng)類的入口點(diǎn)。

example.OuterClass.Person person = example.OuterClass.Person.newBuilder() .setName("Alice") .setId(123) .build();

總結(jié)

了解 proto 插件是使用 gRPC 得基礎(chǔ)。一開始我是一直沒搞懂這個 Request 類是怎么出來了,一直引入失敗。

后續(xù)就開始一片片得深入 gRPC 的使用。

以上就是gRPC實(shí)踐之proto及Maven插件概念及使用詳解的詳細(xì)內(nèi)容,更多關(guān)于gRPC proto Maven插件的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評論