設定 gRPC 服務

如要建立 gRPC 服務 (無論是否使用 Cloud Endpoints),您必須在一個或多個 proto 檔案中指定介面定義,這些檔案是具有 .proto 副檔名的文字檔。您要先在 proto 檔案中定義 API 介面,包括資料結構、方法、方法參數以及傳回類型。接著,透過特定語言的通訊協定緩衝區編譯器 protoc,編譯 proto 檔案。詳情請參閱「什麼是 gRPC?」和「gRPC 概念」。

如要將 gRPC 服務交由 Endpoints 代管,則除了已編譯的 proto 檔案外,您還必須在一或多個 YAML 檔案中指定「服務設定」。服務設定是一種規格,可讓您定義 gRPC 服務的行為,包括驗證、配額等。

服務設定總覽

您可以在 YAML 檔案的頂端指定有關服務的基本資訊,例如名稱和標題。此外,您還能在 YAML 檔案的子區段設定服務的其他層面,例如:

例如:

type: google.api.Service
config_version: 3
name: calendar.googleapis.com
title: Google Calendar API
apis:
- name: google.calendar.v3.Calendar
authentication:
  providers:
  - id: google_calendar_auth
    jwks_uri: https://www.googleapis.com/oauth2/v1/certs
    issuer: https://securetoken.google.com
  rules:
  - selector: "*"
    requirements:
      provider_id: google_calendar_auth
backend:
  rules:
    - selector: "*"
      address: grpcs://my-service-98sdf8sd0-uc.a.run.app

一般來說,每個子區段都會對應到 .proto 訊息,您可以在其中設定服務的各個層面。例如:

  • authentication:指定驗證呼叫端的方式。
  • backend:控制遠端後端路由。
  • http:定義對應規則,將 RPC 方法對應到一或多個 HTTP REST API 方法。
  • usage:可讓您選擇性地啟用和停用 API 金鑰驗證。

服務設定的正式結構定義由 .proto 訊息 google.api.Service 定義。

基本設定

下方的 Bookstore 範例包含了基本介面定義檔案及服務設定檔,也用於 gRPC 教學課程中。

Bookstore 介面定義 bookstore.proto

syntax = "proto3";

package endpoints.examples.bookstore;

option java_multiple_files = true;
option java_outer_classname = "BookstoreProto";
option java_package = "com.google.endpoints.examples.bookstore";

import "google/protobuf/empty.proto";

service Bookstore {
  rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {}
  rpc CreateShelf(CreateShelfRequest) returns (Shelf) {}
  rpc GetShelf(GetShelfRequest) returns (Shelf) {}
  rpc DeleteShelf(DeleteShelfRequest) returns (google.protobuf.Empty) {}
  rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {}
  rpc CreateBook(CreateBookRequest) returns (Book) {}
  rpc GetBook(GetBookRequest) returns (Book) {}
  rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {}
}

message Shelf {
  int64 id = 1;
  string theme = 2;
}

message Book {
  int64 id = 1;
  string author = 2;
  string title = 3;
}

Bookstore 服務設定 api_config.yaml

type: google.api.Service
config_version: 3

name: bookstore.endpoints.MY_PROJECT_ID.cloud.goog

title: Bookstore gRPC API
apis:
- name: endpoints.examples.bookstore.Bookstore

上述程式碼範例是最簡單的服務設定,因為該範例:

  • 定義名稱為 bookstore.endpoints.MY_PROJECT_ID.cloud.goog 的服務,其中 MY_PROJECT_ID 代表您的 Google Cloud 專案 ID。
  • 指定服務公開 bookstore.proto 檔案中定義的 API endpoints.examples.bookstore.Bookstore
  • 在部署設定之後,提供描述性標題,以顯示在 Google Cloud 控制台的「Endpoints」 >「Services」(服務) 頁面上。如需詳細註解,請參考每個檔案的完整 GitHub 版本。

規則和選取器

在某些情況下,您可能需要能夠將設定與服務的個別元素建立關聯。例如,強制對特定方法執行驗證,但不對其他方法執行驗證。如要在服務設定中設定這項功能,您可以使用服務設定的部分部分,例如 authenticationhttp,指定規則選取器。選取器可以識別與規則相關聯的設定適用的服務元素 (例如方法名稱)。

選取器是以逗號分隔的清單,列出服務中定義的完整名稱:方法、訊息、欄位、列舉或列舉值。名稱的最後一個片段可以是萬用字元 *,可與任何後置字串相符。萬用字元只能在名稱結尾處使用,且只能代表整段名稱。例如:foo.* 是可以接受的用法,但 foo.b*foo.*.bar 就不正確。如要為所有適用的元素設定預設值,請直接指定 *

範例 1 (影響整個服務):

usage:
  rules:
  # Allow unregistered calls for all methods.
  - selector: "*"
    allow_unregistered_calls: true

範例 2 (影響單一方法):

usage:
  rules: # IMPORTANT: ONLY LAST MATCHING RULE IS APPLIED
  # Disable API key validation on just the ListShelves method
  # while requiring an API key for the rest of the API.
  - selector: "*"
    allow_unregistered_calls: false
  - selector: "endpoints.examples.bookstore.BookStore.ListShelves"
    allow_unregistered_calls: true

上述範例說明如何針對所有方法 (ListShelves 方法除外) 要求 API 金鑰驗證。

系統會按照順序評估規則,並套用宣告順序中最後一個相符的規則。

使用多個 YAML 檔案

您可能會發現使用多個 YAML 檔案來設定同一服務的不同功能相當實用。因為使用多個 YAML 檔案讓您可以更輕鬆地重複使用檔案,並針對不同的環境修改檔案。舉例來說,在 Bookstore 範例中,基本設定會在 api_config.yaml 檔案中指定,而 HTTP 規則則會在 api_config_http.yaml 檔案中指定。如此一來,只有在您要將 Bookstore 的 JSON/HTTP 轉碼為 gRPC 時,才要部署 HTTP 規則。

如果您為服務設定使用多個 YAML 檔案,則在設定部署完成時,每個檔案都會轉換為 google.api.Service proto 訊息,所有訊息隨後會透過 proto 合併語意進行合併。也就是說,後者執行個體中的所有單一純量欄位將會取代前者執行個體中的同等欄位。因此,如果您在兩個檔案中為同一規則提供了不同的單一值,則當系統部署設定時會使用您在第二個檔案中指定的值。單一嵌入訊息將會合併,而重複的欄位則會串聯。

如同規則,合併也容易受到順序影響。如果有兩個服務設定,第二個服務設定會覆寫第一個設定。

註解 (只限 HTTP 規則)

設定 HTTP 選項的方式除了使用 YAML 檔案之外,您還能透過選項機制,直接在 proto 檔案中設定選項。API 註解是在 annotations.proto 中定義。

如果您希望設定選項在通訊協定緩衝區介面定義的所有用法上保持不變,請使用註釋。例如,如果 API 具有單一實作,或者所有的實作都需要相同的 HTTP 介面,則可以在 proto 檔案中註解 HTTP 設定。

如果 proto 檔案和服務設定 YAML 檔案中同時提供了設定選項,則服務設定會覆寫註解。

proto 檔案中的註解範例:

rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {
    option (google.api.http) = { get: "/v1/shelves" };
}


# The preceding annotation is equivalent to the following service configuration:

http:
  rules:
  - selector: endpoints.examples.bookstore.BookStore.ListShelves
    get: '/v1/shelves'

詳情請參閱將 HTTP/JSON 轉碼為 gRPC

設定驗證

您可以使用 gcloud endpoints services deploy 建立服務的執行階段設定,部署服務設定和編譯的 proto 檔案gcloud endpoints services deploy 指令能夠驗證服務設定,並標記任何錯誤和警告。

警告分為一般及 Linter 警告。Linter 警告會使用 <group>-<rule> 形式的 ID,其中 <group> 代表設定群組,<rule> 則代表特定 Linter 規則。舉例來說,群組下方是 versioning,規則則是 http-version-prefix

WARNING: bookstore.proto:51:3: (lint) versioning-http-version-prefix: method
'endpoints.examples.bookstore.BookStore.ListShelves' has a different version
prefix in HTTP path ('v2') than api version 'v1'.

您可以在 API 元素的說明文件中加入指令,以略過 Linter 警告。此外,您也可以將指令新增到 proto 檔案或服務設定 YAML 檔案中。請參考下列範例,其中略過上述警告:

service Bookstore {
  // Returns an object.
  // (== suppress_warning versioning-http-version-prefix ==)
  rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {
      option (google.api.http) = { get: "/v1/shelves" };
  }
}

如要略過整個群組的警告,您可以使用萬用字元 (*),而不使用規則名稱。例如,versioning-* 會略過與 versioning 群組相關的所有警告。

附加到父項元素的略過指令也會套用到所有子項目。舉例來說,以下範例會在服務內的所有方法上抑制所有 versioning 群組警告:

// (== suppress_warning versioning-* ==)
service Bookstore {
  // Returns an object.
  rpc ListShelves(google.protobuf.Empty) returns (ListShelvesResponse) {
      option (google.api.http) = { get: "/v1/shelves" };
  }
}

如要全面略過警告,請將指令附加到服務設定的總覽說明文件:

type: google.api.Service
name: your_api.endpoints.<producer-project-id>.cloud.goog
title: Bookstore gRPC API
apis:
- name: endpoints.examples.bookstore.BookStore
documentation:
    overview: |
      A simple Bookstore gRPC API.
      (== suppress_warning documentation-presence ==)

請注意,說明文件中的指令 (例如 suppress_warning) 必須單獨成行,否則系統將無法識別。YAML 區塊文字標記 (例如 >) 會移除所有換行符號,因此如果您在上述範例中使用 overview: >,系統就無法執行略過動作。如要進一步瞭解 YAML 中的區塊文字,請參閱「縮排劃界」說明。

後續步驟