前言
gRPC是Google公布的开源项目,基于HTTP2.0协议,并支持常见的众多编程语言。HTTP2.0协议是基于二进制的HTTP协议的升级版本,gRPC底层使用了Netty框架
(1):RPC接口和HTTP接口有什么区别呢?
RPC(Remote Procedure Call,远程过程调用)和HTTP(HyperText Transfer Protocol,超文本传输协议),前者是一种方法后者是协议,两者都常用于实现服务,在这个层面最本质的区别是RPC服务主要工作在TCP协议之上(也可以在HTTP协议),而HTTP服务工作在HTTP协议之上。由于HTTP协议基于TCP协议,所以RPC服务天然比HTTP更轻量,效率更胜一筹
两者都是基于网络实现的,从这一点上,都是基于Client/Server架构
(2):RPC接口和HTTP接口怎么选择?
传输效率:RPC比HTTP更快,虽然两者底层都是TCP,但是HTTP信息更加臃肿(不过可以采用gzip压缩),而RPC可以基于thrift实现高效的二进制传输
灵活性:HTTP比RPC更简单,开发效率更快。RPC每次增删改一个传输/返回参数服务端和客户端都要重新生成pb文件
所以综上所述,我的建议是内部接口走RPC,开放接口走HTTP
首先是前期准备(以CentOS-7为例)
(1):完成Golang运行环境安装,版本根据需求自定义,建议1.17以上
(2):安装 protobuf 编译器
(2-1):wget https://github.com/protocolbuffers/protobuf/releases/download/v3.11.2/protobuf-all-3.11.2.tar.gz
(2-2):tar zxf protobuf-all-3.11.2.tar.gz
(2-3):cd protobuf-3.11.2
(2-4):./configure -prefix=/usr/local/
(2-5):make && make install
root@localhost> protoc --version
# 能正常输出版本即可,安装过程中出现失败按照错误提示安装前置扩展即可
(3):安装Go protobuf插件
(3-1):go get -u github.com/golang/protobuf/proto
(3-2):go get -u github.com/golang/protobuf/protoc-gen-go
(3-3):go get -u google.golang.org/grpc
然后是创建服务端(以golang1.7版本为例)
(1):创建proto文件
// 指定 proto 版本
syntax = "proto3";
option go_package="./;proto";
// 指定包名
package proto;
// 说明接口用途,养成良好注释习惯
service CloseExpireOrder {
rpc CloseExpireOrder(CloseExpireOrderRequest) returns (CloseExpireOrderResponse) {}
}
// 接口请求参数
message CloseExpireOrderRequest {
string oid = 1;
}
// 接口返回参数
message CloseExpireOrderResponse {
int32 result = 1;
string msg = 2;
string data = 3;
}
(2):生成pb.go文件
进入上述proto所在目录运行 "protoc -I . --go_out=plugins=grpc:. ./xxx.proto"
(3):创建业务控制器
package order
import (
"context"
"encoding/json"
"net/http"
CloseExpireOrderPB "xxx/services/grpc/proto/closeexpireorder"
)
type OrderControllers struct{}
func (h *OrderControllers) CloseExpireOrder(ctx context.Context, c *CloseExpireOrderPB.CloseExpireOrderRequest) (*CloseExpireOrderPB.CloseExpireOrderResponse, error) {
if c.Oid == "" {
return &CloseExpireOrderPB.CloseExpireOrderResponse{Result: http.StatusBadRequest, Msg: "校验参数缺失", Data: "{}"}, nil
}
// 这里写你的业务。。。。。
return &CloseExpireOrderPB.CloseExpireOrderResponse{Result: http.StatusOK, Msg: "订单成功已成功关闭", Data: "{}"}, nil
}
(4):创建入口路由文件【只用创建一次】
```
/*
* @Author: psq
* @Date: 2022-01-30 21:20:08
* @LastEditors: psq
* @LastEditTime: 2022-09-02 17:22:23
*/
package service
import (
"fmt"
"net"
"os"
"xxx/services/grpc/controllers/order"
CloseExpireOrderPB "xxx/services/grpc/proto/closeexpireorder"
GoogleGPRC "google.golang.org/grpc"
"google.golang.org/grpc/reflection"
)
/**
* @description: 启动GRPC服务
* @param {int16} port 运行端口
* @return {*}
*/
func GrpcServiceStart(port int16) {
lis, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
if err != nil {
fmt.Println(fmt.Scanln("GRPC启动失败, 服务已自动, 终止错误内容: [%s]", err))
os.Exit(0)
}
fmt.Println("GRPC启动成功, 占用端口", port)
GrpcServer := GoogleGPRC.NewServer()
reflection.Register(GrpcServer)
CloseExpireOrderPB.RegisterCloseExpireOrderServer(GrpcServer, &order.OrderControllers{})
GrpcServer.Serve(lis)
}
```
(5):GRPC接口测试
// 安装过程如果遇到报错,按照提示安装所需的前置扩展即可
(1) : go get github.com/fullstorydev/grpcui
(2) : go install github.com/fullstorydev/grpcui/cmd/grpcui
(3) : root@localhost> grpcui -plaintext 127.0.0.1:[GRPC服务端口]
上述步骤完成后,恭喜你,GRPC服务已经创建好了,很简单吧!!!
最后就是客户端调用了
python调用示例(版本3.6)
(1):pip install grpcio
(2):pip install protobuf
(3):pip install grpcio_tools
# 将服务端的proto文件原样复制过来
(4):python -m grpc_tools.protoc --python_out=../pb2/ --grpc_python_out=../pb2grpc -I. ./xxx.proto
# 调用示例
'''
Author: psq
Date: 2022-09-02 17:31:42
LastEditors: psq
LastEditTime: 2022-09-04 14:45:33
'''
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
import grpc
import [XXX]_pb2,
import [XXX]_pb2_grpc
if __name__ == '__main__':
with grpc.insecure_channel("[GRPC主机地址]:[GRPC主机端口]") as channel:
res = closeexpireorder_pb2_grpc.CloseExpireOrderStub(channel = channel).CloseExpireOrder(closeexpireorder_pb2.CloseExpireOrderRequest(oid = "hello world!"))
print(res.msg)
golang调用示例(版本1.17)
package main
import (
"fmt"
CloseExpireOrderPB "xxx/services/grpc/proto/closeexpireorder"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
func main() {
//得到 gRPC 链接客户端句柄
conn, err := grpc.Dial("[GRPC主机地址]:[GRPC主机端口]", grpc.WithInsecure())
if err != nil {
fmt.Println("did not connetc : ", err)
return
}
defer conn.Close()
//将 proto 里面的服务句柄 和 gRPC句柄绑定
c := pb.NewCloseExpireOrder(conn)
//远程调用 CloseExpireOrder接口
r1, err := c.CloseExpireOrder(context.Background(), &pb.CloseExpireOrderRequest{Oid: "hello world"})
if err != nil {
fmt.Println("cloud not get Hello server ..", err)
return
}
fmt.Println(r1.Result, r1.Msg, r1.Data)
}
php调用示例(版本7.2)
(1):使用编译或pecl方式安装grpc和protobuf扩展
(2):使用composer安装grpc和protobuf依赖包
composer require grpc/grpc -vvv
composer require google/protobuf -vvv
(3):将服务端的proto文件原样复制到你要存放的目录后运行命令生成连接文件
protoc --php_out=. ./xxx.proto
(4):创建连接客户端
<?php
/*
* @Author: psq
* @Date: 2022-09-07 16:14:35
* @LastEditors: psq
* @LastEditTime: 2022-09-07 17:15:25
*/
class GrpcClient extends \Grpc\BaseStub
{
/**
* @description: GRPC连接初始化
* @param {*} $channel
* @return {*}
*/
public function __construct($channel = null)
{
parent::__construct('[GRPC主机地址]:[GRPC主机端口]', [
'credentials' => \Grpc\ChannelCredentials::createInsecure(),
], $channel);
}
/**
* @description: 获取用户平台VIP等级
* @param {UserGradeRequest} $argument
* @param {*} $metadata
* @param {*} $options
* @return {*}
*/
public function CloseExpireOrder(\Proto\CloseExpireOrderRequest $argument, $metadata = [], $options = [])
{
// 传递参数说明
// 0: 找到golang那边生成的pd.go文件里面的FullMethod的值原模原样填写过来即可!
// 1: [接收返回内容的控制器, 解析]
return $this->_simpleRequest('/proto.CloseExpireOrder/CloseExpireOrder', $argument, ['Proto\CloseExpireOrderResponse', 'decode'], $metadata, $options);
}
// 后续有新的接口在后面加function即可
}
(5): 调用测试
$request = new \Proto\CloseExpireOrderRequest();
$request->setOid("hello world");
$requestSend = (new GrpcClient())->CloseExpireOrder($request)->wait();
list($grpcResponse, $grpcSendStatus) = $requestSend;
dump($grpcSendStatus);
// 注意:$grpcSendStatus->code如果等于0表示请求成功,其他表示失败
dump($grpcResponse->getResult());
dump($grpcResponse->getMsg());
dump($grpcResponse->getData());
其他开发语言我这边暂时没用到,需要自行补充啦~~