grpc服务集成RESFful JSON API grpc-gateway和swagger-ui界面

1 篇文章 0 订阅
1 篇文章 0 订阅


阅读时间:5min左右

本文目的:

说明如何使用grpc-gateway(下图红色部分)反向代理插件将RESTful JSON API转换为gRPC,并使用swagger ui提供rest api界面。

grpc-gateway

集成步骤:

上图所示,由下往上

一、HelloWorld gRPC服务

首先先有一个gRPC服务,我们这个服务使用java实现,并使用maven进行管理,具体细节可查看git库:

1.安装所需软件版本
安装包版本备注
go1.13.1(必须,安装包链接:https://golang.org/dl/)
protobuf3.6.1(必须,https://github.com/protocolbuffers/protobuf/releases)
java1.8.0(可选,原因是grpc服务是由java编写)
maven3.5.4(可选)

安装步骤不再展开,我相信你们可以安装好的。

2.编写Hello world gRPC服务
1)创建一个maven工程

最后的项目结构如下
(刚创建的项目没有代码文件,由接下来的步骤创建)

.
├── cmd
│   ├── helloworld.pb.go
│   ├── helloworld.pb.gw.go
│   ├── helloworld.swagger.go
│   └── swagger
│       └── ui
│           └── data
│               └── datafile.go
├── helloworld.swagger.json
├── java-grpc-swagger.iml
├── pom.xml
├── proxy
├── proxy.go
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── tuputech
│   │   │           └── grpc
│   │   │               ├── HelloWorldClient.java
│   │   │               └── HelloWorldServer.java
│   │   ├── proto
│   │   │   └── helloworld.proto
│   │   └── resources
│   │       └── swagger-ui
│   │           ├── favicon-16x16.png
│   │           ├── favicon-32x32.png
│   │           ├── index.html
│   │           ├── oauth2-redirect.html
│   │           ├── swagger-ui-bundle.js
│   │           ├── swagger-ui-bundle.js.map
│   │           ├── swagger-ui-standalone-preset.js
│   │           ├── swagger-ui-standalone-preset.js.map
│   │           ├── swagger-ui.css
│   │           ├── swagger-ui.css.map
│   │           ├── swagger-ui.js
│   │           └── swagger-ui.js.map
│   └── test
│       └── java

直接拷贝gRPC github上的代码,进行运行即可

2)拷贝gRPC的proto的文件

helloworld.proto

https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto/helloworld.proto
3)拷贝gRPC的server和client的java代码

HelloWorldServer.java和HelloWorldClient.java

https://github.com/grpc/grpc-java/tree/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java

https://github.com/grpc/grpc-java/tree/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java

4)编译直接运行

运行时日志

Sep 17, 2018 8:57:00 PM com.tuputech.grpc.HelloWorldServer start
信息: Server started, listening on 50051

二、RESTful JSON gRPC-gateway

1.安装gprc-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
2.修改helloworld.proto文件

添加gateway的选项

import "google/api/annotations.proto"

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      post: "/v1/hello"
      body: "*"
    };
  }
}
3.生成grpc golang stub类文件
 protoc -I/Users/stephen/Documents/develop/java-grpc-swagger/src/main/proto/ -I. \
  -I$GOPATH/src \
  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
  --go_out=plugins=grpc:. \
  /Users/stephen/Documents/develop/java-grpc-swagger/src/main/proto/helloworld.proto

对应生成helloworld.pb.go文件

4.生成反向代理代码
  protoc -I/Users/stephen/Documents/develop/java-grpc-swagger/src/main/proto/ -I. \
  -I$GOPATH/src \
  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
  --plugin=protoc-gen-grpc=grpc_ruby_plugin \
  --grpc-gateway_out=logtostderr=true:. \
  /Users/stephen/Documents/develop/java-grpc-swagger/src/main/proto/helloworld.proto

对应生成helloworld.pb.gw.go

把以上生成的go文件移到cmd的文件夹下面

5.编写proxy.go
package main

import (
    "flag"
    "log"
    "net/http"

    "github.com/grpc-ecosystem/grpc-gateway/runtime"
    "golang.org/x/net/context"
    "google.golang.org/grpc"

    gw "../java-grpc-swagger/cmd"
)

var (
    greeterEndpoint = flag.String("helloworld_endpoint", "localhost:50051", "endpoint of Greeter gRPC Service")
)

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, *greeterEndpoint, opts)
    if err != nil {
        return err
    }

    log.Print("Greeter gRPC Server gateway start at port 8080...")
    http.ListenAndServe(":8080", mux)
    return nil
}

func main() {
    flag.Parse()

    if err := run(); err != nil {
        log.Fatal(err)
    }
}

编译生成可执行文件proxy

go build proxy.go
6.启动服务
1)启动grpc服务
Sep 18, 2018 10:51:35 AM com.tuputech.grpc.HelloWorldServer start
信息: Server started, listening on 50051
2)启动RESTful JSON API gateway
➜  java-grpc-swagger proxy
2018/09/18 10:27:57 Greeter gRPC Server gateway start at port 8080...

3)使用curl访问
➜  ~ curl -X POST "http://localhost:8080/v1/hello" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"name\": \"string\"}"
{"message":"Hello string"}%

三、集成swagger-ui

1.生成RESTful JSON API的Swagger说明
  protoc -I/Users/stephen/Documents/develop/java-grpc-swagger/src/main/proto/ -I. \
  -I$GOPATH/src \
  -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
  --swagger_out=logtostderr=true:. \
  /Users/stephen/Documents/develop/java-grpc-swagger/src/main/proto/helloworld.proto

对应生成helloworld.swagger.json文件。在cmd的目录下新建helloworld.swagger.go,定义常量为Swagger,常量值为helloworld.swagger.json内容

package helloworld

const (
        Swagger = `
        {
          "swagger": "2.0",
          "info": {
            "title": "helloworld.proto",
            "version": "version not set"
          },
          "schemes": [
            "http",
            "https"
          ],
          "consumes": [
            "application/json"
          ],
          "produces": [
            "application/json"
          ],
          "paths": {
            "/v1/hello": {
              "post": {
                "summary": "Sends a greeting",
                "operationId": "SayHello",
                "responses": {
                  "200": {
                    "description": "",
                    "schema": {
                      "$ref": "#/definitions/helloworldHelloReply"
                    }
                  }
                },
                "parameters": [
                  {
                    "name": "body",
                    "in": "body",
                    "required": true,
                    "schema": {
                      "$ref": "#/definitions/helloworldHelloRequest"
                    }
                  }
                ],
                "tags": [
                  "Greeter"
                ]
              }
            }
          },
          "definitions": {
            "helloworldHelloReply": {
              "type": "object",
              "properties": {
                "message": {
                  "type": "string"
                }
              },
              "title": "The response message containing the greetings"
            },
            "helloworldHelloRequest": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                }
              },
              "description": "The request message containing the user's name."
            }
          }
        }
        `
)
2.修改proxy.go代码

添加方法返回swagger.json的内容

func run() error {
    ctx := context.Background()
    ctx, cancel := context.WithCancel(ctx)
    defer cancel()

    mux := http.NewServeMux()
    mux.HandleFunc("/swagger.json", func(w http.ResponseWriter, req *http.Request) {
        io.Copy(w, strings.NewReader(gw.Swagger))
    })

    gwmux := runtime.NewServeMux()
    opts := []grpc.DialOption{grpc.WithInsecure()}
    err := gw.RegisterGreeterHandlerFromEndpoint(ctx, gwmux, *greeterEndpoint, opts)
    if err != nil {
        return err
    }

    log.Print("Greeter gRPC Server gateway start at port 8080...")
    http.ListenAndServe(":8080", mux)
    return nil
}

重新编译并运行proxy。使用浏览器访问http://localhost:8080/swagger.json,即可得到hello world RESful API的具体说明。

在这里插入图片描述
为了将API更直观显示出来,我们将swagger-ui安装到我们的gateway里面。

3.下载swagger github源码
git clone https://github.com/swagger-api/swagger-ui.git

将dist目录下的所有文件拷贝到项目目录resources/swagger-ui里面

修改swagger-ui/index.html,替换
http://petstore.swagger.io/v2/swagger.json
为"http://localhost:8080/swagger.json"

 const ui = SwaggerUIBundle({
        // url: "https://petstore.swagger.io/v2/swagger.json",
        url: "http://localhost:8080/swagger.json",

4.将swagger-ui文件编译成go的内置文件:
1)安装go-bindata工具
go get -u github.com/jteeuwen/go-bindata/...
2)制作成go的内置数据文件
go-bindata --nocompress -pkg swagger -o cmd/swagger/ui/data/datafile.go src/main/resources/swagger-ui/...
5.swagger-ui的文件服务器
1)elazarl/go-bindata-assetf将内置的数据文件对外提供http服务
go get github.com/elazarl/go-bindata-assetfs/...
2)修改proxy.go代码,添加swagger函数
3)重新编译proxy.go
go build proxy.go
4)重新启动gateway服务

使用浏览器查看swagger-ui

http://localhost:8080/swagger-ui

在这里插入图片描述

总结

本文至此,已完成grpc服务集成RESTful Json grpc-gateway反向代理和提供swagger-ui界面的配置。


参考
https://github.com/grpc-ecosystem/grpc-gateway
https://coreos.com/blog/grpc-protobufs-swagger.html
https://github.com/swagger-api/swagger-ui/tree/8062a9eca0dc9d037d2c4940c0a592b15b61bd21
https://www.cnblogs.com/lienhua34/p/6285829.html

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值