gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版

HarmonyOS学习 2021-11-25 18:26:07
java 面试 编程语言 后端开发

  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:

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

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)

}

// 实例化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)

}

}

  • 以上就是gRPC服务的代码,与前几篇文章中的差不多,就不赘述了;

 编写gRPC-Gateway服务端的代码

  • 开始编写gRPC-Gateway服务端代码,这是本文的重点所在,除了提供与前文一样的gRPC-Gateway服务,还提供了swagger的json文件服务,以及swagger的ui服务;

  • 新建文件夹$GOPATH/src/swaggerdemo/gateway;

  • 在新建的gateway文件夹下新增文件gateway.go,内容如下,有几处要注意的地方稍后会说明:

package main

import (

“github.com/elazarl/go-bindata-assetfs”

“log”

“net/http”

“path”

“strings”

“github.com/golang/glog”

“github.com/grpc-ecosystem/grpc-gateway/runtime”

“golang.org/x/net/context”

“google.golang.org/grpc”

swagger “swaggerdemo/pkg/ui/data/swagger”

gw “swaggerdemo”

)

func run() error {

ctx := context.Background()

ctx, cancel := context.WithCancel(ctx)

defer cancel()

gwmux, err := newGateway(ctx)

if err != nil {

panic(err)

}

mux := http.NewServeMux()

mux.Handle(“/”, gwmux)

mux.HandleFunc(“/swagger/”, serveSwaggerFile)

serveSwaggerUI(mux)

log.Println(“grpc-gateway listen on localhost:9090”)

return http.ListenAndServe(“:9090”, mux)

}

func newGateway(ctx context.Context) (http.Handler, error) {

opts := []grpc.DialOption{grpc.WithInsecure()}

gwmux := runtime.NewServeMux()

if err := gw.RegisterGreeterHandlerFromEndpoint(ctx, gwmux, “:50051”, opts); err != nil {

return nil, err

}

return gwmux, nil

}

func serveSwaggerFile(w http.ResponseWriter, r *http.Request) {

log.Println(“start serveSwaggerFile”)

if !strings.HasSuffix(r.URL.Path, “swagger.json”) {

log.Printf(“Not Found: %s”, r.URL.Path)

http.NotFound(w, r)

return

}

p := strings.TrimPrefix(r.URL.Path, “/swagger/”)

p = path.Join(“…/”, p)

log.Printf(“Serving swagger-file: %s”, p)

http.ServeFile(w, r, p)

}

func serveSwaggerUI(mux *http.ServeMux) {

fileServer := http.FileServer(&assetfs.AssetFS{

Asset: swagger.Asset,

AssetDir: swagger.AssetDir,

Prefix: “third_party/swagger-ui”,

})

prefix := “/swagger-ui/”

mux.Handle(prefix, http.StripPrefix(prefix, fileServer))

}

func main() {

defer glog.Flush()

if err := run(); err != nil {

glog.Fatal(err)

}

}

  • 对于这个gateway.go文件,有以下几处需要重点注意:
  1. 外部的RESTful请求转发到server.go的功能,被封装到newGateway方法中;

  2. 请求URL中如果含有/swagger,就交给serveSwaggerFile方法处理,这里面的逻辑是将文件$GOPATH/src/swaggerdemo/swaggerdemo.swagger.json返回给请求方;

  3. 重点关注serveSwaggerUI方法,经过该方法的处理后,如果请求URL中含有/swagger-ui,就会交给前面生成的datafile.go处理,也就是打开了swagger-ui的页面;

  • 至此,开发工作已经完成,可以开始验证了;

 验证

  1. 进入目录$GOPATH/src/swaggerdemo/server,执行go run server.go启动gRPC服务;

  2. 进入目录$GOPATH/src/swaggerdemo/gateway,执行go run gateway.go启动gRPC-Gateway服务;

  3. 确保服务所在机器的防火墙已经关闭;

  4. 我这边服务器IP地址是http://192.168.133.204/,因此浏览器访问: http://192.168.133.204:9090/swagger/swaggerdemo.swagger.json ,即可看到swagger.json的内容,如下图:

gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版_Java

  1. 访问swagger-ui页面,地址是: http://192.168.133.204:9090/swagger-ui/ ,如下图,可见swagger-ui功能正常:

gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版_Java_02

  1. 此时的swagger-ui页面并未展示gRPC-Gateway的接口内容,需要将http://192.168.133.204:9090/swagger/swaggerdemo.swagger.json填入下图红框1中,再点击红框2的按钮,即可正常展示,红框3就是gRPC-Gateway对外暴露的服务:

gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版_后端开发_03

最后总结

ActiveMQ+Kafka+RabbitMQ学习笔记PDF

gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版_面试_04

  • RabbitMQ实战指南

gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版_面试_05

  • 手写RocketMQ笔记

gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版_Java_06

  • 手写“Kafka笔记”

gRPC学习之六:gRPC-Gateway集成swagger,java语言程序设计与数据结构进阶版_Java_07

关于分布式,限流+缓存+缓存,这三大技术(包含:ZooKeeper+Nginx+MongoDB+memcached+Redis+ActiveMQ+Kafka+RabbitMQ)等等。这些相关的面试也好,还有手写以及学习的笔记PDF,都是啃透分布式技术必不可少的宝藏。以上的每一个专题每一个小分类都有相关的介绍,并且小编也已经将其整理成PDF啦

本文已被 CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

版权声明
本文为[HarmonyOS学习]所创,转载请带上原文链接,感谢
https://blog.51cto.com/u_15438507/4690457

  1. Java经典面试题详解,突围金九银十面试季(附详细答案,mysql集群架构部署方案
  2. java整理,java高级特性编程及实战第一章
  3. java教程——反射,mongodb下载教程
  4. Java岗大厂面试百日冲刺 - 日积月累,每日三题【Day12,zookeeper原理作用
  5. Java后端互联网500道中高级面试题(含答案),linux钩子技术
  6. java8 Stream API及常用方法,java初级程序员面试
  7. java-集合-Map(双列)——迪迦重制版,2021Java开发社招面试解答之性能优化
  8. Flink处理函数实战之二:ProcessFunction类,java线程面试题目
  9. flex 布局详解,【Java面试题
  10. Linux basic command learning
  11. Why did docker lose to kubernetes? Docker employee readme!
  12. MySQL安装
  13. Elastic Search Aggregate Learning five: Problem Analysis of Uncertainty of sequencing results, Alibaba Java Performance Tuning Practical
  14. Installing, configuring, starting and accessing rabbitmq under Linux
  15. Oracle SQL injection summary
  16. Installation MySQL
  17. L'exposition à la photo d'essai sur la route i7 du nouveau vaisseau amiral de BMW Pure Electric a également été comparée à celle de Xiaopeng p7.
  18. spring JTA 关于异常处理的时机问题
  19. Le problème du temps de traitement des exceptions dans la JTA printanière
  20. Flink Handling Function Real War II: processfunction class, Java thread interview subject
  21. Oracle SQL injection summary
  22. [Java data structure] you must master the classic example of linked list interview (with super detailed illustration and code)
  23. Do you really know MySQL order by
  24. Record a java reference passing problem
  25. spring JTA 關於异常處理的時機問題
  26. Java - Set - Map (double file) - dija Rewriting, 2021 Java Developer's Performance Optimization
  27. Android入门教程 | OkHttp + Retrofit 取消请求的方法
  28. Java 8 Stream API and common methods, Java Junior Program interview
  29. Github 疯传!史上最强!BAT 大佬,2021年最新Java大厂面试笔试题分享
  30. git(3)Git 分支,zookeeper下载教程
  31. Java Backend Internet 500 questions d'entrevue moyennes et avancées (y compris les réponses), technologie de crochet Linux
  32. Entretien d'entretien d'usine Java post sprint de 100 jours - accumulation de jours et de mois, trois questions par jour [jour 12, fonction de principe de Zookeeper
  33. Tutoriel Java - reflection, tutoriel de téléchargement mongodb
  34. How to analyze several common key and hot issues in redis from multiple dimensions
  35. GIT (3) GIT Branch, Zookeeper Download tutoriel
  36. Tutoriel de démarrage Android | okhttp + Retrofit comment annuler une demande
  37. Design pattern [3.3] - Interpretation of cglib dynamic agent source code
  38. Share the actual operation of private collection project nodejs backend + Vue + Mysql to build a management system
  39. Springboot has 44 application initiators
  40. GitHub上霸榜久居不下的《Java面试突击宝典》,java图形用户界面设计基础
  41. GitHub上访问下载破百万的神仙文档《Java面试神技》看完我呆了,java面试问项目中遇到的问题
  42. GitHub上标星75k 超牛的《Java面试突击版,java高级工程师技能
  43. GitHub上标星2,java项目开发实训教程
  44. Docker development environment Preview
  45. JavaScript高級深入淺出:掌握 this 指向
  46. JavaScript Advanced Insight and outside: Mastering this direction
  47. Vue de l'application pratique de Javascript, drop drag Event
  48. docker 安装部署 Jenkins 2.322
  49. kafka安装
  50. 近九万字图文详解RabbitMQ
  51. Engaged in Java for one and a half years, how to break through yourself
  52. 输出9*9乘法表----java
  53. 判断一个数是不是素数-------java
  54. java项目,记录页面修改值,内部打“官司”用
  55. Docker installation Deployment Jenkins 2.322
  56. Comment porter un pantalon en hiver? Les petits hommes, les jambes épaisses et la largeur de l'entrejambe peuvent être vus. 3 techniques pour éviter la foudre
  57. MySQL下载和安装教程
  58. In depth analysis of rocketmq source code - message storage module
  59. Spring transaction management
  60. mysql恢复ibd数据,为何频频报错?