gRPC最佳入门教程,Golang/Python/PHP多语言讲解
雪山飞猪 人气:0
[toc]
# 一、gRPC是什么?
gRPC,其实就是RPC的一种,前面带了一个g,代表是RPC中的大哥,龙头老大的意思,另外g也有global的意思,意思是全球化比较fashion。
常见的RPC框架有如下:
1. gRPC。谷歌出品
2. Thrift。Apache出品
3. Dubbo。阿里出品,也是一个微服务框架
看[官方文档](https://grpc.io/)的介绍,有以下4点特性:
1. 使用Protocal Buffers这个强大的序列化工具集和语言
2. grpc可以跨语言使用
3. 安装简单,扩展方便(用该框架每秒可达到百万个RPC)
4. 基于HTTP2协议
# 二、Protocol Buffers是什么?
谷歌开源的一种结构数据序列化的工具,比方说JSON、XML也是结构数据序列化的工具,不同的是,
1. Protocol Buffers序列化后的数据是不可读的,因为是二进制流
2. 使用Protocol Buffer需要事先定义数据的格式(.proto 协议文件),还原一个序列化之后的数据需要使用到这个数据格式
3. Protocol Buffer 比 XML、JSON快很多,因为是基于二进制流,比字符串更省带宽,传入速度快
Protocol Buffer语法:查看[官方文档](https:/https://img.qb5200.com/download-x/developers.google.com/protocol-buffershttps://img.qb5200.com/download-x/docs/proto3)
# 三、需求:开发健身房服务
定义了一个健身房(Gym),然后提供一个叫健身(Bodybuilding)的服务
使用该服务,需要指定人(Person),人有名字和动作两个属性
```
syntax = "proto3";
//命名空间
package lightweight;
//健身房
service Gym {
rpc BodyBuilding (Person) returns (Reply) {
}
}
//谁在健身
message Person {
string name = 1;
repeated string actions = 2;
}
//结果
message Reply {
int32 code = 1;
string msg = 2;
}
```
# 四、最佳实践
下面以Golang、Python、PHP介绍该grpc的使用,代码已经上传到了[chenqionghe/grpc-demo](https://github.com/chenqionghe/grpc-demo)
## Golang
### 1. 安装protoc工具
地址:https://github.com/google/protobuf/releases
我是mac,用的是这个地址:https://github.com/protocolbuffers/protobuf/releaseshttps://img.qb5200.com/download-x/download/v3.11.4/protoc-3.11.4-osx-x86_64.zip
解压后放到了可以访问的bin即可
### 2. 安装protoc-gen-go
protoc依赖该工具生成代码
```
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
```
### 3. 安装grpc包
这是要代码里需要使用的,go get直接安装不了,手动克隆
```
git clone https://github.com/grpc/grpc-go.git $GOPATH/src/google.golang.org/grpc
git clone https://github.com/golang/net.git $GOPATH/src/golang.org/x/net
git clone https://github.com/golang/text.git $GOPATH/src/golang.org/x/text
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
git clone https://github.com/google/go-genproto.git $GOPATH/src/google.golang.org/genproto
cd $GOPATH/src/
go install google.golang.org/grpc
```
### 4. 生成代码
```
# 生成服务端代码
protoDir="../protos"
outDir="../languages/golang/gym"
protoc -I ${protoDir}/ ${protoDir}/*proto --go_out=plugins=grpc:${outDir}
```
protoc工具参数解释:
* -I: 指定import路径,可以指定多个-I参数,编译时按顺序查找,不指定默认当前目录
* -go_out:指定og语言的访问类
* plugins:指定依赖的插件
执行
然后我们会看到在golang目录生成了该代码
![](https://img2018.cnblogs.com/blog/662544/202003/662544-20200302120144409-1594156158.png)
### 5. 定义服务端
```
package main
import (
"app/lightweight"
"context"
"fmt"
"google.golang.org/grpc"
"log"
"net"
)
const (
port = ":50051"
)
// server继承自动生成的服务类
type server struct {
lightweight.UnimplementedGymServer
}
// 服务端必须实现了相应的接口BodyBuilding
func (s *server) BodyBuilding(ctx context.Context, in *lightweight.Person) (*lightweight.Reply, error) {
fmt.Printf("%s正在健身, 动作: %s\n", in.Name, in.Actions)
return &lightweight.Reply{Code: 0, Msg: "ok",}, nil
}
func main() {
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
lightweight.RegisterGymServer(s, &server{})
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
```
### 6. 定义客户端
```
package main
import (
"app/lightweight"
"context"
"fmt"
"google.golang.org/grpc"
"log"
"time"
)
const (
address = "localhost:50051"
)
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 := lightweight.NewGymClient(conn)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
r, err := c.BodyBuilding(ctx, &lightweight.Person{
Name: "chenqionghe",
Actions: []string{"深蹲", "卧推", "硬拉"},
})
if err != nil {
log.Fatalf("error: %v", err)
}
fmt.Printf("code: %d, msg: %s", r.Code, r.Msg)
}
```
### 7. 运行代码
golang目录结果是现在是这样的
```
.
├── client.go
├── go.mod
├── go.sum
├── lightweight
│ └── gym.pb.go
└── server.go
```
运行服务端和客户端,效果如下
![](https://img2018.cnblogs.com/blog/662544/202003/662544-20200302120158376-520152349.png)
## Python
### 1.安装grpc包
```
pip install grpcio
```
### 2.安装protobuf
```
pip install protobuf
```
### 3.安装grpc的protobuf编译工具
包含了protoc编译器和生成代码的插件
```
pip install grpcio-tools
```
### 4.生成代码
```
#!/usr/bin/env bash
protoDir="../protos"
outDir="../languages/python/gym/"
python3 -m grpc_tools.protoc -I ${protoDir}/ --python_out=${outDir} --grpc_python_out=${outDir} ${protoDir}/*proto
```
![](https://img2018.cnblogs.com/blog/662544/202003/662544-20200302120215136-2075105048.png)
### 5. 定义服务端
```
from concurrent import futures
import logging
import grpc
# 支持新的包
import sys
sys.path.append("lightweight")
import lightweight.gym_pb2_grpc as gym_pb2_grpc
import lightweight.gym_pb2 as gym_pb2
class Gym(gym_pb2_grpc.GymServicer):
def BodyBuilding(self, request, context):
print(f"{request.name}在健身, 动作: {list(request.actions)}")
return gym_pb2.Reply(code=0, msg='ok')
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
gym_pb2_grpc.add_GymServicer_to_server(Gym(), server)
server.add_insecure_port('[::]:50051')
server.start()
server.wait_for_termination()
if __name__ == '__main__':
logging.basicConfig()
serve()
```
### 6.定义客户端
```
from __future__ import print_function
import logging
import grpc
# 支持导入新的包
import sys
sys.path.append("lightweight")
import lightweight.gym_pb2_grpc as gym_pb2_grpc
import lightweight.gym_pb2 as gym_pb2
def run():
with grpc.insecure_channel('localhost:50051') as channel:
stub = gym_pb2_grpc.GymStub(channel)
response = stub.BodyBuilding(gym_pb2.Person(
name='chenqionghe', actions=['深蹲', '卧推', '硬拉']
))
print(f'code: {response.code}, msg:{response.msg}')
if __name__ == '__main__':
logging.basicConfig()
run()
```
### 7.运行代码
目录结构如下,分别运行
```
├── client.py
├── lightweight
│ ├── gym_pb2.py
│ └── gym_pb2_grpc.py
└── server.py
```
![](https://img2018.cnblogs.com/blog/662544/202003/662544-20200302120225540-626624207.png)
## PHP
### 1. 安装protoc
地址:https://github.com/google/protobuf/releases
我是mac,用的是这个地址:https://github.com/protocolbuffers/protobuf/releaseshttps://img.qb5200.com/download-x/download/v3.11.4/protoc-3.11.4-osx-x86_64.zip
解压后放到了可以访问的bin即可
### 2. 安装grpc扩展
方式一:pecl安装
```
pecl install grpc
```
将扩展加入到php.ini
```
extension=grpc.so
```
### 3. 安装protobuf扩展
```
pecl install protobuf
```
将扩展加入到php.ini
```
extension=protobuf.so
```
### 4.安装生成代码的插件grpc_php_plugin
该插件用来生成PHP的gRPC代码
```
git clone -b v1.27.0 https://github.com/grpc/grpc
cd grpc && git submodule update --init && make grpc_php_plugin
```
>注意:这个过程耗时比较久,请做好心理准备,画风是这样的(依赖的所有仓库可以在.gitmodules文件中看到)
![](https://img2018.cnblogs.com/blog/662544/202003/662544-20200302120245347-1021912900.png)
如果grpc_php_plugin安装不上,mac系统可以直接copy我已经编译好的[grpc_php_plugin](https://github.com/chenqionghe/grpc-demo/blob/master/grpc/bins/opt/grpc_php_plugin)
安装完成画风
![](https://img2018.cnblogs.com/blog/662544/202003/662544-20200302120256013-619603378.png)
最终会在bins/opt下生成grpc_php_plugin文件,我们把它移动到/usr/local/bin下
### 5.生成代码
```
#!/usr/bin/env bash
protoDir="../protos"
outDir="../languages/php/lightweight"
protoc -I ${protoDir}/ ${protoDir}/*proto --go_out=plugins=grpc:${outDir}
protoc --proto_path=${protoDir} \
--php_out=${outDir} \
--grpc_out=${outDir} \
--plugin=protoc-gen-grpc=/usr/local/bin/grpc_php_plugin \
${protoDir}/*.proto
```
生成代码如下
![](https://img2018.cnblogs.com/blog/662544/202003/662544-20200302120322391-164535321.png)
### 6.定义客户端文件
1.创建composer.json文件并执行
```
{
"name": "gym",
"require": {
"grpc/grpc": "^v1.3.0",
"google/protobuf": "^v3.3.0"
},
"autoload": {
"psr-4": {
"GPBMetadata\\": "lightweight/GPBMetadata/",
"Lightweight\\": "lightweight/Lightweight/"
}
}
}
```
执行composer install
2.创建客户端文件client.php
```
Grpc\ChannelCredentials::createInsecure(),
]);
//带上自己的卡和运动计划
$request = new \Lightweight\Person();
$request->setName("chenqionghe");
$request->setActions(['深蹲', '卧推', '硬拉']);
//去健身房健身
list($response, $status) = $client->BodyBuilding($request)->wait();
echo sprintf("code: %s, msg: %s \n", $response->getCode(), $response->getMsg());
```
注意:php不支持grpc的服务端,建议服务端起一个上面的golang或者python中的server
这里我用的是golang的
### 7.运行代码
![](https://img2020.cnblogs.com/blog/662544/202003/662544-20200302120706553-25725592.png)
OK,到这里,分别演示了Golang、Python、PHP使用gRPC的例子,相信你也已经学会了
加载全部内容