GRPC框架
GRPC是Google公司基于Protobuf开发的跨语言的开源RPC框架。GRPC基于HTTP/2协议设计,可以基于一个HTTP/2链接提供多个服务,对于移动设备更加友好。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.
在 gRPC里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC系统类似, gRPC也是基于以下理念:
定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。
在服务端实现这个接口,并运行一个 gRPC服务器来处理客户端调用。
在客户端拥有一个存根能够像服务端一样的方法。 gRPC客户端和服务端可以在多种环境中运行和交互 -从 google内部的服务器到你自己的笔记本,并且可以用任何 gRPC支持的语言 来编写。
所以,你可以很容易地用 Java创建一个 gRPC服务端,用 Go、 Python、Ruby来创建客户端。此外, Google最新 API将有 gRPC版本的接口,使你很容易地将 Google的功能集成到你的应用里。
参考资料
gRPC 官方文档中文版:http://doc.oschina.net/grpc?t=60133
gRPC官网:https://grpc.io
使用
如果从Protobuf的角度看,GRPC只不过是一个针对service接口生成代码的生成器。
我们继续看在Protobuf里说的例子
proto文件,定义一个包含乘除两个方法的ArithService服务
syntax = "proto3";
//指定生成在哪个文件夹下,;后为包名
option go_package ="/;pb";
//现在不用package
//package pb;
// 算术运算请求结构
message ArithRequest {
int32 a = 1;
int32 b = 2;
}
// 算术运算响应结构
message ArithResponse {
int32 pro = 1; // 乘积
int32 quo = 2; // 商
int32 rem = 3; // 余数
}
// rpc方法
service ArithService {
rpc multiply (ArithRequest) returns (ArithResponse); // 乘法运算方法
rpc divide (ArithRequest) returns (ArithResponse); // 除法运算方法
}
对proto文件进行编译:
$ protoc --go_out=plugins=grpc:. *.proto
GRPC插件会为服务端和客户端生成不同的接口:
服务端
// ArithServiceServer is the server API for ArithService service.
type ArithServiceServer interface {
Multiply(context.Context, *ArithRequest) (*ArithResponse, error)
Divide(context.Context, *ArithRequest) (*ArithResponse, error)
}
我们只要去定义一个服务,去实现这两个方法,就定义好服务端的server了。
客户端
type ArithServiceClient interface {
Multiply(ctx context.Context, in *ArithRequest, opts ...grpc.CallOption) (*ArithResponse, error)
Divide(ctx context.Context, in *ArithRequest, opts ...grpc.CallOption) (*ArithResponse, error)
}
客户端,直接可以在main函数中定义一个客户端,并且调用这两个方法即可
完整代码:
server端:
package main
import (
"go-micro/pb"
"golang.org/x/net/context"
"google.golang.org/grpc"
"net"
)
//定义了服务端
type ArithService struct {
}
//并具体实现在pb文件server中的接口
func (service *ArithService) Multiply(ctx context.Context, request *pb.ArithRequest) (*pb.ArithResponse, error) {
var resp pb.ArithResponse
resp.Pro=request.A*request.B
return &resp,nil
}
func (service *ArithService) Divide(ctx context.Context, request *pb.ArithRequest) (*pb.ArithResponse, error) {
var resp pb.ArithResponse
resp.Quo=request.A/request.B
resp.Rem=request.A%request.B
return &resp,nil
}
func main() {
//获取grpc服务端对象
server := grpc.NewServer()
//注册grpc服务
pb.RegisterArithServiceServer(server,new(ArithService))
//设置服务端监听
listen, err := net.Listen("tcp", "127.0.0.1:8848")
if err != nil {
panic(err)
}
//在指定端口上提供grpc服务
server.Serve(listen)
}
Server 端流程:
- 获取grpc服务端对象
- 注册grpc服务
- 设置服务端监听
- 在指定端口上提供grpc服务
client:
func main(){
//和grpc服务建立连接
//需要验证,使用所以使用grpc.WithInsecure()跳过了证书验证,之后再学习验证方法
conn, err := grpc.Dial("127.0.0.1:8848",grpc.WithInsecure())
if err != nil {
panic(err)
}
defer conn.Close()
//创建客户端
client := pb.NewArithServiceClient(conn)
req:=pb.ArithRequest{
A: 8,
B: 3,
}
response, err := client.Divide(context.Background(), &req)
if err != nil {
panic(err)
}
fmt.Println(response)
multiply, err := client.Multiply(context.Background(), &req)
if err != nil {
panic(err)
}
fmt.Println(multiply)
}
Client 端流程:
- 获取grpc服务端对象
- 注册grpc服务
- 设置服务端监听
- 在指定端口上提供grpc服务