使用grpc實現php、java、go三方互調

grpc做爲經典的rpc協議,雖然略重,可是是有學習的價值的php

經過下面的內容能夠快速上手這個grpc框架java

完整案例代碼已上傳github: github.com/neatlife/my…git

安裝命令行工具

php須要這個額外的protoc、grpc_php_plugin工具把這個protobuf格式的文件生成php語言裏的類github

go須要安裝protoc-gen-go工具把protobuf格式的接口定義文件生成go語言裏的類定義golang

java無需手動安裝額外工具,有maven便可,再次體現了java的優越性(shell

protoc

github.com/protocolbuf…bash

解壓後,把bin目錄放到PATH裏面

編譯grpc_php_plugin

構建參考服務器

git clone https://github.com/grpc/grpc.git
cd grpc
brew install autoconf automake libtool shtool
LIBTOOL=glibtool LIBTOOLIZE=glibtoolize make -j8
複製代碼

grpc源碼庫較大,能夠直接開8核進行編譯 編譯好的grpc_php_plugin在bins/opt/目錄下,把grpc_php_plugin放到PATH裏面 數據結構

安裝php的grpc擴展

擴展的地址:pecl.php.net/package/gRP…框架

編譯protoc-gen-go

項目地址:github.com/golang/prot…

git clone https://github.com/golang/protobuf.git
cd protobuf/protoc-gen-go
go build
複製代碼

操做效果以下

把這個生成的protoc-gen-go放到PATH

案例設計

go: 提供grpc服務端,提供一個sayHello的接口,參數爲表明名字的字符串,返回值爲 「Hello"拼接上這個名字 java和php做爲客戶端調用這個go的客戶端

grpc依賴

go

"golang.org/x/net/context"                                                                                                                                                                      
"google.golang.org/grpc"
"google.golang.org/grpc/reflection"
複製代碼

java

<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-netty</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-protobuf</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>io.grpc</groupId>
    <artifactId>grpc-stub</artifactId>
    <version>1.0.0</version>
</dependency>
複製代碼

php

"grpc/grpc": "^v1.9",                                                                                                                                                                       
"google/protobuf": "^v3.5"
複製代碼

核心代碼

proto文件

syntax = "proto3";

option go_package = "pbf";

package helloworld;

// The greeting service definition.
service Hello {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloResponse) {}
}

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

// The response message containing the greetings
message HelloResponse {
  string message = 1;
}
複製代碼

這個protobuf文件定義了兩個數據結構,HelloRequest和HelloResponse,和一個SayHello的接口

使用下面的命令把這個proto文件編譯成對應的php和go的數據結構

#!/bin/bash

for file in ./protos/*.proto; do
    echo "生成對應的php類文件: $file"
    protoc -I ./protos --php_out=./php/pbf --grpc_out=./php/pbf --plugin=protoc-gen-grpc=$(which grpc_php_plugin) $file
done

protoc -I ./protos --go_out=plugins=grpc:./go/pbf ./protos/*.proto
複製代碼

go服務端核心代碼

// helloServer implements helloworld.HelloServer
type helloServer struct{}

// SayHello implements helloworld.HelloServer
func (s *helloServer) SayHello(ctx context.Context, in *pbf.HelloRequest) (*pbf.HelloResponse, error) {
	return &pbf.HelloResponse{Message: "Hello " + in.Name}, nil
}

func main() {
	s := grpc.NewServer()
	pbf.RegisterHelloServer(s, &helloServer{})

	reflection.Register(s)
   s.Serve(lis)
}
複製代碼

func (s *helloServer) SayHello(ctx context.Context, in *pbf.HelloRequest) (*pbf.HelloResponse, error)裏面就是SayHello這個接口的具體實現了

php客戶端核心代碼

$name = '小明';

$client = new Helloworld\HelloClient('localhost:8488', [
    'credentials' => Grpc\ChannelCredentials::createInsecure(),
]);
$request = new Helloworld\HelloRequest();
$request->setName($name);
list($response, $status) = $client->SayHello($request)->wait();

echo '服務端返回狀態碼: ' . $status->code . PHP_EOL;
echo "服務器端回覆內容:" . $response->getMessage() . PHP_EOL;
複製代碼

code 0表示正常

java客戶端核心代碼

private final HelloGrpc.HelloBlockingStub blockingStub;

public HelloClient(String host, int port) {
    //初始化鏈接
    channel = ManagedChannelBuilder.forAddress(host, port)
            .usePlaintext(true)
            .build();
    //初始化遠程服務Stub
    blockingStub = HelloGrpc.newBlockingStub(channel);
}

public String sayHello(String name) {
    //構造服務調用參數對象
    Helloworld.HelloRequest request = Helloworld.HelloRequest.newBuilder().setName(name).build();
    //調用遠程服務方法
    Helloworld.HelloResponse response = blockingStub.sayHello(request);
    //返回值
    return response.getMessage();
}
複製代碼

sayHello()裏就是經過grpc調用go的sayHello方法。

查看效果

能夠看到,這三個程序都ok了

一些注意的點

go、java、php的編譯已經寫到了Makefile中, 使用make便可一鍵編譯

參考連接

  1. github.com/golang/prot…
  2. blog.csdn.net/strongyoung…
相關文章
相關標籤/搜索