欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

gRPC学习系列文章链接

  1. 在CentOS7部署和设置GO
  2. GO的gRPC开发环境准备
  3. 初试GO版gRPC开发
  4. 实战四类服务方法
  5. gRPC-Gateway实战
  6. gRPC-Gateway集成swagger

本篇概览

  • 本文《gRPC学习》系列的第五篇,gRPC常用于服务端之间的相互调用,如果想把服务暴露给前端,虽然动手修改服务端也能实现,但似乎增加了不少工作量,此时还可以选择gRPC-Gateway方式来快速将gRPC服务以http的方式暴露出来;
  • gRPC-Gateway原理如下图,借助grpc-gateway插件,可以基于proto文件生成反向代理(Reverse Proxy)的代码,这个反向代理运行起来后,对外提供RESTful服务,收到RESTful请求后通过gRPC调用原来的gRPC服务:

  • 本文展示了gRPC-Gateway环境搭建、开发、验证的整个过程,由以下步骤组成:
  1. 极速搭建gRPC-Gateway环境;
  2. 编写proto文件;
  3. 根据proto文件生成gRPC、gRPC-Gateway源码;
  4. 添加业务代码;
  5. 编译、运行、验证;

提前说明文件和目录

  • 本次实战在$GOPATH/src目录下新增文件夹helloworld,里面总共有以下内容:
[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
  • 准备工作完成,接下来正式开始开发;

前提条件

  • 本文的所有操作都没有用到root账号,而是前文创建的golang账号;
  • 请参照以下两篇文章将GO环境和gRPC环境搭建好:
  1. 在CentOS7部署和设置GO
  2. GO的gRPC开发环境准备

极速搭建gRPC-Gateway环境

  • 所谓的搭建gRPC-Gateway环境,其实是完成以下三件事:

  1. 在搭建环境时参考了一些网上的文章,结果遇到了各种问题一直没有成功(我当然不会认为文章有问题,必须认识到是自己能力不足的原因所致);
  2. 经过反复折腾后终于成功后,我把所有操作做成一个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
  1. 进入$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文件

  • 在$GOPATH/src目录下,新建文件夹helloworld,里面新建文件helloworld.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;
}
  • 上述proto文件有以下几处要注意的地方:
  1. 整个文件其实就是以 《初试GO版gRPC开发》一文中的helloworld.proto为基础,增加了两处内容;
  2. 增加的第一处,是用import关键词导入google/api/annotations.proto;
  3. 增加的第二处,是SayHello方法的声明处,增加了option配置,作用是配置SayHello方法对外暴露的RESTful接口的信息;
  4. 在使用protoc-gen-grpc-gateway的时候,上述两处配置会被识别到并生成对应的代码;

根据proto文件生成gRPC、gRPC-Gateway源码

  1. proto文件编写完成,接下来是生成gRPC、gRPC-Gateway的源码;
  2. 生成gRPC源码的命令咱们前面的文章中已经用过,如下:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=plugins=grpc:. \
helloworld.proto
  1. 执行完成后会在当前目录生成helloworld.pb.go文件;
  2. 执行生成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
  1. 执行完成后会在当前目录生成helloworld.pb.gw.go文件;
  2. 执行生成swagger文件的命令:
protoc -I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--swagger_out=logtostderr=true:. \
helloworld.proto
  1. 执行完成后会在当前目录生成helloworld.swagger.json文件;
  2. 至此,helloworld目录下一共有这些内容:
[golang@centos7 src]$ tree helloworld/
helloworld/
├── helloworld.pb.go
├── helloworld.pb.gw.go
├── helloworld.proto
└── helloworld.swagger.json 0 directories, 4 files
  1. 接下来开始编码,把运行整个服务所需的代码补全;
  2. 由于篇幅限制,本文暂不提及swagger相关的开发和验证,因此生成的helloworld.swagger.json文件本篇用不上,留待下一篇文章使用;

编写服务端代码server.go并启动

  1. 接下来编写服务端代码server.go,这个和《初试GO版gRPC开发》中的server.go内容一样;
  2. 在$GOPATH/src/helloworld目录下新建文件夹server,在此文件夹下新建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)
}
}
  1. 在server.go所在目录执行go run server.go,控制台提示如下:
[golang@centos7 server]$ go run server.go
2020/12/13 08:20:32 开始监听,等待远程调用...
  1. 此时gRPC的服务端已启动,可以响应远程调用,接下来开发反向代理(Reverse Proxy);

编写反向代理(Reverse Proxy)代码helloworld.gw.go并启动

  • 接下来编反向代理(Reverse Proxy)代码helloworld.gw.go;
  • 在$GOPATH/src/helloworld目录下新建文件夹gateway,在此文件夹下新建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())
}
}
  1. 第一处要注意的地方,是调用http.ListenAndServe监听9090端口,这是对外提供RESTful服务的端口;
  2. 第二处要注意的地方,是echoEndpoint配置了将外部RESTful请求转发到server.go提供gRPC服务的入口处;
  3. 第三处要注意的地方,是调用了自动生成代码中的RegisterGreeterHandlerFromEndpoint方法完成上下游调用的绑定;
  • 在hellowworld.gw.go所在目录执行go run hellowworld.gw.go,开始监听9090端口的web请求;

验证

  1. 在本机上验证,用curl发送请求:
curl \
-X POST \
-d '{"name": "will"}' \
192.168.133.203:9090/helloworld
  1. 收到响应如下,这是来自server.go的内容,可见http请求通过Reserve Proxy到达了真实的gRPC服务提供者,并顺利返回给调用方:
{"message":"Hello will"}
  1. 去看server.go的日志如下:
[golang@centos7 server]$ go run server.go
2020/12/19 14:16:47 开始监听,等待远程调用...
2020/12/19 14:24:35 Received: will
  1. 还可以在其他机器上通过postman验证,记得关闭服务所在机器的防火墙,请求和响应如下,注意按数字顺序设置和观察:

  • 至此,将gRPC服务快速暴露为RESTful服务的实战就完成了,如果您正在做这方面的尝试,希望本文能给您一些参考,接下来的文章咱们一起把swagger补全,让开发和联调更加高效;

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...

https://github.com/zq2599/blog_demos

gRPC学习之五:gRPC-Gateway实战的更多相关文章

  1. Golang gRPC学习(03): grpc官方示例程序route_guide简析

    代码主要来源于grpc的官方examples代码: route_guide https://github.com/grpc/grpc-go/tree/master/examples/route_gui ...

  2. gRPC学习之四:实战四类服务方法

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  3. gRPC学习之一:在CentOS7部署和设置GO

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  4. gRPC学习之二:GO的gRPC开发环境准备

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos gRPC学习系列文章链接 在CentOS7部署和设置G ...

  5. gRPC学习之三:初试GO版gRPC开发

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  6. Spring Boot 2+gRPC 学习系列1:搭建Spring Boot 2+gRPC本地项目

    Spring Boot 2+gRPC 学习系列1:搭建Spring Boot 2+gRPC本地项目 https://blog.csdn.net/alinyua/article/details/8303 ...

  7. Spring Cloud Gateway实战之五:内置filter

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. gRPC学习

    概述 gRPC 一开始由 google 开发,是一款语言中立.平台中立.开源的远程过程调用(RPC)系统. 在 gRPC 里客户端应用可以像调用本地对象一样直接调用另一台不同的机器上服务端应用的方法, ...

  9. Golang gRPC学习(04): Deadlines超时限制

    为什么要使用Deadlines 当我们使用gRPC时,gRPC库关系的是连接,序列化,反序列化和超时执行.Deadlines 允许gRPC客户端设置自己等待多长时间来完成rpc操作,直到出现这个错误 ...

随机推荐

  1. springcloud gateway(hystrix filter)

    参考 https://blog.csdn.net/forezp/article/details/83792388 1.依赖pom.xml <project xmlns="http:// ...

  2. XCTF(MISC) 图片隐写

    题目描述:菜猫给了菜狗一张图,说图下面什么都没有 1.给了个pdf,打开是这玩意 2.盲猜flag是图片后面,右键直接删除图片试试. 答案出来了.

  3. 淘宝的sign参数js逆向

    前言:现在网站都有很强的反爬机制,都是非常常见的是用js前端加密参数,所以不得不去分析和逆向js混淆后的代码 一. 打开天猫或淘宝,shift+ctrl+F12全局搜索sign参数. 这里发现很多地方 ...

  4. WPF教程十二:了解自定义控件的基础和自定义无外观控件

    这一篇本来想先写风格主题,主题切换.自定义配套的样式.但是最近加班.搬家.新租的房子打扫卫生,我家宝宝6月中旬要出生协调各种的事情,导致了最近精神状态不是很好,又没有看到我比较喜欢的主题风格去模仿的, ...

  5. python pil 图像加工处理

    from PIL import Imagefrom PIL import ImageEnhanceim=Image.open("d://aa.jpg","r") ...

  6. Java基础00-循环语句7

    1. for循环语句 1.1 循环结构 1.2 for循环语句的格式 执行流程图: 1.3 案例 (1)输出数据 (2)求和 (3)求偶数和 (4)水仙花 public static void mai ...

  7. [刘阳Java]_Spring IOC程序代码如何编写_第3讲

    第2讲我们介绍了Spring IOC的基本原理,这篇文章告诉大家Spring IOC程序代码是如何编写的,从而可以更好的理解IOC和DI的概念(所有的Java类的初始化工作扔给Spring框架,一个J ...

  8. 【有奖互动】HMS Core. Sparkle游戏应用创新沙龙,诚邀您参与

    活动简介 随着互联网基础设施的完善和"宅经济"效应凸显,游戏行业逆势上扬,迎来巨大消费市场.同时,用户需求愈加多样化,如何进一步创新和技术升级.提升核心竞争力已成为游戏开发与运营的 ...

  9. Linux服务器相关性能的命令

    Linux服务器相关性能的命令 一.查看服务器性能信息的相关命令 1.cpu信息查看 cpu分为物理cpu和逻辑cpu 物理cpu:实际物理服务器插槽上cpu的个数,可以通过physical id不重 ...

  10. 测试笔记01-Git

    Git工具 Git 一个分布式版本管理工具, 学习资料: https://www.liaoxuefeng.com/wiki/896043488029600/1317161920364578 其中:解决 ...