grpc作為經典的rpc協議,雖然略重,但是是有學習的價值的
通過下面的內容可以快速上手這個grpc框架
安裝命令行工具
php需要這個額外的protoc、grpc_php_plugin工具把這個protobuf格式的文件生成php語言里的類
go需要安裝protoc-gen-go工具把protobuf格式的接口定義文件生成go語言里的類定義
java無需手動安裝額外工具,有maven即可,再次體現了java的優越性(
protoc
解壓后,把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擴展
編譯protoc-gen-go
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
io.grpc
grpc-netty
1.0.0
io.grpc
grpc-protobuf
1.0.0
io.grpc
grpc-stub
1.0.0
復制代碼
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即可一鍵編譯
參考鏈接