gRPC 如何搭配 Swagger 使用

本文将介绍如何将 gRPC 和 Swagger 结合使用,以便更有效地开发和测试接口。

用 Apifox,节省研发团队的每一分钟

gRPC 如何搭配 Swagger 使用

免费使用 Apifox

相关推荐

最新文章

API

一体化协作平台

API 设计

API 文档

API 调试

自动化测试

API Mock

API Hub

立即体验 Apifox
目录

什么是 gRPC?

gRPC 是一个由谷歌开发的现代开源高性能 RPC 远程过程调用( Remote Procedure Calls)框架,具备良好的兼容性,可在多个开发环境下运行。

它采用了领先的 HTTP/2 底层架构设计作为底层传输协议,能够在大规模数据传输场景(例如视频流传输)和大量服务相互调用的微服务架构场景下大展身手。

gRPC 自然也包含了许多 HTTP/2 的优点:

  • 数据传输二进制分帧
  • 多路复用
  • 服务端推送
  • 头部压缩

Swagger 是什么?

Swagger 是一个包含完整规范和框架的工具集,用于帮助开发者生成符合 RESTful 风格的 API 文档。业内又把符合 REST API 描述格式标准的规范称之为 OpenAPI。

Swagger 规范在 3 以后的版本名称变更为 OpenAPI 3.x。

OpenAPI 是连接 Swagger工具集和 RESTful API 设计风格的纽带,使三者形成了一个生态。OpenAPI 规范标准化了 RESTful API 的文档表示; Swagger 工具简化了遵循该规范的 API 文档产出流程。

Swagger 的总体目标是通过 API 定义驱动文档和代码的自动生成,使服务端实现、接口文档及客户端 SDK 能够保持高度一致和同步更新,以提高前后端的开发效率和协作效果。

如何将 gRPC 接口文档转换为 Swagger 规范

先决条件

gRPC 接口的数据交换方式采用轻量化的 Protobuf 序列化协议,使得它能够在资源受限场景提供更快的数据处理速度,因此它依赖于 protocol buffer 文件提供服务。

下文中将以 Go 语言为例,演示如何将 .proto 文件编译成 .go 文件,然后再输出符合 Swagger 规范的格式。 根据不同需要,会使用到不同的命令行文件,我们需要大致如下几个命令行文件。

工具介绍
protobufprotocol buffer 编译所需的命令行
protoc-gen-go从 proto 文件,生成 .go 文件
protoc-gen-go-grpc从 proto 文件,生成 GRPC 相关的 .go 文件
protoc-gen-grpc-gateway从 proto 文件,生成 grpc-gateway 相关的 .go 文件
protoc-gen-openapiv2从 proto 文件,生成 swagger 界面所需的参数文件

除了安装上述命令行,我们还需要根据需要,运行至少4种不同命令来编译 *.proto 文件,非常晦涩难懂。

安装

go get github.com/rookie-ninja/rk-boot
go get github.com/rookie-ninja/rk-grpc

快速开始

1、创建 api/v1/greeter.proto

syntax = "proto3";

package api.v1;

option go_package = "api/v1/greeter";

service Greeter {
  rpc Greeter (GreeterRequest) returns (GreeterResponse) {}
}

message GreeterRequest {
  string name = 1;
}

message GreeterResponse {
  string message = 1;
}

2、创建 api/v1/gw_mapping.yaml

type: google.api.Service
config_version: 3

# Please refer google.api.Http in https: //github.com/googleapis/googleapis/blob/master/google/api/http.proto file for details.
http:
  rules:
    - selector: api.v1.Greeter.Greeter
      get: /api/v1/greeter

3、创建 buf.yaml

version: v1beta1
name: github.com/rk-dev/rk-demo
build:
  roots:
    - api

4、创建 buf.gen.yaml

version: v1beta1
plugins:
  # protoc-gen-go needs to be installed, generate go files based on proto files
  - name: go
    out: api/gen
    opt:
     - paths=source_relative
  # protoc-gen-go-grpc needs to be installed, generate grpc go files based on proto files
  - name: go-grpc
    out: api/gen
    opt:
      - paths=source_relative
      - require_unimplemented_servers=false
  # protoc-gen-grpc-gateway needs to be installed, generate grpc-gateway go files based on proto files
  - name: grpc-gateway
    out: api/gen
    opt:
      - paths=source_relative
      - grpc_api_configuration=api/v1/gw_mapping.yaml
  # protoc-gen-openapiv2 needs to be installed, generate swagger config files based on proto files
  - name: openapiv2
    out: api/gen
    opt:
      - grpc_api_configuration=api/v1/gw_mapping.yaml

5、编译 proto file

$ buf generate
如下的文件会被创建。
$ tree api/gen 
api/gen
└── v1
    ├── greeter.pb.go
    ├── greeter.pb.gw.go
    ├── greeter.swagger.json
    └── greeter_grpc.pb.go

1 directory, 4 files

6、创建 boot.yaml

grpc:
  - name: greeter                   # Name of grpc entry
    port: 8080                      # Port of grpc entry
    enabled: true                   # Enable grpc entry
    sw:
      enabled: true                 # Enable swagger
      jsonPath: "api/gen/v1"        # Provide swagger config file path

7、创建 main.go

package main

import (
    "context"
    "fmt"
    "github.com/rookie-ninja/rk-boot"
    "github.com/rookie-ninja/rk-grpc/boot"
    "github.com/rookie-ninja/rk-demo/api/gen/v1"
    "google.golang.org/grpc"
)

// Application entrance.
func main() {
    // Create a new boot instance.
    boot := rkboot.NewBoot()

    //  ******   //  Register GRPC & Gateway **   // *****  *

    // Get grpc entry with name
    grpcEntry := boot.GetEntry("greeter").(*rkgrpc.GrpcEntry)
    // Register grpc registration function
    grpcEntry.AddRegFuncGrpc(registerGreeter)
    // Register grpc-gateway registration function
    grpcEntry.AddRegFuncGw(greeter.RegisterGreeterHandlerFromEndpoint)

    // Bootstrap
    boot.Bootstrap(context.Background())

    // Wait for shutdown sig
    boot.WaitForShutdownSig(context.Background())
}

// Implementation of [type GrpcRegFunc func(server *grpc.Server)]
func registerGreeter(server *grpc.Server) {
    greeter.RegisterGreeterServer(server, &GreeterServer{})
}

// Implementation of grpc service defined in proto file
type GreeterServer struct{}

func (server *GreeterServer) Greeter(ctx context.Context, request *greeter.GreeterRequest) (*greeter.GreeterResponse, error) {
    return &greeter.GreeterResponse{
        Message: fmt.Sprintf("Hello %s!", request.Name),
    }, nil
}

8、文件夹结构

$ tree
.
├── api
│   ├── gen
│   │   └── v1
│   │       ├── greeter.pb.go
│   │       ├── greeter.pb.gw.go
│   │       ├── greeter.swagger.json
│   │       └── greeter_grpc.pb.go
│   └── v1
│       ├── greeter.proto
│       └── gw_mapping.yaml
├── boot.yaml
├── buf.gen.yaml
├── buf.yaml
├── go.mod
├── go.sum
└── main.go

4 directories, 12 files

9、验证

访问 Swagger:http://localhost:8080/sw

无需复杂流程,使用 Apifox 管理 gRPC 接口

使用 Apifox 即可便捷的管理 gRPC 接口,且支持中文显示,无需复杂配置,非常方便上手~

Apifox 支持基于 .proto 文件的 gRPC 调试,包括一元调用和流式调用。在创建项目时「选择 gRPC 项目」-->「导入 .proto 文件」,无需写代码即可直接调用 gRPC 接口。

创建 gRPC

在调试 gRPC 接口之前,也需要先导入作为 API 定义的 .proto 文件。如果一个 .proto 文件依赖于其他 .proto 文件,那么需要手动添加依赖关系目录。

添加 Proto

一元调用

只需要在地址栏填写 URL 后点击「调用」按钮,即可发起一元调用。

一元调用

流式调用

流式调用包含服务端流、客户端流、双向流

在发起调用之后,你可以在 Message 标签下撰写消息并发送。Apifox 提供了一个时间线视图,按照时间顺序集中展示调用状态、发送的消息、收到的消息。点击消息之后,可以非常方便地查看消息的详情。

流式调用

关于 Apifox

  • 集成了API 文档、API 调试、API Mock、API 自动化测试 API 一体化协作平台
  • 拥有更先进的 API 设计/开发/测试工具
  • Apifox = Postman + Swagger + Mock + JMeter
Apifox

知识扩展: