日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
使用gRPC、Ballerina和Go構(gòu)建有效的微服務(wù)

關(guān)鍵要點(diǎn)

  • 根據(jù)交互和溝通方式,我們可以將微服務(wù)分為兩類:面向外部的微服務(wù)和內(nèi)部微服務(wù)。
  • RESTful API 是面向外部的微服務(wù)事實(shí)上的通信技術(shù)(REST 的普遍性和豐富的支持生態(tài)系統(tǒng)在其持續(xù)成功中發(fā)揮著至關(guān)重要的作用)。
  • gRPC 是遠(yuǎn)程過程調(diào)用 (RPC) API 范式的一個相對較新的實(shí)現(xiàn)。它可以在內(nèi)部微服務(wù)之間的所有同步通信中發(fā)揮主要作用
  • 在這里,我們通過使用真實(shí)世界的微服務(wù)用例來檢查關(guān)鍵 gRPC 概念、它們的用法以及將 gRPC 作為服務(wù)間通信的好處。
  • 許多主要的編程語言都支持 gRPC。我們將討論使用 Ballerinalang 和 Golang 作為編程語言的示例實(shí)現(xiàn)。

在現(xiàn)代微服務(wù)架構(gòu)中,我們可以根據(jù)微服務(wù)的交互和通信將微服務(wù)分為兩大類。第一組微服務(wù)充當(dāng)面向外部的微服務(wù),直接暴露給消費(fèi)者。它們主要是基于 HTTP 的 API,使用為外部開發(fā)人員優(yōu)化的常規(guī)基于文本的消息傳遞有效負(fù)載(JSON、XML 等),并使用表示狀態(tài)傳輸 (REST) 作為事實(shí)上的通信技術(shù)。

創(chuàng)新互聯(lián)憑借專業(yè)的設(shè)計(jì)團(tuán)隊(duì)扎實(shí)的技術(shù)支持、優(yōu)質(zhì)高效的服務(wù)意識和豐厚的資源優(yōu)勢,提供專業(yè)的網(wǎng)站策劃、做網(wǎng)站、成都做網(wǎng)站、網(wǎng)站優(yōu)化、軟件開發(fā)、網(wǎng)站改版等服務(wù),在成都十余年的網(wǎng)站建設(shè)設(shè)計(jì)經(jīng)驗(yàn),為成都上千中小型企業(yè)策劃設(shè)計(jì)了網(wǎng)站。

REST 無處不在且豐富的生態(tài)系統(tǒng)在這些面向外部的微服務(wù)的成功中發(fā)揮著至關(guān)重要的作用。OpenAPI為描述、生成、使用和可視化這些 REST API 提供了定義明確的規(guī)范。API 管理系統(tǒng)可以很好地與這些 API 配合使用,并提供安全性、速率限制、緩存和貨幣化以及業(yè)務(wù)需求。GraphQL 可以替代基于 HTTP 的 REST API,但它超出了本文的范圍。

另一組微服務(wù)是內(nèi)部的,不與外部系統(tǒng)或外部開發(fā)人員通信。這些微服務(wù)相互交互以完成一組給定的任務(wù)。內(nèi)部微服務(wù)使用同步或異步通信。在許多情況下,我們可以看到通過 HTTP 使用 REST API 作為同步模式,但這并不是最好的技術(shù)。在本文中,我們將仔細(xì)研究如何利用二進(jìn)制協(xié)議(例如 gRPC),它可以成為服務(wù)間通信的優(yōu)化通信協(xié)議

什么是 gRPC?

gRPC 是一種用于服務(wù)間通信的相對較新的遠(yuǎn)程過程調(diào)用 (RPC) API 范例。與所有其他 RPC 一樣,它允許直接調(diào)用不同機(jī)器上的服務(wù)器應(yīng)用程序上的方法,就好像它是本地對象一樣。與Thrift 和Avro等其他二進(jìn)制協(xié)議相同,gRPC 使用接口描述語言 (IDL) 來定義服務(wù)契約。gRPC 使用最新的網(wǎng)絡(luò)傳輸協(xié)議 HTTP/2 作為默認(rèn)傳輸協(xié)議,與基于 HTTP/1.1 的 REST 相比,這使得 gRPC 快速且健壯。

您可以使用 Protocol Buffers定義 gRPC 服務(wù)契約, 其中每個服務(wù)定義指定具有預(yù)期輸入和輸出消息的方法的數(shù)量以及參數(shù)和返回類型的數(shù)據(jù)結(jié)構(gòu)。使用主要編程語言提供的工具,可以使用定義服務(wù)合同的相同協(xié)議緩沖區(qū)文件生成服務(wù)器端框架和客戶端代碼(存根)。

gRPC 的實(shí)用微服務(wù)用例

圖 1:在線零售店微服務(wù)架構(gòu)的一部分

微服務(wù)架構(gòu)的主要好處之一是通過使用最合適的編程語言來構(gòu)建不同的服務(wù),而不是用一種語言構(gòu)建所有東西。圖 1 展示了在線零售店微服務(wù)架構(gòu)的一部分,其中在Ballerina (本文其余部分稱為 Ballerina)和Golang中實(shí)現(xiàn)了四個微服務(wù) ,以提供在線零售店的一些功能。由于許多主流編程語言都支持 gRPC,所以當(dāng)我們定義服務(wù)契約時(shí),可以使用非常適合的編程語言來實(shí)現(xiàn)。

讓我們?yōu)槊總€服務(wù)定義服務(wù)契約。

syntax="proto3";
package retail_shop;
service OrderService {
rpc UpdateOrder(Item) returns (Order);
}
message Item {
string itemNumber = 1;
int32 quantity = 2;
}
message Order {
string itemNumber = 1;
int32 totalQuantity = 2;
float subTotal = 3;

清單 1:Order 微服務(wù)的服務(wù)契約 ( order.proto )

Order 微服務(wù)將獲取購物項(xiàng)目和數(shù)量并返回小計(jì)。這里我使用 Ballerina gRPC 工具分別生成 gRPC 服務(wù)樣板代碼和存根/客戶端。

$ ballerina grpc --mode service --input proto/order.proto --output gen_code

這將生成 OrderService 服務(wù)器樣板代碼。

import ballerina/grpc;
listener grpc:Listener ep = new (9090);
service OrderService on ep {
resource function UpdateOrder(grpc:Caller caller, Item value) {
// Implementation goes here.

// You should return an Order
}
}
public type Order record {|
string itemNumber = "";
int totalQuantity = 0;
float subTotal = 0.0;
|};
public type Item record {|
string itemNumber = "";
int quantity = 0;

|};

清單 2:生成的樣板代碼的代碼片段 ( OrderService_sample_service.bal )

gRPC 服務(wù)完美地映射到 Ballerina 的 service 類型,gRPC rpc 映射到 Ballerina 的類型, resource function gRPC 消息映射到 Ballerina 的record 類型。

我為 Order 微服務(wù)創(chuàng)建了一個單獨(dú)的 Ballerina 項(xiàng)目,并使用生成的 OrderService 樣板代碼來實(shí)現(xiàn) gRPC 一元服務(wù)。

一元阻塞

OrderService 在 Cart 微服務(wù)中被調(diào)用。我們可以使用以下 Ballerina 命令來生成客戶端存根 和客戶端代碼。

$ ballerina grpc --mode client --input proto/order.proto --output gen_code

生成的客戶端存根具有阻塞和非阻塞遠(yuǎn)程方法。此示例代碼演示了 gRPC 一元服務(wù)如何與 gRPC 阻塞客戶端交互。

public remote function UpdateOrder(Item req, grpc:Headers? headers = ()) returns ([Order, grpc:Headers]|grpc:Error) {     
var payload = check self.grpcClient->blockingExecute("retail_shop.OrderService/UpdateOrder", req, headers);
grpc:Headers resHeaders = new;
anydata result = ();
[result, resHeaders] = payload;
return [result, resHeaders];
}
};

清單 3: 為阻塞模式生成的遠(yuǎn)程對象代碼片段

Ballerina 的遠(yuǎn)程方法抽象是一個非常適合的 gRPC 客戶端存根,您可以看到 UpdateOrder 調(diào)用代碼 非常干凈整潔。

Checkout 微服務(wù)通過匯總從 Cart 微服務(wù)收到的所有臨時(shí)訂單來發(fā)出最終賬單。在這種情況下,我們會將所有臨時(shí)訂單作為 stream Order 消息發(fā)送。

syntax="proto3";
package retail_shop;
service CheckoutService {
rpc Checkout(stream Order) returns (FinalBill) {}
}
message Order {
string itemNumber = 1;
int32 totalQuantity = 2;
float subTotal = 3;
}
message FinalBill {
float total = 1;
}

清單 4:Checkout 微服務(wù)的服務(wù)合同 ( checkout.proto )

您可以使用該 ballerina grpc 命令為 checkout.proto 生成樣板代碼 。

$ ballerina grpc --mode service --input proto/checkout.proto --output gen_code

gRPC 客戶端流式傳輸

Cart 微服務(wù)(客戶端)流式消息作為流對象參數(shù)提供,可以使用循環(huán)進(jìn)行迭代,處理客戶端發(fā)送的每條消息。請參閱以下示例實(shí)現(xiàn):

service CheckoutService on ep {
resource function Checkout(grpc:Caller caller, stream clientStream) {
float totalBill = 0;
//Iterating through streamed messages here
error? e = clientStream.forEach(function(Order order) {
totalBill += order.subTotal;
});
//Once the client completes stream, a grpc:EOS error is returned to indicate it
if (e is grpc:EOS) {
FinalBill finalBill = {
total:totalBill
};
//Sending the total bill to the client
grpc:Error? result = caller->send(finalBill);
if (result is grpc:Error) {
log:printError("Error occurred when sending the Finalbill: " +
result.message() + " - " + result.detail()["message"]);
} else {
log:printInfo ("Sending Final Bill Total: " +
finalBill.total.toString());
}
result = caller->complete();
if (result is grpc:Error) {
log:printError("Error occurred when closing the connection: " +
result.message() +" - " + result.detail()["message"]);
}
}
//If the client sends an error instead it can be handled here
else if (e is grpc:Error) {
log:printError("An unexpected error occured: " + e.message() + " - " +
e.detail()["message"]);
}
}
}

清單 5:( CheckoutService_sample_service.bal )的Service 示例實(shí)現(xiàn)的代碼片段 CheckoutService

客戶端流完成后,將返回 grpc:EOS 錯誤,該錯誤可用于確定何時(shí)使用調(diào)用者對象向客戶端發(fā)送最終響應(yīng)消息(總計(jì))。

CheckoutService的示例客戶端代碼 和客戶端存根 可以使用以下命令生成:

$ ballerina grpc --mode client --input proto/checkout.proto --output gen_code

讓我們看一下 Cart 微服務(wù)的實(shí)現(xiàn)。Cart 微服務(wù)有兩個 REST API — 一個用于將商品添加到購物車,另一個用于進(jìn)行最終結(jié)賬。將商品添加到購物車時(shí),它會通過對 Order 微服務(wù)進(jìn)行 gRPC 調(diào)用并將其存儲在內(nèi)存中,從而獲得帶有每個商品小計(jì)的臨時(shí)訂單。調(diào)用 Checkout 微服務(wù)會將所有存儲在內(nèi)存中的臨時(shí)訂單作為 gRPC 流發(fā)送到 Checkout 微服務(wù),并返回要支付的總金額。Ballerina 使用內(nèi)置的 Stream 類型和客戶端對象抽象來實(shí)現(xiàn) gRPC 客戶端流。請參見圖 2,它說明了 Ballerina 的客戶端流式傳輸是如何工作的。

圖 2:Ballerina gRPC 客戶端流式傳輸

CheckoutService 客戶端流的完整實(shí)現(xiàn)可以在 Cart 微服務(wù)結(jié)賬資源功能中找到。最后,在結(jié)賬過程中,對 Golang 實(shí)現(xiàn)的 Stock 微服務(wù)進(jìn)行 gRPC 調(diào)用,并通過扣除已售商品來更新庫存。

grpc-網(wǎng)關(guān)

syntax="proto3";
package retail_shop;
option go_package = "../stock;gen";
import "google/api/annotations.proto";
service StockService {
rpc UpdateStock(UpdateStockRequest) returns (Stock) {
option (google.api.http) = {
// Route to this method from POST requests to /api/v1/stock
put: "/api/v1/stock"
body: "*"
};
}
}
message UpdateStockRequest {
string itemNumber = 1;
int32 quantity = 2;
}
message Stock {
string itemNumber = 1;
int32 quantity = 2;

清單 6:Stock 微服務(wù) ( stock.proto )的服務(wù)合同

在這種情況下,將通過使用 REST API 調(diào)用作為面向外部的 API 來調(diào)用相同的 UpdateStock 服務(wù),并通過使用 gRPC 調(diào)用作為服務(wù)間調(diào)用來調(diào)用。grpc-gateway 是 protoc 的插件,它讀取 gRPC 服務(wù)定義并生成一個反向代理服務(wù)器,將 RESTful JSON API 轉(zhuǎn)換為 gRPC。

圖 3:grpc 網(wǎng)關(guān)

grpc-gateway 可幫助您同時(shí)提供 gRPC 和 REST 風(fēng)格的 API。

以下命令生成Golang gRPC 存根:

protoc -I/usr/local/include -I. \
-I$GOROOT/src \
-I$GOROOT/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=plugins=grpc:. \
stock.proto

以下命令生成Golang grpc-gateway 代碼:

protoc -I/usr/local/include -I. \
-I$GOROOT/src \
-I$GOROOT/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--grpc-gateway_out=logtostderr=true:. \
stock.proto

以下命令生成stock.swagger.json:

protoc -I/usr/local/include -I. \
-I$GOROOT/src \
-I$GOROOT/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
-I$GOROOT/src \
--swagger_out=logtostderr=true:../stock/gen/. \
./stock.proto

樣品運(yùn)行

克隆microservices-with-grpc git repo 并按照 README.md 說明進(jìn)行操作。

結(jié)論

gRPC 相對較新,但其快速發(fā)展的生態(tài)系統(tǒng)和社區(qū)肯定會對微服務(wù)開發(fā)產(chǎn)生影響。由于 gRPC 是一個開放標(biāo)準(zhǔn),所有主流編程語言都支持它,因此非常適合在多語言微服務(wù)環(huán)境中工作。作為一般實(shí)踐,我們可以使用 gRPC 進(jìn)行內(nèi)部微服務(wù)之間的所有同步通信,也可以使用 grpc-gateway 等新興技術(shù)將其公開為 REST 風(fēng)格的 API。除了我們在本文中討論的內(nèi)容之外,諸如 Deadlines、 Cancellation、 Channels和 xDS 支持等 gRPC 功能 將為開發(fā)人員構(gòu)建有效的微服務(wù)提供強(qiáng)大的功能和靈活性。


標(biāo)題名稱:使用gRPC、Ballerina和Go構(gòu)建有效的微服務(wù)
當(dāng)前URL:http://m.5511xx.com/article/dpgspcp.html