grpc 的第一次嘗試

已下線發表於2019-12-24

gRPC是可以在任何環境中執行的現代開源高效能RPC框架。它可以通過可插拔的支援來有效地連線資料中心內和跨資料中心的服務,以實現負載平衡,跟蹤,執行狀況檢查和身份驗證。它也適用於分散式計算的最後一英里,以將裝置,移動應用程式和瀏覽器連線到後端服務。

安裝protocol buffer 編譯器

mac:

brew install protobuf

其他系統可以嘗試編譯安裝

安裝gprc

go get -u google.golang.org/grpc

安裝protoc-gen-go外掛

go get -u github.com/golang/protobuf/protoc-gen-go

使用

新建hello目錄,進入後執行:

protoc --proto_path hello/ --go_out=plugins=grpc:hello hello.proto

會看到hello目錄下生成了hello.pb.go檔案。

當然,其中的 hello.proto 是預先自定義在hello資料夾下的,如:

syntax = "proto3";  //語法宣告

package hello; //包名

// 定義服務
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// 請求資料格式
message HelloRequest {
  string name = 1;
}

// 響應資料格式
message HelloReply {
  string message = 1;
}

server

新建server目錄,
golang例子程式碼來自:https://github.com/grpc/grpc-go/tree/maste...

// main.go
package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "local.com/sai/game/grpc/hello"
)

const (
    port = ":50051"
)

// server is used to implement helloworld.GreeterServer.
type server struct {
    pb.UnimplementedGreeterServer
}

// SayHello implements helloworld.GreeterServer
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    log.Printf("Received: %v", in.GetName())
    return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}

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{})
    if err := s.Serve(lis); err != nil {
        log.Fatalf("failed to serve: %v", err)
    }
}

client

go client

// client.go
package main

import (
    "context"
    "log"
    "os"
    "time"

    "google.golang.org/grpc"
    pb "local.com/sai/game/grpc/hello"
)

const (
    address     = "127.0.0.1:50051"
    defaultName = "13sai"
)

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

    // Contact the server and print out its response.
    name := defaultName
    if len(os.Args) > 1 {
        name = os.Args[1]
    }
    ctx, cancel := context.WithTimeout(context.Background(), time.Second)
    defer cancel()
    r, err := c.SayHello(ctx, &pb.HelloRequest{Name: name})
    if err != nil {
        log.Fatalf("could not greet: %v", err)
    }
    log.Printf("Greeting: %s", r.GetMessage())
}`

php client

擴充套件安裝

下載安裝合適版本的擴充套件即可,記得別忘記在php.ini中加入:

extension=grpc.so
extension=protobuf.so

自動生成程式碼

protoc --php_out=client hello/hello.proto

會看到client目錄下生成了GPBMetadata和Hello兩個目錄。

如果你對grpc相對叫熟練,可以直接進行程式碼編寫:

<?php
require __DIR__ . '/vendor/autoload.php';

class Client extends \Grpc\BaseStub{

    public function __construct($hostname, $opts, $channel = null) {
        parent::__construct($hostname, $opts, $channel);
    }

    /**
     * rpc SayHello(HelloRequest) returns (HelloReply) {}
     * 方法名儘量和 (gprc 定義 Greeter 服務)的方法一樣
     * 用於請求和響應該服務
     */
    public function SayHello(\Hello\HelloRequest $argument){
        // (/hello.Greeter/SayHello) 是請求服務端那個服務和方法,基本和 proto 檔案定義一樣
        return $this->_simpleRequest('/hello.Greeter/SayHello',
            $argument,
            ['\Hello\HelloReply', 'decode']
            );
    }

}

//用於連線 服務端
$client = new \Client('127.0.0.1:50051', [
    'credentials' => Grpc\ChannelCredentials::createInsecure()
]);

//例項化 TestRequest 請求類
$request = new \Hello\HelloRequest();
$request->setName("fairy");

//呼叫遠端服務
$get = $client->SayHello($request)->wait();

//返回陣列
//$reply 是 TestReply 物件
//$status 是陣列
list($reply, $status) = $get;

echo $reply->getMessage().PHP_EOL;
// print_r($client->SayHello($request));

當然,也可以使用grpc_php_plugin外掛生成。

grpc_php_plugin外掛

clone太慢可以使用碼雲

git clone -b $(curl -L https://grpc.io/release) https://github.com/grpc/grpc
cd grpc
#這一步很慢,暫未找到什麼好方法
git submodule update --init
make grpc_php_plugin

新建php-client,再來自動生成:

protoc -I=./hello hello.proto --php_out=./php-client/ --grpc_out=php-client/ --plugin=protoc-gen-grpc=/Users/wangzetao/www/grpc1/bins/opt/grpc_php_plugin

會發現比上面自動生成多了一個GreeterClient.php

<?php
// client.php
require __DIR__ . '/vendor/autoload.php';

//用於連線 服務端
$client = new \Hello\GreeterClient('127.0.0.1:50051', [
    'credentials' => Grpc\ChannelCredentials::createInsecure()
]);

//例項化 TestRequest 請求類
$request = new \Hello\HelloRequest();
$request->setName("world");

//呼叫遠端服務
$get = $client->SayHello($request)->wait();

//返回陣列
//$status 是陣列
list($reply, $status) = $get;

echo $reply->getMessage().PHP_EOL;
// print_r($client->SayHello($request));

執行測試

go run grpc/server/main.go

grpc

go run grpc/client/main.go

go run grpc/client/client.php

go run grpc/client/php-client.php

grpc

grpc初體驗完成了,本次只是小小的使用了一下子,後續感興趣的話可以深入學習一下。文中如有錯誤,歡迎指出交流。

分享開發知識,歡迎交流。

相關文章