通过关键词采集文章采集api(概览极速搭建gRPC-Gateway环境(-gen) )
优采云 发布时间: 2022-03-25 10:01通过关键词采集文章采集api(概览极速搭建gRPC-Gateway环境(-gen)
)
欢迎来到我的 GitHub
内容:所有原创文章分类汇总,支持源码,涉及Java、Docker、Kubernetes、DevOPS等;
本文概述
快速搭建gRPC-Gateway环境;编写原型文件;根据proto文件生成gRPC、gRPC-Gateway源码;添加业务代码;编译、运行、验证;提前解释文件和目录
[golang@centos7 src]$ tree helloworld/
helloworld/
├── gateway
│ └── helloworld.gw.go
├── helloworld.pb.go
├── helloworld.pb.gw.go
├── helloworld.proto
├── helloworld.swagger.json
└── server
└── server.go
先决条件《gRPC学习一:CentOS7部署与设置GO》《gRPC学习二:GO的gRPC开发环境准备》快速搭建gRPC-Gateway环境
搭建环境的时候参考了网上的一些文章,但是遇到了各种问题,一直没有成功(我当然不觉得文章有问题,一定要意识到那是我能力不足的原因经过反复折腾,终于成功了,我把所有的操作都做成了一个shell脚本,执行如下命令,完成了上图中的所有操作:
curl -o install-grpc-gateway.sh \
https://raw.githubusercontent.com/zq2599/blog_demos/master/files/install-grpc-gateway.sh \
&& chmod a+x ./install-grpc-gateway.sh \
&& ./install-grpc-gateway.sh
进入$GOPATH/bin目录,可以看到两个新文件,protoc-gen-grpc-gateway和protoc-gen-swagger:
[golang@centos7 ~]$ cd $GOPATH/bin
[golang@centos7 bin]$ ls -al
总用量 26708
drwxrwxr-x. 2 golang golang 98 12月 19 08:59 .
drwxrwxr-x. 5 golang golang 39 12月 19 08:21 ..
-rwxr-x---. 1 golang golang 5253272 12月 19 08:20 protoc
-rwxrwxr-x. 1 golang golang 8461147 12月 19 08:21 protoc-gen-go
-rwxrwxr-x. 1 golang golang 6717463 12月 19 08:59 protoc-gen-grpc-gateway
-rwxrwxr-x. 1 golang golang 6908535 12月 19 08:59 protoc-gen-swagger
写一个proto文件
// 协议类型
syntax = "proto3";
// 包名
package helloworld;
import "google/api/annotations.proto";
// 定义的服务名
service Greeter {
// 具体的远程服务方法
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api.http) = {
post: "/helloworld"
body: "*"
};
}
}
// SayHello方法的入参,只有一个字符串字段
message HelloRequest {
string name = 1;
}
// SayHello方法的返回值,只有一个字符串字段
message HelloReply {
string message = 1;
}
整个文件其实是基于《gRPC学习之三:gRPC开发的初始GO版本》一文中的helloworld.proto,增加了两处;第一个添加是使用 import关键词 google/api/annotations.proto 导入;第二个是SayHello方法的声明,增加了选项配置,用于配置SayHello方法暴露的RESTful接口的信息;使用 protoc-gen-grpc-gateway 时,会识别以上两种配置并生成对应的代码;根据proto文件生成gRPC和gRPC-Gateway源代码proto文件,下一步生成gRPC和gRPC-Gateway源代码;生成gRPC源码的命令就在前面文章已经用过了,如下:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=plugins=grpc:. \
helloworld.proto
执行完成后,会在当前目录生成helloworld.pb.go文件;执行命令生成gRPC-Gateway源码:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--grpc-gateway_out=logtostderr=true:. \
helloworld.proto
执行完成后,会在当前目录生成helloworld.pb.gw.go文件;执行命令生成swagger文件:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--swagger_out=logtostderr=true:. \
helloworld.proto
执行完成后,会在当前目录生成helloworld.swagger.json文件;到目前为止,helloworld目录下有这些内容:
[golang@centos7 src]$ tree helloworld/
helloworld/
├── helloworld.pb.go
├── helloworld.pb.gw.go
├── helloworld.proto
└── helloworld.swagger.json
0 directories, 4 files
接下来,开始编码,完成运行整个服务所需的代码;限于篇幅,本文不提swagger相关的开发和验证,所以本文不使用生成的helloworld.swagger.json文件。留待下篇文章文章使用;编写服务端代码server.go,开始下一步编写服务端代码server.go,与《gRPC开发初步GO版》中server.go的内容相同;在 $GOPATH 目录下新建一个 server.go 文件夹,在 /src/helloworld 目录下新建 server.go 。内容如下,已添加详细评论:
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "helloworld"
)
const (
port = ":50051"
)
// 定义结构体,在调用注册api的时候作为入参,
// 该结构体会带上SayHello方法,里面是业务代码
// 这样远程调用时就执行了业务代码了
type server struct {
// pb.go中自动生成的,是个空结构体
pb.UnimplementedGreeterServer
}
// 业务代码在此写,客户端远程调用SayHello时,
// 会执行这里的代码
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
// 打印请求参数
log.Printf("Received: %v", in.GetName())
// 实例化结构体HelloReply,作为返回值
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
}
func main() {
// 要*敏*感*词*的协议和端口
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// 实例化gRPC server结构体
s := grpc.NewServer()
// 服务注册
pb.RegisterGreeterServer(s, &server{})
log.Println("开始*敏*感*词*,等待远程调用...")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
在server.go所在目录执行go run server.go,控制台提示如下:
[golang@centos7 server]$ go run server.go
2020/12/13 08:20:32 开始*敏*感*词*,等待远程调用...
此时gRPC服务器已经启动,可以响应远程调用了。接下来,开发反向代理(Reverse Proxy);编写反向代理(Reverse Proxy)代码helloworld.gw.go并启动它
package main
import (
"flag"
"fmt"
"net/http"
gw "helloworld"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
var (
echoEndpoint = flag.String("echo_endpoint", "localhost:50051", "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() {
if err := run(); err != nil {
fmt.Print(err.Error())
}
}
首先要注意的是调用http.ListenAndServe*敏*感*词*9090端口,该端口是对外提供RESTful服务的端口;第二点需要注意的是,echoEndpoint 被配置为将外部 RESTful 请求转发到 server.go 提供 gRPC 服务的入口点;第三点需要注意的是调用自动生成代码中的RegisterGreeterHandlerFromEndpoint方法,完成上下游调用的绑定;在本机进行验证,使用curl发送请求:
curl \
-X POST \
-d '{"name": "will"}' \
192.168.133.203:9090/helloworld
收到的响应如下,是来自server.go的内容。可以看到,http请求通过Reserve Proxy到达真正的gRPC服务提供者,并成功返回给调用者:
{"message":"Hello will"}
查看server.go的日志如下:
[golang@centos7 server]$ go run server.go
2020/12/19 14:16:47 开始*敏*感*词*,等待远程调用...
2020/12/19 14:24:35 Received: will
您也可以在其他机器上通过邮递员身份验证。记得关闭服务所在机器的防火墙。请求和响应如下,注意按数字顺序设置观察: