google grpc 簡(jiǎn)介及官網(wǎng)的快速入門

GRPC是基于protocol buffers3.0協(xié)議的.

本文將向您介紹gRPC和protocol buffers。 gRPC可以使用protocol buffers作為其IDL(接口描述)和其底層消息交換格式。 如果您是gRPC和protocol buffers的新手,請(qǐng)繼續(xù)閱讀! 如果您只是想首先看到gRPC,請(qǐng)參閱我們的快速入門

指南

在gRPC中,客戶端應(yīng)用程序可以直接在不同機(jī)器上的服務(wù)器應(yīng)用程序上調(diào)用方法,就像它是本地對(duì)象一樣,使您更容易創(chuàng)建分布式應(yīng)用程序和服務(wù)。 與許多RPC系統(tǒng)一樣,gRPC基于定義服務(wù)的思想,指定可以使用其參數(shù)和返回類型遠(yuǎn)程調(diào)用的方法。 在服務(wù)器端,服務(wù)器實(shí)現(xiàn)此接口并運(yùn)行g(shù)RPC服務(wù)器來(lái)處理客戶端調(diào)用。 在客戶端,客戶端有一個(gè)stub(簡(jiǎn)稱為一些語(yǔ)言的客戶端),提供與服務(wù)器相同的方法。

gRPC客戶端和服務(wù)器可以在各種環(huán)境中運(yùn)行和交互,從Google內(nèi)部的服務(wù)器到您自己的應(yīng)用,并且可以使用任何gRPC支持的語(yǔ)言編寫。 所以,例如,您可以輕松地創(chuàng)建一個(gè)Java開發(fā)的服務(wù),使用Go,Python或Ruby中的客戶端。In addition, the latest Google APIs will have gRPC versions of their interfaces, letting you easily build Google functionality(功能) into your applications.

Protocol buffer 版本

雖然Protocol buffer已經(jīng)可用于開源用戶一段時(shí)間,但我們的示例使用了proto3的Protocol buffer的新風(fēng)格,它具有略微簡(jiǎn)化的語(yǔ)法,一些有用的新功能,并支持更多的語(yǔ)言。這是目前可用于Java,C ++,Python,Objective-C,C#,lite-runtime(Android Java),Ruby和JavaScript的Protocol buffer Github repo,以及來(lái)自golang/protobuf Github的Go語(yǔ)言自動(dòng)生成,還有更多的語(yǔ)言在開發(fā)中。您可以在proto3語(yǔ)言指南和每種支持的語(yǔ)言的參考文檔(如果可用)查看更多內(nèi)容,并且可以在發(fā)行說(shuō)明中查看與當(dāng)前默認(rèn)版本的主要區(qū)別。更多的proto3文檔即將推出。

一般來(lái)說(shuō),雖然您可以使用proto2(當(dāng)前的默認(rèn)Protocol buffer版本),但我們建議您使用proto3協(xié)議為基礎(chǔ)的gRPC,因?yàn)樗梢宰屇褂萌盗械膅RPC支持的語(yǔ)言,并避免與proto2客戶端與proto3服務(wù)器的兼容性問(wèn)題,反之亦然。

注:因?yàn)閜roto2只提供了消息定義,而沒有提供服務(wù)接口的定義。

服務(wù)定義

gRPC Concepts

像許多RPC系統(tǒng)一樣,gRPC基于定義服務(wù)的思想,指定可以使用其參數(shù)和返回類型遠(yuǎn)程調(diào)用的方法。 默認(rèn)情況下,gRPC使用 protocol buffers作為接口定義語(yǔ)言(IDL),用于描述有效負(fù)載消息的服務(wù)接口和結(jié)構(gòu)。

service HelloService {
  rpc SayHello (HelloRequest) returns (HelloResponse);
}

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  string reply = 1;
}

pf3.0出現(xiàn)了接口定義。

gRPC 定義了四種類型的服務(wù)接口:

  • 一元RPC,客戶端向服務(wù)器發(fā)送請(qǐng)求并獲得響應(yīng),就像正常的函數(shù)調(diào)用一樣。
rpc SayHello(HelloRequest) returns (HelloResponse){
}
  • 服務(wù)器流RPC,客戶端發(fā)送一個(gè)對(duì)象服務(wù)器端返回一個(gè)Stream(流式消息)
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){
}
  • 客戶端流式RPC,客戶端發(fā)送一個(gè)Stream(流式消息)服務(wù)端返回一個(gè)對(duì)象。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) {
}
  • 雙向流RPC
    其中雙方使用讀寫流發(fā)送消息序列。 兩個(gè)流獨(dú)立運(yùn)行,所以客戶端和服務(wù)器可以按照他們喜歡的順序進(jìn)行讀取和寫入:例如,服務(wù)器可能在寫入響應(yīng)之前等待接收所有客戶端消息,或者可以交替地讀取消息然后寫入消息, 或讀取和寫入的其他組合。 每個(gè)流中消息的順序被保留。
    類似于WebSocket(長(zhǎng)連接),客戶端可以向服務(wù)端請(qǐng)求消息,服務(wù)器端也可以向客戶端請(qǐng)求消息)。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){
}

使用api

從.proto文件中的服務(wù)定義開始,gRPC提供了生成客戶機(jī)和服務(wù)器端代碼的protocol buffer編譯器插件。 gRPC用戶通常在客戶端調(diào)用這些API,并在服務(wù)器端實(shí)現(xiàn)相應(yīng)的API。

  • 在服務(wù)器端,服務(wù)器實(shí)現(xiàn)服務(wù)聲明的方法,并運(yùn)行g(shù)RPC服務(wù)器來(lái)處理客戶端調(diào)用。 gRPC基礎(chǔ)設(shè)施解碼傳入請(qǐng)求,執(zhí)行服務(wù)方法和編碼服務(wù)響應(yīng)。
  • 在客戶端,客戶端具有稱為stub的本地方法定義(對(duì)于一些語(yǔ)言,首選項(xiàng)是客戶端),其實(shí)現(xiàn)與服務(wù)相同的方法。 然后,客戶端可以直接在本地對(duì)象上調(diào)用這些方法,將調(diào)用的參數(shù)包含在適當(dāng)?shù)膒rotocol buffer消息類型中 - gRPC在將請(qǐng)求發(fā)送到服務(wù)器并返回服務(wù)器的protocol buffer響應(yīng)之后。

同步和異步

同步RPC調(diào)用阻塞,直到響應(yīng)從服務(wù)器返回是與RPC渴望的過(guò)程調(diào)用最接近(差不多這個(gè)意思)。 另一方面,網(wǎng)絡(luò)本質(zhì)上是異步的,并且在許多情況下,能夠在不阻塞當(dāng)前線程的情況下啟動(dòng)RPC是有用的。

大多數(shù)語(yǔ)言中的gRPC編程表面都包含同步和異步語(yǔ)言。 您可以在每種語(yǔ)言的教程和參考文檔中找到更多內(nèi)容(完整的參考文檔即將推出)。

RPC生命周期

現(xiàn)在讓我們仔細(xì)看看當(dāng)gRPC客戶端調(diào)用gRPC服務(wù)器方法時(shí)會(huì)發(fā)生什么。 我們不會(huì)查看實(shí)現(xiàn)細(xì)節(jié),可以在特定語(yǔ)言頁(yè)面中了解更多信息。

一元RPC

客戶端向服務(wù)器發(fā)送單個(gè)請(qǐng)求并獲得單個(gè)響應(yīng),就像正常的函數(shù)調(diào)用一樣。

  • 一旦客戶端調(diào)用stub/客戶端對(duì)象上的方法,就會(huì)通知服務(wù)器RPC客戶端的元數(shù)據(jù)用于此調(diào)用,方法名稱和指定的期限(如果配置的話)

  • 然后,服務(wù)器可以立即發(fā)回自己的初始元數(shù)據(jù)(必須在任何響應(yīng)之前發(fā)送),或等待客戶端的請(qǐng)求消息 - 由應(yīng)用程序決定誰(shuí)先執(zhí)行。

  • 一旦服務(wù)器有客戶端的請(qǐng)求消息,它就做任何創(chuàng)建和填充其響應(yīng)所需的工作。 然后將響應(yīng)(如果成功)返回給客戶端以及狀態(tài)詳細(xì)信息(狀態(tài)代碼和可選狀態(tài)消息)以及可選的尾隨元數(shù)據(jù)。

  • 狀態(tài)是ok的,客戶端得到響應(yīng),客戶端完成所有的調(diào)用。

服務(wù)器流RPC

服務(wù)器流RPC與我們的簡(jiǎn)單示例類似,除了服務(wù)器在獲取客戶端請(qǐng)求消息之后發(fā)送回響應(yīng)流。 在發(fā)回所有響應(yīng)后,服務(wù)器端的狀態(tài)信息(狀態(tài)碼和可選狀態(tài)消息)和可選的尾隨元數(shù)據(jù)將被發(fā)送回完成。 客戶端完成直到接收到服務(wù)器的所有響應(yīng)。

客戶端流式RPC

客戶端流RPC也類似于我們的簡(jiǎn)單示例,除了客戶端將請(qǐng)求流發(fā)送到服務(wù)器,而不是單個(gè)請(qǐng)求。 服務(wù)器返回單個(gè)響應(yīng),通常但不一定在收到所有客戶端的請(qǐng)求后返回響應(yīng),以及其狀態(tài)詳細(xì)信息和可選的尾隨元數(shù)據(jù)。

雙向流RPC

在雙向流RPC中,調(diào)用發(fā)起與客戶端調(diào)用方法然后服務(wù)器端接收客戶端的元數(shù)據(jù),方法名稱,和調(diào)用期限。 服務(wù)器也可以選擇發(fā)回其初始元數(shù)據(jù)或等待客戶端開始發(fā)送請(qǐng)求。
接下來(lái)發(fā)生的情況取決于應(yīng)用程序,因?yàn)榭蛻舳撕头?wù)器可以以任何順序讀取和寫入 - 流完全獨(dú)立運(yùn)行。 因此,例如,服務(wù)器可能會(huì)等到收到所有客戶端的消息后再寫入響應(yīng),否則服務(wù)器和客戶端可能會(huì)“ping-pong”:服務(wù)器獲取請(qǐng)求,然后發(fā)送回應(yīng),然后客戶端發(fā)送基于響應(yīng)的另一個(gè)請(qǐng)求等等。

截止日期和超時(shí)

gRPC允許客戶端指定在RPC服務(wù)調(diào)用終止之前愿意等待RPC完成的時(shí)間,否則顯示錯(cuò)誤DEADLINE_EXCEEDED。 在服務(wù)器端,服務(wù)器可以查詢特定的RPC是否超時(shí),還是剩下多少時(shí)間來(lái)完成RPC調(diào)用。
如何指定期限或超時(shí)時(shí)間因語(yǔ)言而異 - 例如,并非所有語(yǔ)言都有默認(rèn)的最后期限,某些語(yǔ)言API的工作時(shí)間是截止時(shí)間(固定時(shí)間點(diǎn)),而某些語(yǔ)言API的工作范圍是超時(shí) (一段時(shí)間內(nèi))。

RPC 終止

在gRPC中,客戶端和服務(wù)器都相對(duì)獨(dú)立和本地確定本地調(diào)用成功,并且其結(jié)論可能不匹配另一端。 這意味著,例如,您可以在服務(wù)器端成功完成一個(gè)RPC返回(“我已發(fā)送我的所有回復(fù)”),但在客戶端失敗(“我的截止日期之后回復(fù)”)。 服務(wù)器也可以在客戶端發(fā)送所有請(qǐng)求之前決定完成。

取消RPC調(diào)用

客戶端或服務(wù)器可以隨時(shí)取消RPC。取消立即被終止以便不再進(jìn)行任何工作。它不是一個(gè)“撤消”:在取消之前的修改不會(huì)被回滾。

元數(shù)據(jù)

元數(shù)據(jù)是關(guān)于鍵值對(duì)列表形式的特定RPC調(diào)用(例如認(rèn)證細(xì)節(jié))的信息,其中鍵是字符串,并且值通常是字符串(但可以是二進(jìn)制數(shù)據(jù))。 元數(shù)據(jù)對(duì)gRPC本身是不透明的 - 它允許客戶端提供與對(duì)服務(wù)器的調(diào)用相關(guān)聯(lián)的信息,反之亦然。
對(duì)元數(shù)據(jù)的訪問(wèn)取決于依賴的語(yǔ)言。

通道

gRPC通道提供與指定主機(jī)和端口上的gRPC服務(wù)器的連接,并在創(chuàng)建客戶端stub(或僅某些語(yǔ)言的“客戶端”)時(shí)使用。 客戶端可以指定通道參數(shù)來(lái)修改gRPC的默認(rèn)行為,例如打開和關(guān)閉消息壓縮。 通道有狀態(tài),包括連接和空閑。 > gRPC如何處理關(guān)閉頻道與語(yǔ)言有關(guān)。 某些語(yǔ)言也允許查詢通道狀態(tài)。

快速入門

下載example

?  # Clone the repository at the latest release to get the example code:
?  git clone -b v1.4.0 https://github.com/grpc/grpc-java
?  # Navigate to the Java examples:
?  cd grpc-java/examples

-b v1.4.0表示指定的是1.4.0這個(gè)版本,不指定版本默認(rèn)的是master版本。

運(yùn)行一個(gè)grpc的應(yīng)用

編譯服務(wù)器端和客戶端,這一步需要很長(zhǎng)時(shí)間,

? ./gradlew installDist

運(yùn)行服務(wù)器:

?  ./build/install/examples/bin/hello-world-server
六月 25, 2017 6:58:58 下午 io.grpc.examples.helloworld.HelloWorldServer start
信息: Server started, listening on 50051

運(yùn)行客戶端:

?./build/install/examples/bin/hello-world-client
六月 25, 2017 6:59:08 下午 io.grpc.examples.helloworld.HelloWorldClient greet
信息: Will try to greet world ...
六月 25, 2017 6:59:09 下午 io.grpc.examples.helloworld.HelloWorldClient greet
信息: Greeting: Hello world

修改gRPC服務(wù)

進(jìn)入src/main/proto/目錄,修改helloworld.proto文件,增加一個(gè)SayHelloAgain方法,

syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {}
  // Sends another greeting
  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings
message HelloReply {
  string message = 1;
}

helloworld.proto文件中增加了一個(gè)SayHelloAgain方法,入?yún)⑹?code>HelloRequest,返回參數(shù)是HelloReply

修改服務(wù)器代碼,增加SayHelloAgain方法的實(shí)現(xiàn)

重新編譯.prto文件,將會(huì)重新生成客戶端,服務(wù)端代碼,也重新生成序列化,我們?cè)诜?wù)端去增加剛才helloworld.proto文件中增加了一個(gè)SayHelloAgain方法的實(shí)現(xiàn):

src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java文件增加sayHelloAgain方法實(shí)現(xiàn):

private class GreeterImpl extends GreeterGrpc.GreeterImplBase {

  @Override
  public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }

  @Override
  public void sayHelloAgain(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello again " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }
}
...

修改客戶端

修改src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java文件,增加blockingStub.sayHelloAgain的調(diào)用。

public void greet(String name) {
  logger.info("Will try to greet " + name + " ...");
  HelloRequest request = HelloRequest.newBuilder().setName(name).build();
  HelloReply response;
  try {
    response = blockingStub.sayHello(request);
  } catch (StatusRuntimeException e) {
    logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
    return;
  }
  logger.info("Greeting: " + response.getMessage());
  try {
    response = blockingStub.sayHelloAgain(request);
  } catch (StatusRuntimeException e) {
    logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus());
    return;
  }
  logger.info("Greeting: " + response.getMessage());
}

編譯文件,重新執(zhí)行

? ./gradlew installDist

運(yùn)行服務(wù)器:

? ./build/install/examples/bin/hello-world-server

運(yùn)行客戶端:

? ./build/install/examples/bin/hello-world-client

客戶端打印:

?  ./build/install/examples/bin/hello-world-client
六月 25, 2017 7:43:29 下午 io.grpc.examples.helloworld.HelloWorldClient greet
信息: Will try to greet world ...
六月 25, 2017 7:43:29 下午 io.grpc.examples.helloworld.HelloWorldClient greet
信息: Greeting: Hello world
六月 25, 2017 7:43:30 下午 io.grpc.examples.helloworld.HelloWorldClient greet
信息: Greeting: Hello again world

總結(jié)

運(yùn)行一個(gè)簡(jiǎn)單的gRPC列子,首先你需要學(xué)會(huì)下面三個(gè)步驟:

  • 使用一個(gè).proto文件定義服務(wù)(定義了消息體和服務(wù)接口)
  • 使用protocol buffer編譯器去編譯.proto文件并且去生成客戶端和服務(wù)端代碼(不能使用protoc指令,因?yàn)間RPC是使用的基于protocol buffer3.0的,maven和gradle都提供了對(duì)應(yīng)的編譯器,而protoc 指令是protocol buffer2.0的指令)。
  • 編寫自己的客戶端和服務(wù)端(服務(wù)器端額外編寫接口實(shí)現(xiàn))。

發(fā)現(xiàn)所有的RPC框架的基礎(chǔ)流程都是如此。

參考資料

官網(wǎng)地址
官網(wǎng)java快速指南
github地址
protocol buffer3.0協(xié)議

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 134,991評(píng)論 19 139
  • 轉(zhuǎn)自:http://blog.csdn.net/kesonyk/article/details/50924489 ...
    晴天哥_王志閱讀 24,932評(píng)論 2 38
  • 主要基于官網(wǎng)介紹的文檔總結(jié)而來(lái)。 需要先了解 protocol buffers 為什么使用gRPC 通過(guò)gPRC,...
    kingeasternsun閱讀 3,669評(píng)論 1 4
  • 最近項(xiàng)目需要用到 gRPC,網(wǎng)上gRPC 的資料較少,翻譯了官網(wǎng)的 gRPC guide 文檔,以供組內(nèi)學(xué)習(xí),部分...
    不智魚閱讀 6,153評(píng)論 0 13
  • 荒野上的火還在燃著 你的瞳孔里焦灼難耐 遠(yuǎn)方的星辰流不出喧騰的瀑布 夢(mèng)做的過(guò)了頭 便會(huì)引來(lái)欲望的信子 未來(lái)的城池 ...
    禾靜一閱讀 366評(píng)論 2 9