gRPC官方文檔(概覽)

文章來自gRPC 官方文檔中文版php

概覽

開始

歡迎進入 gRPC 的開發文檔,gRPC 一開始由 google 開發,是一款語言中立、平臺中立、開源的遠程過程調用(RPC)系統。 本文檔經過快速概述和一個簡單的 Hello World 例子來向您介紹 gRPC 。你能夠在本站發現更詳細的教程和參考文檔——文檔將會愈來愈豐富。html

快速開始

爲了直觀地着手運行 gRPC,能夠從你所選擇的語言對應的快速開始入手,裏面包含建立這個列子的安裝指導、快速上手指南等更多內容。java

你能夠從這裏找到 gRPC 的源碼庫。咱們大多數例子都在源碼庫 examples 目錄下。node

gRPC 是什麼?

在 gRPC 裏_客戶端_應用能夠像調用本地對象同樣直接調用另外一臺不一樣的機器上_服務端_應用的方法,使得您可以更容易地建立分佈式應用和服務。與許多 RPC 系統相似,gRPC 也是基於如下理念:定義一個_服務_,指定其可以被遠程調用的方法(包含參數和返回類型)。在服務端實現這個接口,並運行一個 gRPC 服務器來處理客戶端調用。在客戶端擁有一個_存根_可以像服務端同樣的方法。python

gRPC 客戶端和服務端能夠在多種環境中運行和交互 - 從 google 內部的服務器到你本身的筆記本,而且能夠用任何 gRPC 支持的語言來編寫。因此,你能夠很容易地用 Java 建立一個 gRPC 服務端,用 Go、Python、Ruby 來建立客戶端。此外,Google 最新 API 將有 gRPC 版本的接口,使你很容易地將 Google 的功能集成到你的應用裏。android

使用 protocol buffers

gRPC 默認使用 protocol buffers,這是 Google 開源的一套成熟的結構數據序列化機制(固然也可使用其餘數據格式如 JSON)。正如你將在下方例子裏所看到的,你用 proto files 建立 gRPC 服務,用 protocol buffers 消息類型來定義方法參數和返回類型。你能夠在 Protocol Buffers 文檔找到更多關於 Protocol Buffers 的資料。git

Protocol buffers 版本

儘管 protocol buffers 對於開源用戶來講已經存在了一段時間,例子內使用的卻一種名叫 proto3 的新風格的 protocol buffers,它擁有輕量簡化的語法、一些有用的新功能,而且支持更多新語言。當前針對 Java 和 C++ 發佈了 beta 版本,針對 JavaNano(即 Android Java)發佈 alpha 版本,在protocol buffers Github 源碼庫裏有 Ruby 支持, 在golang/protobuf Github 源碼庫裏還有針對 Go 語言的生成器, 對更多語言的支持正在開發中。 你能夠在 proto3 語言指南裏找到更多內容, 在與當前默認版本的發佈說明比較,看到二者的主要不一樣點。更多關於 proto3 的文檔很快就會出現。雖然你_能夠_使用 proto2 (當前默認的 protocol buffers 版本), 咱們一般建議你在 gRPC 裏使用 proto3,由於這樣你可使用 gRPC 支持所有範圍的的語言,而且能避免 proto2 客戶端與 proto3 服務端交互時出現的兼容性問題,反之亦然。github

你好 gRPC!

如今你已經對 gRPC 有所瞭解,瞭解其工做機制最簡單的方法是看一個簡單的例子。 Hello World 將帶領你建立一個簡單的客戶端——服務端應用,向你展現:golang

  • 經過一個 protocol buffers 模式,定義一個簡單的帶有 Hello World 方法的 RPC 服務。
  • 用你最喜歡的語言(若是可用的話)來建立一個實現了這個接口的服務端。
  • 用你最喜歡的(或者其餘你願意的)語言來訪問你的服務端。

這個例子完整的代碼在咱們 GitHub 源碼庫的 examples 目錄下。 咱們使用 Git 版本系統來進行源碼管理,可是除了如何安裝和運行一些 Git 命令外,你不必知道其餘關於 Git 的任何事情。 須要注意的是,並非全部 gRPC 支持的語言均可以編寫咱們例子的服務端代碼,好比 PHP 和 Objective-C 僅支持建立客戶端。 比起針對於特定語言的複雜教程,這更像是一個介紹性的例子。你能夠在本站找到更有深度的教程,gRPC 支持的語言的參考文檔很快就會所有開放。objective-c

準備

本節解釋瞭如何在你本機上準備好例子代碼的運行環境。若是你只是想讀一下例子,你能夠直接到下一步。

安裝 Git

你能夠從http://git-scm.com/download下載和安裝 Git。安裝好 Git 後,你應該能訪問 git 命令行工具。你須要的主要命令以下:

  • git clone ... : 從遠程代碼庫克隆一份到本機。
  • git checkout ... : 檢出一個特殊分支或一個標籤版本的代碼來改進。

安裝 gRPC

針對你選擇的語言構建和安裝 gRPC 插件和相關工具,能夠參照快速開始。 Java gRPC 除了 JDK 外不須要其餘工具。

得到源碼

  • Java

Java 例子代碼在 GitHub 源碼庫裏。你能夠運行以下命令克隆源碼到本地:

git clone https://github.com/grpc/grpc-java.git

切換當前目錄到grpc-java/examples

cd grpc-java/examples

  • C++

例子代碼在 GitHub 源碼庫的 examples 目錄。你能夠運行以下命令克隆源碼到本地:

$ git clone https://github.com/grpc/grpc.git

切換當前目錄到 examples/cpp/helloworld

$ cd examples/cpp/helloworld/

  • Python

例子代碼在 GitHub 源碼庫的 examples 目錄。你能夠運行以下命令克隆源碼到本地:

$ git clone https://github.com/grpc/grpc.git

切換當前目錄到 examples/python/helloworld

$ cd examples/python/helloworld/

  • Go

獲取例子:

$ go get -u github.com/grpc/grpc-go/examples/helloworld/greeter_client
$ go get -u github.com/grpc/grpc-go/examples/helloworld/greeter_server

切換當前目錄到 examples/helloworld

  • Ruby

例子代碼在 GitHub 源碼庫的 examples 目錄。你能夠運行以下命令克隆源碼到本地:

$ git clone https://github.com/grpc/grpc.git

切換當前目錄到 examples/ruby ,而後使用 bundler 安裝例子的包依賴:

$ gem install bundler # if you don't already have bundler available
$ bundle install
  • Node.js

例子代碼在 GitHub 源碼庫的 examples 目錄。你能夠運行以下命令克隆源碼到本地:

$ git clone https://github.com/grpc/grpc.git

切換當前目錄到 examples/node , 接着安裝包依賴:

$ cd examples/node
$ npm install
  • C#

例子代碼在 GitHub 源碼庫的 examples 目錄。你能夠運行以下命令克隆源碼到本地:

$ git clone https://github.com/grpc/grpc。git

從 Visual Studio (或 Linux 上的 Monodevelop ) 打開 Greeter.sln。能夠從 C# Quickstart 找到平臺特定的設置步驟。

  • Objective-C

例子代碼在 GitHub 源碼庫的 examples 目錄。你能夠運行以下命令克隆源碼到本地:

$ git clone https://github.com/grpc/grpc.git
$ cd grpc
$ git submodule update --init

切換當前目錄到 examples/objective-c/helloworld

  • PHP

例子代碼在 GitHub 源碼庫的 examples 目錄。你能夠運行以下命令克隆源碼到本地:

$ git clone https://github.com/grpc/grpc.git

切換當前目錄到 examples/php 。 雖然咱們大多數例子使用同一個 .proto 文件,但 PHP 的例子有本身的 helloworld.proto 文件,這是由於它依賴 proto2 語法。 PHP暫時沒有針對 proto3 的支持。

定義服務

建立咱們例子的第一步是定義一個_服務_:一個 RPC 服務經過參數和返回類型來指定能夠遠程調用的方法。就像你在 概覽 裏所看到的, gRPC 經過 protocol buffers 來實現。 咱們使用 protocol buffers 接口定義語言來定義服務方法,用 protocol buffer 來定義參數和返回類型。客戶端和服務端均使用服務定義生成的接口代碼。 這裏有咱們服務定義的例子,在 helloworld.proto 裏用 protocol buffers IDL 定義的。Greeter 服務有一個方法 SayHello ,可讓服務端從遠程客戶端接收一個包含用戶名的 HelloRequest 消息後,在一個 HelloReply 裏發送回一個 Greeter。這是你能夠在 gRPC 裏指定的最簡單的 RPC - 你能夠在教程裏找到針對你選擇的語言更多類型的例子。

syntax = "proto3";

option java_package = "io.grpc.examples";

package helloworld;

// The greeter service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (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;
}

生成 gRPC 代碼

一旦定義好服務,咱們可使用 protocol buffer 編譯器 protoc 來生成建立應用所需的特定客戶端和服務端的代碼 - 你能夠生成任意 gRPC 支持的語言的代碼,固然 PHP 和 Objective-C 僅支持建立客戶端代碼。生成的代碼同時包括客戶端的存根和服務端要實現的抽象接口,均包含 Greeter 所定義的方法。

(假如你沒有在系統裏安裝 gRPC 插件和 protoc ,而且僅僅是要看一下這個例子,你能夠跳過這一步,直接到下一步來查看生成的代碼。)

  • Java

    這個例子的構建系統也是 Java gRPC 自己構建的一部分 —— 爲了簡單起見,咱們推薦使用咱們事先生成的例子代碼。你能夠參考 README 來看一下如何從你本身的 .proto 文件生成代碼。

    這個例子事先生成的代碼在 src/generated/main下。 如下類包含全部咱們須要建立這個例子全部的代碼:

    • HelloRequest.java, HelloResponse.java和其餘文件包含全部 protocol buffer 用來填充、序列化和提取HelloRequestHelloReply 消息類型的代碼。
    • GreeterGrpc.java, 包含 (還有其餘有用的代碼):

      Greeter 服務端須要實現的接口

public static interface Greeter {
        public void sayHello(Helloworld.HelloRequest request,
        StreamObserver<Helloworld.HelloReply> responseObserver);
        }

客戶端用來與 Greeter 服務端進行對話的 存根 類。就像你所看到的,異步存根也實現了 Greeter 接口。

public static class GreeterStub extends AbstractStub<GreeterStub>
    implements Greeter {
      ...
    }
  • C++

    生成客戶端和服務端接口,運行:

$ make helloworld.grpc.pb.cc helloworld.pb.cc

這從內部調用 protocol buffer 編譯器:

$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto

生成:

helloworld.pb.h 聲明瞭用於填充、序列化、提取 HelloRequestHelloResponse 消息類型的類,而且還有它的實現 helloworld.pb.cc

helloworld.grpc.pb.h,聲明瞭咱們生成的服務類和它的實現 helloworld.grpc.pb.cc

  • Python

能夠用以下命令生成客戶端和服務端:

$ ./run_codegen.sh

這內部調用 protocol buffer 編譯器:

$ protoc -I ../../protos --python_out=. --grpc_out=. --plugin=protoc-gen-grpc=`which grpc_python_plugin` ../../protos/helloworld.proto

這生成了 helloworld_pb2.py ,包含咱們生成的客戶端和服務端類,此外還有用於填充、序列化、提取 HelloRequestHelloResponse 消息類型的類。

  • Go

爲了生成客戶端和服務端接口,運行 protocol buffer 編譯器:

protoc -I ../protos ../protos/helloworld.proto --go_out=plugins=grpc:helloworld

這生成了 helloworld.pb.go ,包含了咱們生成的客戶端和服務端類,此外還有用於填充、序列化、提取 HelloRequestHelloResponse 消息類型的類。

  • Ruby

爲了生成客戶端和服務端接口,運行 protocol buffer 編譯器:

protoc -I ../protos --ruby_out=lib --grpc_out=lib --plugin=protoc-gen-grpc=`which grpc_ruby_plugin` ../protos/helloworld.proto

lib 目錄下生成了以下文件:

  • lib/helloworld.rb 定義了一個 Helloworld 模塊, 這個模塊提供了用於填充、序列化、提取請求、應答消息類型的全部 protocol buffer 代碼。

  • lib/helloworld_services.rb 用生成的客戶端和服務端代碼繼承了 Helloworld 模塊。

  • Node.js

Node.js庫從運行時加載的 .proto 文件動態生成服務描述和客戶端存根的定義,因此使用此語言時不必生成任何特殊代碼。而是在例子客戶端和服務端裏,咱們 require gRPC 庫,而後用它的 load() 方法:

var grpc = require('grpc');
var hello_proto = grpc.load(PROTO_PATH).helloworld;
  • C#

  • 爲了生成 Windows 上的代碼,咱們使用來自 Google.Protobuf NuGet 包裏的 protoc.exe 和來自 Grpc.Tools NuGet 包裏的 Grpc.Tools ,這兩個文件都在 tools 目錄下。 通常你須要本身把 Grpc.Tools 包添加到解決方案,但在這個教程裏,這一步已經爲你作好了。你應該在 examples/csharp/helloworld 下執行如下命令:

> packages\Google.Protobuf.3.0.0-alpha4\tools\protoc.exe -I../../protos --csharp_out Greeter --grpc_out Greeter --plugin=protoc-gen-grpc=packages\Grpc.Tools.0.7.0\tools\grpc_csharp_plugin.exe ../../protos/helloworld.proto
  • 在 Linux 或 OS X ,咱們依賴經過 Linuxbrew 或者 Homebrew 安裝的 protocgrpc_csharp_plugin 。請在 route_guide 目錄下運行這個命令:
$ protoc -I../../protos --csharp_out Greeter --grpc_out Greeter --plugin=protoc-gen-grpc=`which grpc_csharp_plugin` ../../protos/helloworld.proto

根據你的 OS 運行合適的命令,在 Greeter 目錄從新生成以下文件:

  • Greeter/Helloworld.cs 定義了命名空間 Helloworld 它包含了全部用來填充、序列化、提取請求和應答消息類型的 protocol buffer 代碼。
  • Greeter/HelloworldGrpc.cs,提供了存根類和服務類,包括:

    • 一個 Greeter.IGreeter 接口,能夠在定義 RootGuide 服務實現的時候來繼承它。
    • 一個 Greeter.GreeterClient 類,可用來訪問遠程的 RouteGuide 實例。
  • Objective-c

爲了簡單,咱們提供了一個 Podspec 文件,用來使用適當的插件、輸入、輸出運行 protoc ,並描述如何編譯生成的代碼。你僅僅須要在 examples/objective-c/route_guide 下運行:

$ pod install

而後你能夠打開由 Cocoapods 建立的 XCode 工做空間,看一下生成的代碼。運行命令生成:

- `Helloworld.pbobjc.h`, 定義生成的消息類的頭文件。
- `Helloworld.pbobjc.m`,包含消息類的實現。
- `Helloworld.pbrpc.h`,定義生成的服務類的頭文件。
- `Helloworld.pbrpc.m`,包含服務類的實現。
  • PHP

    gRPC PHP 使用 protoc-gen-php 工具來從 .proto 文件生成代碼。你能夠在 PHP 快速開始裏找到如何安裝它。爲了生成 Greeter 服務的代碼,運行:

    protoc-gen-php -i . -o . ./helloworld.proto

    生成 helloworld.php ,包含:

    • 全部用來填充、序列化、提取請求和應答消息類型的 protocol buffer 代碼.
    • GreeterClient 類,可讓客戶端調用在 Greeter 服務裏的方法。

寫一個服務器

如今讓咱們寫點代碼!首先咱們將建立一個服務應用來實現服務(你會記起來,咱們能夠是使用除了Objective-C and PHP 外的其餘全部語言來實現)。在本節,咱們不打算對如何建立一個服務端進行更深刻地探討 —— 更詳細的信息能夠在你選擇語言對應的教程裏找到。

服務實現

  • Java

    GreeterImpl.java 準確地實現了 Greeter 服務所須要的行爲。 正如你所見,GreeterImpl 類經過實現 sayHello 方法,實現了從 IDL 生成的GreeterGrpc.Greeter 接口 。

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

    sayHello 有兩個參數:

    • HelloRequest,請求。
    • StreamObserver<HelloReply>: 應答觀察者,一個特殊的接口,服務器用應答來調用它。

      爲了返回給客戶端應答而且完成調用:

    1. 用咱們的激動人心的消息構建並填充一個在咱們接口定義的 HelloReply 應答對象。
    2. HelloReply 返回給客戶端,而後代表咱們已經完成了對 RPC 的處理。
  • C++

    greeter_server.cc 實現了 Greeter 服務所須要的行爲。 正如你所見,GreeterServiceImpl 類經過實現 sayHello 方法,實現了從 proto 服務定義生成的Greeter::Service 接口 。

    class GreeterServiceImpl final : public Greeter::Service {
    Status SayHello(ServerContext* context, const HelloRequest* request,
                    HelloReply* reply) override {
      std::string prefix("Hello ");
      reply->set_message(prefix + request->name());
      return Status::OK;
    }
    };

    在此咱們實現同步版本的 Greeter,它提供了默認的 gRPC 服務行爲(這裏也有一個異步的接口,Greeter::AsyncService)。

    sayHello 有三個參數:

    • ServerContext: RPC上下文對象。
    • HelloRequest : 請求。
    • HelloReply :應答。

      爲了返回給客戶端應答而且完成調用:

    1. 用咱們的激動人心的消息構建並填充一個在咱們接口定義的 HelloReply 應答對象。
    2. Status::OK 返回給客戶端,代表咱們已經完成了對 RPC 的處理。
  • Python

    greeter_server.py 實現了 Greeter 服務所須要的行爲。 正如你所見,Greeter 類經過實現 sayHello 方法,實現了從 proto 服務定義生成的helloworld_pb2.BetaGreeterServicer 接口:

    class Greeter(helloworld_pb2.BetaGreeterServicer):
    
    def SayHello(self, request, context):
      return helloworld_pb2.HelloReply(message='Hello, %s!' % request.name)

    爲了返回給客戶端應答而且完成調用:

    1. 用咱們的激動人心的消息構建並填充一個在咱們接口定義的 HelloReply 應答對象。
    2. HelloReply 返回給客戶端。
  • Go

    greeter_server/main.go 實現了 Greeter 服務所須要的行爲。 正如你所見,服務器有一個 server 結構。它經過實現 sayHello 方法,實現了從 proto 服務定義生成的GreeterServer 接口:

    // server is used to implement helloworld.GreeterServer.
    type server struct{}
    // SayHello implements helloworld.GreeterServer
    func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
      return &pb.HelloReply{Message: "Hello " + in.Name}, nil
    }

    爲了返回給客戶端應答而且完成調用:

    1. 用咱們的激動人心的消息構建並填充一個在咱們接口定義的 HelloReply 應答對象。
    2. HelloReply 返回給客戶端。
  • Ruby

    greeter_server.rb 實現了 Greeter 服務所須要的行爲。 服務器有一個 GreeterServer 類,它經過實現 sayHello 方法,實現了從 proto 服務定義生成的GreeterServer 接口:

    class GreeterServer < Helloworld::Greeter::Service
    # say_hello implements the SayHello rpc method.
    def say_hello(hello_req, _unused_call)
      Helloworld::HelloReply.new(message: "Hello #{hello_req.name}")
    end

    爲了返回給客戶端應答而且完成調用:咱們用激動人心的消息構建並填充一個在咱們接口定義的 HelloReply 應答對象,而後返回它。

  • Node.js

    greeter_server.js 實現了 Greeter 服務所須要的行爲。 服務器經過實現 SayHello 方法,實現了服務定義:

    function sayHello(call, callback) {
    callback(null, {message: 'Hello ' + call.request.name});
    }

    爲了返回給客戶端應答並完成調用,咱們填充了應答並將其傳遞給一個已提供了的回調,用 null 做爲第一個參數來表示沒有出現錯誤。

  • C#

    GreeterServer/Program.cs 實現了 Greeter 服務所須要的行爲。 服務器的 GreeterImpl類,經過實現 sayHello 方法,實現了生成的IGreeter 接口:

    class GreeterImpl : Greeter.IGreeter
    {
      public Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
      {
          return Task.FromResult(new HelloReply { Message = "Hello " + request.Name });
      }
    }

    爲了返回給客戶端應答並完成如下調用:

    1. 用咱們的激動人心的消息構建並填充一個在咱們接口定義的 HelloReply 應答對象。
    2. HelloReply 返回給客戶端。

服務端實現

須要提供一個 gRPC 服務的另外一個主要功能是讓這個服務實在在網絡上可用。

  • Java

    HelloWorldServer.java 提供瞭如下代碼做爲 Java 的例子。

    /* The port on which the server should run */
    private int port = 50051;
    private Server server;
    private void start() throws Exception {
    server = ServerBuilder.forPort(port)
        .addService(GreeterGrpc.bindService(new GreeterImpl()))
        .build()
        .start();
    logger.info("Server started, listening on " + port);
    Runtime.getRuntime().addShutdownHook(new Thread() {
      @Override
      public void run() {
        // Use stderr here since the logger may has been reset by its JVM shutdown hook.
        System.err.println("*** shutting down gRPC server since JVM is shutting down");
        HelloWorldServer.this.stop();
        System.err.println("*** server shut down");
      }
    });
    }
  • C++

    greeter_server.cc 提供瞭如下代碼做爲 C++ 的例子。

    void RunServer() {
    std::string server_address("0.0.0.0:50051");
    GreeterServiceImpl service;
    ServerBuilder builder;
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    builder.RegisterService(&service);
    std::unique_ptr<Server> server(builder.BuildAndStart());
    std::cout << "Server listening on " << server_address << std::endl;
    server->Wait();
    }
  • Python

    greeter_server.py 提供瞭如下代碼做爲 Python 的例子。

    server = helloworld_pb2.beta_create_Greeter_server(Greeter())
    server.add_insecure_port('[::]:50051')
    server.start()
    try:
      while True:
        time.sleep(_ONE_DAY_IN_SECONDS)
    except KeyboardInterrupt:
      server.stop()
  • Go

    greeter_server/main.go 提供瞭如下代碼做爲 Go 的例子。

    const (
      port = ":50051"
    )
    ...
    func main() {
      lis, err := net.Listen("tcp", port)
      if err != nil {
          log.Fatalf("failed to listen: %v", err)
      }
      s := grpc.NewServer()
      pb.RegisterGreeterServer(s, &server{})
      s.Serve(lis)
    }
  • Ruby

    greeter_server.rb 提供瞭如下代碼做爲 Ruby 的例子。

    def main
    s = GRPC::RpcServer.new
    s.add_http2_port('0.0.0.0:50051')
    s.handle(GreeterServer)
    s.run
    end
  • Node.js

    greeter_server.js 提供瞭如下代碼做爲 Ruby 的例子。

    function main() {
    var server = new Server({
      "helloworld.Greeter": {
        sayHello: sayHello
      }
    });
    server.bind('0.0.0.0:50051');
    server.listen();
    }
  • C#

    GreeterServer/Program.cs 提供瞭如下代碼做爲 C# 的例子。

    Server server = new Server
    {
      Services = { Greeter.BindService(new GreeterImpl()) },
      Ports = { new ServerPort("localhost", 50051, ServerCredentials.Insecure) }
    };
    server.Start();

在這裏咱們建立了合理的 gRPC 服務器,將咱們實現的 Greeter 服務綁定到一個端口。而後咱們啓動服務器:服務器如今已準備好從 Greeter 服務客戶端接收請求。咱們將在具體語言對應的文檔裏更深刻地瞭解這全部的工做是怎樣進行的。

寫一個客戶端

客戶端的 gRPC 很是簡單。在這一步,咱們將用生成的代碼寫一個簡單的客戶程序來訪問咱們在上一節裏建立的 Greeter 服務器。 一樣,咱們也不打算對如何實現一個客戶端程序深刻更多,咱們把這些內容放到教程裏。

鏈接服務

首先咱們看一下咱們如何鏈接 Greeter 服務器。咱們須要建立一個 gRPC 頻道,指定咱們要鏈接的主機名和服務器端口。而後咱們用這個頻道建立存根實例。

  • Java

    private final ManagedChannel channel;
    private final GreeterGrpc.GreeterBlockingStub blockingStub;
    public HelloWorldClient(String host, int port) {
    channel = ManagedChannelBuilder.forAddress(host, port)
        .usePlaintext(true)
        .build();
    blockingStub = GreeterGrpc.newBlockingStub(channel);
    }

    在這個例子裏,咱們建立了一個阻塞的存根。這意味着 RPC 調用要等待服務器應答,將會返回一個應答或拋出一個異常。 gRPC Java 還能夠有其餘種類的存根,能夠向服務器發出非阻塞的調用,這種狀況下應答是異步返回的。

  • C++

    int main(int argc, char** argv) {
    GreeterClient greeter(
        grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials(),
                            ChannelArguments()));
    ...
    }
    ...
    class GreeterClient {
    public:
    GreeterClient(std::shared_ptr<ChannelInterface> channel)
        : stub_(Greeter::NewStub(channel)) {}
    ...
    private:
    std::unique_ptr<Greeter::Stub> stub_;
    };
  • Python

    生成的 Python 代碼有一個根據頻道建立存根的幫助方法。

    channel = implementations.insecure_channel('localhost', 50051)
    stub = helloworld_pb2.beta_create_Greeter_stub(channel)
    ...
  • Go

    const (
      address     = "localhost:50051"
      defaultName = "world"
    )
    func main() {
      // Set up a connection to the server.
      conn, err := grpc.Dial(address)
      if err != nil {
          log.Fatalf("did not connect: %v", err)
      }
      defer conn.Close()
      c := pb.NewGreeterClient(conn)
    ...
    }

    在 gRPC Go 你是使用一個特殊的 Dial() 方法來建立頻道。

  • Ruby

    stub = Helloworld::Greeter::Stub.new('localhost:50051')

    在 Ruby 裏,咱們能夠在一個方法裏調用從 .proto 文件裏生成的存根類。

  • Node.js

    var client = new hello_proto.Greeter('localhost:50051');

    在 Node.js ,咱們能夠在一步調用 Greeter 存根構造器。

  • C#

    Channel channel = new Channel("127.0.0.1:50051", Credentials.Insecure);
    var client = Greeter.NewClient(channel);
    ...
  • Objective-C

    在 Objective-C 裏,咱們能夠用生成的 HLWGreeter 類指定的初始化方法完成,這個方法須要用NSString * 類型表示的服務器和端口做爲參數。

    #import <GRPCClient/GRPCCall+Tests.h>
    ...
    static NSString * const kHostAddress = @"localhost:50051";
    ...
    [GRPCCall useInsecureConnectionsForHost:kHostAddress];
    HLWGreeter *client = [[HLWGreeter alloc] initWithHost:kHostAddress];

    當用給定的 host:port 對通信的時候,注意對 useInsecureConnectionsForHost: 的調用,要通知 gRPC 庫使用明文 (而不是 TLS 加密的鏈接)。

  • PHP

    $client = new helloworld\GreeterClient(
        new Grpc\BaseStub('localhost:50051', []));

    在 PHP 裏,咱們可使用 GreeterClient 類的構造器一步完成。

調用 RPC

如今咱們能夠聯繫服務並得到一個 greeting :

  1. 咱們建立並填充一個 HelloRequest 發送給服務。
  2. 咱們用請求調用存根的 SayHello(),若是 RPC 成功,會獲得一個填充的 HelloReply ,從其中咱們能夠得到 greeting。
  • Java

    HelloRequest req = HelloRequest.newBuilder().setName(name).build();
    HelloReply reply = blockingStub.sayHello(req);

    你能夠在 HelloWorldClient.java 裏查看完整的客戶端代碼。

  • C++

    std::string SayHello(const std::string& user) {
      HelloRequest request;
      request.set_name(user);
      HelloReply reply;
      ClientContext context;
      Status status = stub_->SayHello(&context, request, &reply);
      if (status.ok()) {
        return reply.message();
      } else {
        return "Rpc failed";
      }
    }

    你能夠在 greeter_client.cc 裏查看完整的客戶端代碼。

  • Python

    response = stub.SayHello(helloworld_pb2.HelloRequest(name='you'), _TIMEOUT_SECONDS)
    print "Greeter client received: " + response.message

    你能夠在 greeter_client.py 裏查看完整的客戶端代碼。

  • Go

    r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name: name})
    if err != nil {
          log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.Message)

    你能夠在 greeter_client/main.go 裏查看完整的客戶端代碼。

  • Ruby

    message = stub.say_hello(Helloworld::HelloRequest.new(name: user)).message
    p "Greeting: #{message}"

    你能夠在 greeter_client.rb 裏查看完整的客戶端代碼。

  • Node.js

client.sayHello({name: user}, function(err, response) {
    console.log('Greeting:', response.message);
  });

你能夠在 /examples/node/greeter_client.js 裏查看完整的客戶端代碼。

  • C#

    var reply = client.SayHello(new HelloRequest { Name = user });
    Console.WriteLine("Greeting: " + reply.Message);

    你能夠在 GreeterClient/Program.cs 裏查看完整的客戶端代碼。

  • Objective-C

    HLWHelloRequest *request = [HLWHelloRequest message];
    request.name = @"Objective-C";
    [client sayHelloWithRequest:request handler:^(HLWHelloReply *response, NSError *error) {
    NSLog(@"%@", response.message);
    }];

    你能夠在 examples/objective-c/helloworld 裏查看完整的客戶端代碼。

  • PHP

$request = new helloworld\HelloRequest();
  $request->setName($name);
  list($reply, $status) = $client->SayHello($request)->wait();
  $message = $reply->getMessage();

你能夠在greeter_client.php 裏查看完整的客戶端代碼。

試一下!

你能夠嘗試用同一個語言在客戶端和服務端構建並運行例子。或者你能夠嘗試 gRPC 最有用的一個功能 - 不一樣的語言間的互操做性,即在不一樣的語言運行客戶端和服務端。每一個服務端和客戶端使用從同一過 proto 文件生成的接口代碼,則意味着任何 Greeter 客戶端能夠與任何 Greeter 服務端對話。

  • Java 首先運行服務端:

    你能夠從 examples 目錄構建並運行服務端。首先構建客戶端和服務端:

    $ ../gradlew -PskipCodegen=true installDist

而後運行服務端,服務端將監聽 50051 : $ ./build/install/grpc-examples/bin/hello-world-server

  • C++

    你能夠從 examples/cpp/helloworld 目錄下構建並運行服務端。首先構建客戶端和服務端:

    $ make

    而後運行服務端,服務端將監聽 50051 :

    $ ./greeter_server

  • Python 你能夠用以下命令到 examples/python/helloworld 下運行服務端:

    $ ./run_server.sh

  • Go

    你能夠用以下命令到 examples/helloworld 下運行服務端:

    $ greeter_server &

  • Ruby

    你能夠用以下命令到 examples/ruby 下運行服務端:

    $ bundle exec ./greeter_server.rb &

  • Node.js 你能夠用以下命令到 examples/node 下運行服務端:

    $ node ./greeter_server.js &

  • C# 構建解決方案,而後到 examples/csharp

> cd GreeterServer/bin/Debug
> GreeterServer.exe

一旦服務器在運行,在其餘的終端窗口運行客戶端並確認它收到一個消息。

  • Java

    你能夠在 examples 目錄下構建並運行客戶端。假如你尚未構建客戶端,可使用以下命令:

    $ ../gradlew -PskipCodegen=true installDist

而後運行客戶端: $ ./build/install/grpc-examples/bin/hello-world-client

  • C++
    你能夠在 examples/cpp/helloworld 目錄下構建並運行客戶端。假如你尚未構建客戶端,可使用以下命令:

    $ make 而後運行客戶端: $ ./greeter_client

  • Python

    你能夠從examples/python/helloworld目錄下用以下命令運行客戶端: $ ./run_client.sh

  • Go

    你能夠從examples/helloworld目錄下用以下命令運行客戶端:

    $ greeter_client

  • Ruby

    你能夠從examples/node目錄下用以下命令運行客戶端: $ bundle exec ./greeter_client.rb

  • Node.js

    你能夠從examples/node目錄下用以下命令運行客戶端:

    $ node ./greeter_client.js

  • C#

    構建解決方案,而後從 examples/csharp 目錄:

    > cd GreeterClient/bin/Debug
    > GreeterClient.exe
  • Objective-C

    打開由Cocoapods 建立的 XCode 工做空間,運行應用,你能夠在 XCode 的控制檯日誌裏看到結果。

  • PHP

    你能夠從 examples/php 目錄運行客戶端 :

    $ ./run_greeter_client.sh
相關文章
相關標籤/搜索