最近在搞grpc这块的东西,需要帮自动化测试工具把grpc转成http,用到了这块东西,折腾了好几天最终搞定
可直接看分割线一下内容
1、GRPC概述
GRPC 一开始由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。
在 GRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法,使得您能够更容易地创建分布式应用和服务。与许多 RPC 系统类似,GRPC 也是基于以下理念:定义一个服务,指定其能够被远程调用的方法(包含参数和返回类型)。在服务端实现这个接口,并运行一个 GRPC 服务器来处理客户端调用。在客户端拥有一个存根能够像服务端一样的方法。
2、特性
基于HTTP/2
HTTP/2 提供了连接多路复用、双向流、服务器推送、请求优先级、首部压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU,帮助移动设备延长电池寿命等。gRPC 的协议设计上使用了HTTP2 现有的语义,请求和响应的数据使用HTTP Body 发送,其他的控制信息则用Header 表示。
IDL使用ProtoBuf
GRPC使用ProtoBuf来定义服务,ProtoBuf是由Google开发的一种数据序列化协议(类似于XML、JSON、hessian)。ProtoBuf能够将数据进行序列化,并广泛应用在数据存储、通信协议等方面。压缩和传输效率高,语法简单,表达力强。
多语言支持(C, C++, Python, PHP, Nodejs, C#, Objective-C、Golang、Java)
GRPC支持多种语言,并能够基于语言自动生成客户端和服务端功能库。目前已提供了C版本grpc、Java版本grpc-java 和 Go版本grpc-go,其它语言的版本正在积极开发中,其中,grpc支持C、C++、Node.js、Python、Ruby、Objective-C、PHP和C#等语言,grpc-java已经支持Android开发。
为什么需要grpc测试工具?
目前大多数分布式服务之间的调用是基于http 1.*协议实现的,HTTP/1.* 是纯文本数据传输。而grpc框架的底层网络协议是HTTP2.0,在传输的过程中数据是二进制的,在目前的市面是还有没有比较完善和方便的测试grpc框架的测试工具,像是测试http1.*的postman这种下载就能使用的测试工具。
但是在开源社区已经有很多的贡献者给出解决方案,这些方案都是一个在grpc服务和传统的httpclient测试工具之间代建一个代理服务,将传统的http1.*的请求包装转化为grpc框架的HTTP2请求。
常用的grpc测试框架是有:
grpcc:https://github.com/njpatel/grpcc,grppc是nodejs技术实现的,一个命令行工具。
Omgrpc: https://github.com/troylelandshields/omgrpc, omgrpc是nodejs技术实现,运行一个客户端,读取解析一个protobuf文件,将message消息的结构体中的字段会映射到一张表单中,填写相关的测试数据就可以运行。
Grpc-json-proxy: https://github.com/jnewmano/grpc-json-proxy,go语言的技术实现,启动一个一个go程序做代理层,可以结合postman等流行httpclient测试工具使用。对go 语言开发的grpc服务支持较好。
grpc-gateway是ProtoC的插件。ProtoC是protobuf底层解析器,它读取GRPC服务定义,并生成一个反向代理服务器,将一个REST的JSON API转换成GRPC。这个服务器是根据您的GRPC定义中的自定义选项生成的。
它可以帮助您同时提供GRPC和REST风格的API。
它用许多编程语言生成API客户机和服务器存根,它快速、易用、带宽高效,其设计得到了Google的验证。但是,您可能还希望提供一个传统的REST API。原因可以是维护向后兼容性、支持gRPC不支持的语言或客户端,也可以是简单地维护RESTful体系结构所涉及的美学和工具。而GRPC Gateway仅生成go语言的代理,因此在搭建GRPC Gateway前需要搭建Go语言基本环境。 另外由于Go语言相关插件以及Github访问,可能需要代理才能访问。因此运行本手册建议先确保能使用代理服务器访问Golang、Github等网站
本项目旨在为您的GRPC服务提供HTTP+JSON接口。附加HTTP语义的服务中的少量配置就是使用该库生成反向代理所需的全部配置。
******************************************************************************************************************************************************
分割线
******************************************************************************************************************************************************
5、开始搭建:
5.1 搭建go语言环境
安装golang环境的官方文档,https://www.nats.io/documentation/tutorials/go-install/,有详细的说明,但是官方的网站,可能需要代理才能访问。
可以在https://studygolang.com/dl这里下载到所需资源,本例是win7的64位系统所以本例下载的是go1.9.2 windows/amd64的压缩文件,解压后的目录结构如下:
正确的配置GOROOT和GOPATH环境变量:
$GOROOT 指向golang安装之后的根目录,windows平台下默认为c:/go此处记得修改。本例中是D:\softo\go
$GOPATH 个人代码存放目录,本例中是D:\softo\go\third_party
在系统环境变量里面添加:window下,在我的电脑右键,点击属性->高级系统设置(window8)->高级->环境变量
在系统变量里添加GOPATH(你代码放的地方),如果msi安装的话,GOROOT(golang的安装目录),GOBIN(golang安装目录中bin文件夹)直接添加啦,zip安装这两个就需要自己配置
配置完成,打开cmd,输入go ,就可以看到go的命令
Protobuf是grpc框架底层的序列化工具,所以再使用grpc框架时,一定需要安装protobuf工具。到https://github.com/protocolbuffers/protobuf/releases,下载所需要的版本(win32的我用的是这个版本protoc-3.6.1-win32.zip),本例中下载win版本的zip包,目录地址是D:\softo\protobuf, 解压下来目录结构是:
把bin目录写到系统环境变量里面,本例是:D:\softo\protobuf\bin,将其加入系统PATH变量中。
Protobuf的版本要求大于3.0.0-beta-3,另外protobuf的include目录,在后续步骤会采用。
5.3 grpc-gateway 依赖
grpc-gateway是一个开源的服务项目,在github上可以很轻松的获得。这是grpc-gateway的地址:https://github.com/grpc-ecosystem/grpc-gateway。
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger go get -u github.com/golang/protobuf/protoc-gen-go |
下载资源的过程可能需要用到(因为有部分的google组件)
参考:https://grpc-ecosystem.github.io/grpc-gateway/docs/usage.html(官方的安装步骤)。
如果不想下载,或者环境不允许的情形下可以使用以下步骤实现
组件可以从下面链接访问下载:
http://git.orientsec.com.cn/projects/GRPC/repos/grpc-docs/browse/%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C/third_party.zip
将third_party.zip解压到D:\softo\go目录
目录结构为
grpc-gateway 使用
在%GOPATH%/src目录下新建一个gw目录(名称可以任意),将grpc service端的*.protobuf的文件拷贝一份到目录下,本例的路劲如下:D:\softo\go\third_party\src\gw\greeter.proto,其内容如下:
syntax = "proto3"; option java_multiple_files = true; option java_package = "com.orientsec.demo"; option java_outer_classname = "GreeterProto"; package com.orientsec.demo; service Greeter { rpc sayHello (GreeterRequest) returns (GreeterReply) {} } message GreeterRequest { int32 no = 1; string name = 2; bool sex = 3; double salary = 4; string desc = 5; } message GreeterReply { bool success = 1; string message = 2; int32 no = 3; double salary = 4; int64 total = 5; } |
修改greeter.proto文件:
syntax = "proto3"; option java_multiple_files = true; option java_package = "com.orientsec.demo"; option java_outer_classname = "GreeterProto"; package com.orientsec.demo; import "google/api/annotations.proto"; service Greeter { // rpc sayHello (GreeterRequest) returns (GreeterReply) {} rpc sayHello (GreeterRequest) returns (GreeterReply) { option (google.api.http) = { post: "/v1/sayHello" body: "*" }; } } message GreeterRequest { int32 no = 1; string name = 2; bool sex = 3; double salary = 4; string desc = 5; } message GreeterReply { bool success = 1; string message = 2; int32 no = 3; double salary = 4; int64 total = 5; } |
环境准备到此结束
通过下面的命令生成grpc stub, 切换到目录 D:\softo\go\third_party\src\gw:
protoc -ID:\softo\protobuf\include -I. -I%GOPATH%/src -I%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --go_out=plugins=grpc:. ./greeter.proto |
D表示的是d盘
运行的结果,在D:\softo\go\third_party\src\gw生成一个greeter.pb.go文件。该文件主要是grpc stub文件,处理grpc 服务注册发现等问题。
通过下面的命令生成反向代理:
protoc -ID:\softo\protobuf\include -I. -I%GOPATH%/src -I%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --grpc-gateway_out=logtostderr=true:. ./greeter.proto |
运行的结果,在D:\softo\go\third_party\src\gw生成一个greeter.pb.gw.go文件。该文件的主要作用是生成代理服务,转化http包到rpc包格式等。
编译后生成如下:
新建目录D:\softo\go\third_party\src, 目录下新建main.go文件,内容如下:
package main import ( "flag" "net/http" "github.com/golang/glog" "golang.org/x/net/context" "github.com/grpc-ecosystem/grpc-gateway/runtime" "google.golang.org/grpc" gw "gw") var (echoEndpoint = flag.String("echo_endpoint", "localhost:51001", "endpoint of YourService")) func run() error { ctx := context.Background() ctx, cancel := context.WithCancel(ctx) defer cancel() mux := runtime.NewServeMux() opts := []grpc.DialOption{grpc.WithInsecure()} err := gw.RegisterGreeterHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts) if err != nil { return err } return http.ListenAndServe(":9090", mux) } func main() { flag.Parse() defer glog.Flush() if err := run(); err != nil { glog.Fatal(err) } }
|
其中echoEndpoint = flag.String("echo_endpoint", "ip:51001", "endpoint of YourService"),ip:51001,是grpc 服务地址。gw.RegisterYourServiceHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts),其中红色部分需要收到修改一下, 本例修改为:gw.RegisterGreeterHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts),
注意:YourService应该是和你的proto文件里面定义的service 名字保持一致不然可能会报这种错误
http.ListenAndServe(":9090", mux) 这里地址是grpc-gateway提供服务的端口。
src目录如下
可以使用postman工具进行测试,本例测试结果如图:
可新建gw2 gw3 gw4 gw5 gw6 gw7 gw8 gw9文件夹将分别将带有service 目录的proto分别复制到各个文件里,
并新建对应的main*.go启动文件,注意标红地方修改,监听端口不要和其他的main.go冲突
如果有依赖的公用proto文件一并复制到文件夹里,然后按照上面的编译方式进行编译,然后为每个可执行的proto
引用文章https://blog.csdn.net/panshiqu/article/details/53788067内容如下:
Mac 下编译 Linux 和 Windows 64位可执行程序:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go12 |
Linux 下编译 Mac 和 Windows 64位可执行程序:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go12 |
Windows 下编译 Mac 和 Linux 64位可执行程序:
SET CGO_ENABLED=0 SET GOOS=darwin SET GOARCH=amd64 go build main.go
SET CGO_ENABLED=0 SET GOOS=linux SET GOARCH=amd64 go build main.go
|
GOOS:目标平台的操作系统(darwin、freebsd、linux、windows) GOARCH:目标平台的体系架构(386、amd64、arm) 交叉编译不支持 CGO 所以要禁用它
上面的命令编译 64 位可执行程序,你当然应该也会使用 386 编译 32 位可执行程序 很多博客都提到要先增加对其它平台的支持,但是我跳过那一步,上面所列的命令也都能成功,且得到我想要的结果,可见那一步应该是非必须的,或是我所使用的 Go 版本已默认支持所有平台。
可用于多proto,代理转发到不同的grpc-gateway端口
1.下载nginx
http://nginx.org/en/download.html,以nginx/Windows-1.15.8为例,
下载后解压,解压后如下
双击nginx.exe,访问localhost:80查看是否安装成功
进入conf文件修改nginx.conf
如下
通过postman工具测试图