中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

gRPC之proto及Maven插件怎么使用

發布時間:2023-04-19 16:49:46 來源:億速云 閱讀:145 作者:iii 欄目:開發技術

這篇文章主要講解了“gRPC之proto及Maven插件怎么使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“gRPC之proto及Maven插件怎么使用”吧!

    一. 前言

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

    二. proto 的概念和使用

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

    2.1 具體的執行流程

    • 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 文件

    gRPC之proto及Maven插件怎么使用

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

    使用文件

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

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

    三. 生成Java文件的核心類

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

    3.1 grpc 類

    以 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 對象了。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)

    3.2 DTO 和 Build 類

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

    DTO 類 (HelloRequest)

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

    gRPC之proto及Maven插件怎么使用

    // 容易讓人迷惑的方法 :
    - 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插件怎么使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    名山县| 漯河市| 那坡县| 长武县| 峡江县| 花垣县| 栾川县| 杭锦后旗| 轮台县| 太康县| 会同县| 偏关县| 台中县| 洛隆县| 周宁县| 隆子县| 微山县| 忻城县| 贵阳市| 耿马| 东丰县| 诸暨市| 栖霞市| 邹平县| 独山县| 康定县| 深泽县| 多伦县| 新疆| 宁化县| 桐庐县| 开原市| 滨海县| 屯门区| 江孜县| 靖西县| 福鼎市| 三原县| 巫山县| 正镶白旗| 贵港市|