以 gRPC-Web 實作前端與後端的溝通

本文章同時發佈於:

文章為自己的經驗與夥伴整理的內容,設計沒有標準答案,如有可以改進的地方,請告訴我,我會盡我所能的修改,謝謝大家~

大家好,實作完微服務的溝通後,接下來要來實作前端與後端的 gRPC-Web 部分,整體的服務終於有點微服務的樣子了 XD

整體架構如下,除了外部的Web前端以外,還需要Envoy來轉換 HTTP1.1 至 HTTP2(詳細原因在DAY11)

實際運作

gRPC schemas:

以下流程可以與上方 schema 做對照,會比較清楚,

可以發現流程圖與昨天的相似,不過多了 Envoy 來轉發。

先 run 起來再說

先 run 起來可能會比較有感覺,請 clone Github-Example-Code,並將 Server run 起來,

$ cd DAY15
$ docker-compose up

打開localhost:8060

就可以看到 Web 端已經可以收到 Server-Stream 了!

Web 講解

const { QueryRequest, CreateRequest } = require("../proto/schema_pb.js");
const { DigimonPromiseClient } = require("../proto/schema_grpc_web_pb.js");

async function createDigimon(digimonPromiseClient, name) {
  let createRequest = new CreateRequest();
  createRequest.setName(name);
  const createResponse = await digimonPromiseClient.create(createRequest, {});
  return createResponse;
}

async function queryDigimonStream(digimonPromiseClient, digimonID) {
  let queryRequest = new QueryRequest();
  queryRequest.setId(digimonID);

  const queryStream = await digimonPromiseClient.queryStream(queryRequest, {});
  return queryStream;
}

(async () => {
  try {
    const digimonPromiseClient = new DigimonPromiseClient(
      "http://localhost:8080"
    );

    const createResponse = await createDigimon(digimonPromiseClient, "Agumon");
    const queryStream = await queryDigimonStream(
      digimonPromiseClient,
      createResponse.getId()
    );

    queryStream.on("data", function (response) {
      console.log(
        response.getId(),
        response.getName(),
        response.getStatus(),
        response.getLocation(),
        response.getWeather().toString()
      );
    });
    queryStream.on("status", function (status) {
      console.log(status.code);
      console.log(status.details);
      console.log(status.metadata);
    });
    queryStream.on("end", function (end) {
      // stream end signal
    });
  } catch (err) {
    console.error(err.code);
    console.error(err.message);
  }
})();

Web 的 Code 並不長,先以DigimonPromiseClient()建立 gRPC Client,之後就可以使用queryStream來獲得 stream 的物件。

stream 物件有一個 on function,可以以 callback 分別註冊:

  • data: 接收到 Server-Stream 的資料
  • status: 連線狀態
  • end: 連線結束的處理

謝謝你的閱讀~

comments powered by Disqus