gRPC学习之六:gRPC-Gateway集成swagger

蜂信物联FastBee平台https://gitee.com/beecue/fastbee

阿里资料开源项目https://gitee.com/vip204888

百度低代码前端框架https://gitee.com/baidu/amis

OpenHarmony开源项目https://gitcode.com/openharmony

仓颉编程语言开放项目https://gitcode.com/Cangjie

  • 这个git项目中有多个文件夹,本章的应用在go-source文件夹下,如下图红框所示:

在这里插入图片描述

  • go-source里面有多个子文件夹,本篇的源码在swaggerdemo中,如下图红框:

在这里插入图片描述

提前预览关键知识点

在gRPC-Gateway集成swagger服务的过程并不简单,咱们将其中的重点提前看一下,做到心里有数:

  1. 为了简化实战过程,gRPC-Gateway暴露的服务并未使用https,而是http,但是swagger-ui提供的调用服务却是https的,因此要在proto文件中指定swagger以http调用服务,指定的时候会用到文件protoc-gen-swagger/options/annotations.proto,因此需要找到这个文件对应的包,放在合适的位置;

  2. swaggerdemo.swagger.json:这是swagger-ui要用的json文件,依据此文件,swagger才能正确的展现出gRPC-Gateway暴露的服务和参数定义,可以在页面上发起请求,此文件由插件protoc-gen-swagger生成,该插件是上一篇《gRPC-Gateway实战》中安装好的;

  3. 在gRPC-Gateway的代码中集成swagger-ui的代码:swagger-ui的代码由多个png、html、js文件组成,需要用工具go-bindata转换成go源码并放入合适的位置,流程如下图:

在这里插入图片描述

  1. 要将swaggerdemo.swagger.json文件通过web暴露出来,需要工具go-bindata-assetfs;

  2. 使用swagger的方式:打开swagger-ui页面后,将swaggerdemo.swagger.json输入给swagger-ui页面,令其解析后,生成对应的在线接口服务;

前提条件

提前展示文件结构

  • 本次实战涉及到多个文件,在此先将最终的文件内容全部展示出来,以便您在开发过程中作为参考,所有内容都在$GOPATH/src/swaggerdemo目录下:

[golang@centos7 src]$ tree swaggerdemo/

swaggerdemo/

├── gateway

│ └── gateway.go

├── pkg

│ └── ui

│ └── data

│ └── swagger

│ └── datafile.go

├── server

│ └── server.go

├── swaggerdemo.pb.go

├── swaggerdemo.pb.gw.go

├── swaggerdemo.proto

├── swaggerdemo.swagger.json

└── third_party

└── swagger-ui

├── favicon-16x16.png

├── favicon-32x32.png

├── index.html

├── oauth2-redirect.html

├── swagger-ui-bundle.js

├── swagger-ui-bundle.js.map

├── swagger-ui.css

├── swagger-ui.css.map

├── swagger-ui-es-bundle-core.js

├── swagger-ui-es-bundle-core.js.map

├── swagger-ui-es-bundle.js

├── swagger-ui-es-bundle.js.map

├── swagger-ui.js

├── swagger-ui.js.map

├── swagger-ui-standalone-preset.js

└── swagger-ui-standalone-preset.js.map

8 directories, 23 files

新建工程文件夹

  • 本次实战与前面几篇文章的代码没有关系,而是一个全新的工程,请在$GOPATH/src下面新建名为swaggerdemo的文件夹;

安装必要的go包

  1. 安装git,执行命令sudo yum install -y git unzip

  2. 工程中会用到几个包,接下来逐个安装;

  3. go-bindata用来将swagger-ui的源码转为GO代码:

go get -u github.com/jteeuwen/go-bindata/…

  1. go-bindata-assetfs在应用启动后,对外提供文件服务,这样可以通过web访问swagger的json文件:

go get -u github.com/elazarl/go-bindata-assetfs/…

  1. glog是常用的日志工具:

go get -u github.com/golang/glog

编写proto文件

  • 进入目录$GOPATH/src/swaggerdemo,新建swaggerdemo.proto,内容如下,有几处要注意的地方稍后会说明:

// 协议类型

syntax = “proto3”;

// 包名

package swaggerdemo;

import “google/api/annotations.proto”;

import “protoc-gen-swagger/options/annotations.proto”;

// 定义swagger内容

option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {

info: {

title: “grpc gateway helloworld sample”;

version: “1.0”;

};

schemes: HTTP;

};

// 定义的服务名

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;

}

  • 文件swaggerdemo.proto和 《gRPC-Gateway实战》一文中的proto文件大部分是一致的,不同之处在于增加了swagger的配置,这个配置的作用是让swagger把远程调用配置成http,如果没有这些配置,swagger默认的远程调用就是https的,本文的gRPC-Gateway提供的是http服务,所以要加上这些配置,在上述swaggerdemo.proto的内容中,具体的配置有以下两处:
  1. 用import关键词导入protoc-gen-swagger/options/annotations.proto

  2. 下面这段就是swagger的配置了,重点是schemes,里面只有HTTP:

option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {

info: {

title: “grpc gateway helloworld sample”;

version: “1.0”;

};

schemes: HTTP;

};

  • 还要把swaggerdemo.proto中提到的protoc-gen-swagger/options/annotations.proto文件放在合适的地方,以便使用swaggerdemo.proto的时候能找到此annotations.proto文件,执行以下命令:

cd $GOPATH/src

cp -r ./github.com/grpc-ecosystem/grpc-gateway/protoc-gen-swagger ./

  • 上述命令中的protoc-gen-swagger文件夹,是在前文的操作中下载好的;

生成gRPC、gRPC-Gateway所需的go源码

  • 生成gRPC、gRPC-Gateway所需的go源码,这样的操作在前面已经做过,这里用swaggerdemo.proto再做一次,先进入目录$GOPATH/src/swaggerdemo

  • 执行以下命令,生成gRPC所需源码:

protoc -I. \

-I$GOPATH/src \

-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

–go_out=plugins=grpc:. \

swaggerdemo.proto

  • 执行以下命令,生成gRPC-Gateway所需源码:

protoc -I. \

-I$GOPATH/src \

-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

–grpc-gateway_out=logtostderr=true:. \

swaggerdemo.proto

生成swagger所需的json文件

  • 还是在目录$GOPATH/src/swaggerdemo,执行以下命令,生成swagger所需json:

protoc -I. \

-I$GOPATH/src \

-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \

–swagger_out=logtostderr=true:. \

swaggerdemo.proto

  • 此时的$GOPATH/src/swaggerdemo目录下新增以下三个文件:
  1. swaggerdemo.pb.go:gRPC所需的go文件

  2. swaggerdemo.pb.gw.go:gRPC-Gateway所需的go文件

  3. swaggerdemo.swagger.json:swagger-ui要用的json文件,依据此文件,swagger展现的页面中会有gRPC-Gateway暴露的服务和参数定义,可以在页面上发起请求

生成swagger-ui的go文件

  • 要想在服务中提供swagger的web页面,需要将swagger-ui的源码转为go文件,步骤如下:
  1. 接下来的命令会从Github下载swagger-ui的源码,这个文件本该从swagger官方下载,但是我这里尝试多次后发现,下载得到的zip包很容器出现文件损坏而无法解压缩的情况,于是我将此文件放在了自己的Github上,下面的操作也是从我自己的Github下载的,但实际上此文件和swagger官方的并无区别;

  2. 进入目录$GOPATH/src/swaggerdemo,执行以下命令下载swagger-ui源码,并放入指定位置:

wget https://raw.githubusercontent.com/zq2599/blog_download_files/master/files/swagger-ui.zip -O swagger-ui.zip \

&& unzip swagger-ui.zip \

&& mkdir -p $GOPATH/src/swaggerdemo/third_party/ \

&& mv ./swagger-ui-3.38.0/dist $GOPATH/src/swaggerdemo/third_party/ \

&& mv $GOPATH/src/swaggerdemo/third_party/dist $GOPATH/src/swaggerdemo/third_party/swagger-ui \

&& rm -f ./swagger-ui.zip \

&& rm -rf ./swagger-ui-3.38.0

  1. 执行以下命令新建文件夹,该文件夹用来存放稍后生成的swagger-ui的go源码:

mkdir -p $GOPATH/src/swaggerdemo/pkg/ui/data/swagger

  1. 执行以下命令,将swagger-ui源码转为datafile.go文件:

cd $GOPATH/src/swaggerdemo/

go-bindata --nocompress -pkg swagger -o pkg/ui/data/swagger/datafile.go third_party/swagger-ui/…

  1. 这时候在$GOPATH/src/swaggerdemo/pkg/ui/data/swagger目录下生成了文件datafile.go
  • 所有文件和材料已经准备完成,开始编码;

编写gRPC的服务端代码

  • 按照swaggerdemo.proto的配置新建一个gRPC服务,步骤如下:
  1. 新建文件夹$GOPATH/src/swaggerdemo/server;

  2. 在新建的server文件夹下新增文件server.go,内容如下,只是个普通的gRPC服务而已:

package main

import (

“context”

“log”

“net”

“google.golang.org/grpc”

pb “swaggerdemo”

)

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)

}

最后

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?

掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。

rver) 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)

}

最后

面试是跳槽涨薪最直接有效的方式,马上金九银十来了,各位做好面试造飞机,工作拧螺丝的准备了吗?

掌握了这些知识点,面试时在候选人中又可以夺目不少,暴击9999点。机会都是留给有准备的人,只有充足的准备,才可能让自己可以在候选人中脱颖而出。

[外链图片转存中…(img-elM9upUI-1725137994773)]

[外链图片转存中…(img-9vP9AXbI-1725137994774)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值