gRPC+gRPC Gateway+swagger小记
前言
本文记录了grpc-gateway的简单使用。
定义proto
先来看看最常规的
syntax = "proto3";
package protos;
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
然后加入gateway等相关的内容
syntax = "proto3";
package protos;
// 1 导入 gateway 相关的proto 以及 swagger 相关的 proto
import "google/api/annotations.proto";
import "protoc-gen-swagger/options/annotations.proto";
// 2 定义 swagger 相关的内容
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_swagger) = {
info: {
title: "grpc gateway sample";
version: "1.0";
license: {
name: "MIT";
};
};
schemes: HTTP;
};
service Greeter {
rpc SayHello (HelloRequest) returns (HelloReply) {
// 3 标识接口路由
option (google.api.http) = {
post: "/hello_world"
body: "*"
};
}
}
message HelloRequest {
string name = 1;
}
message HelloReply {
string message = 1;
}
从proto生成文件
执行下面的三个命令。
protoc -I . --go_out=plugins=grpc:. hello.proto
protoc -I . --grpc-gateway_out=logtostderr=true:. hello.proto
protoc -I . --swagger_out=logtostderr=true:. hello.proto
实现service和启动service
实现
package services
import (
"context"
pb "grpc-sample/protos"
"log"
)
type server struct{}
func NewServer() *server {
return &server{}
}
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
log.Println("request: ", in.Name)
return &pb.HelloReply{Message: "hello, " + in.Name}, nil
}
启动
package main
import (
"google.golang.org/grpc"
pb "grpc-sample/protos"
"grpc-sample/services"
"log"
"net"
)
const (
PORT = ":9192"
)
func main() {
lis, err := net.Listen("tcp", PORT)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterGreeterServer(s, services.NewServer())
log.Println("rpc services started, listen on localhost:9192")
s.Serve(lis)
}
整合 swagger
先下载swagger ui的静态文件。
把这些文件打包成go文件。
go-bindata --nocompress -pkg swagger -o gateway/swagger/datafile.go third_party/swagger-ui/...
9M。。。
写 gateway
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 "grpc-sample/gateway/swagger"
gw "grpc-sample/protos"
)
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:8080")
return http.ListenAndServe(":8080", mux)
}
func newGateway(ctx context.Context) (http.Handler, error) {
opts := []grpc.DialOption{grpc.WithInsecure()}
gwmux := runtime.NewServeMux()
if err := gw.RegisterGreeterHandlerFromEndpoint(ctx, gwmux, ":9192", opts); err != nil {
return nil, err
}
return gwmux, nil
}
func serveSwaggerFile(w http.ResponseWriter, r *http.Request) {
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("../protos", 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)
}
}
结果如下:
总结
通过grpc-gateway的方式来访问grpc服务,还是挺方便的,不过性能会有所折损。
参考
https://segmentfault.com/a/1190000013513469
gRPC+gRPC Gateway+swagger小记的更多相关文章
- AWS API Gateway Swagger定义
导出Swagger接口定义文件 在AWS API Gateway界面上,可以导出swagger接口定义文件. 而后利用Node js swagger-ui 依赖,生成swagger接口地址 Cloud ...
- LNMP : 502 Bad Gateway 解决小记,真正的原因
站点搬迁到新的server.原先一直都是LAMP.如今改为LNMP. 将重写文件 htaccess改成 nginx的 conf.放到了站点.可仅仅能打开首页,其它重写页面一打开都是不停的载入. 载入等 ...
- gRPC helloworld service, RESTful JSON API gateway and swagger UI
概述 本篇博文完整讲述了如果通过 protocol buffers 定义并启动一个 gRPC 服务,然后在 gRPC 服务上提供一个 RESTful JSON API 的反向代理 gateway,最后 ...
- protobuffer、gRPC、restful gRPC的相互转化
转自:https://studygolang.com/articles/12510 文档 grpc中文文档 grpc-gateway,restful和grpc转换库 protobuf 官网 proto ...
- gRPC错误码 http状态码 provide your APIs in both gRPC and RESTful style at the same time
How gRPC error codes map to HTTP status codes in the response https://github.com/grpc-ecosystem/grpc ...
- 如何在 Knative 中部署 WebSocket 和 gRPC 服务?
作者 | 冬岛 阿里云容器平台工程师 导读:虽然说 Knative 默认就支持 WebSocket 和 gRPC,但在使用中会发现,有时想要把自己的 WebSocket 或 gRPC 部署到 Kna ...
- gRPC应用C++
1. gRPC简述 RPC,远程方法调用,就是像调用本地方法一样调用远程方法. gRPC是Google实现的一种RPC框架,基于HTTP/2标准设计,带来诸如双向流.流控.头部压缩.单 TCP 连接 ...
- 使用nestjs集成grpc具体操作
两个程序中, 提供grpc服务的称为服务端, 调用grpc服务的为客户端, 以下是grpc服务端和客户端的代码编写 1. 创建两个nestjs项目demo1(端口: 3000)和demo2(端 ...
- gRPC学习之一:在CentOS7部署和设置GO
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
随机推荐
- element-ui 中Switch的用法
在element-ui中,如果你想知道Switch是开还是关,使用事件 @change="getchange(value2)" 它会输出true或者false.true代表的是开, ...
- Github(第一次尝试)
重要提示:项目中的文件最好最好不要出现中文,尤其是复杂的中文文件名. 前提:本地已经用git 管理 一个测试项目(项目一),分支为master. 1.注册 github: http://git.osc ...
- JavaScript-----14.内置对象 Array()和String()
5. 数组对象 5.1数组的创建 之前提到过数组的创建方式 字面量 new Array() //创建数组的两种方式 //1.利用数组字面量 var arr = [1, 2, 3]; console.l ...
- Windows下使用virtualenv创建虚拟环境
操作系统 : windowns10_x64Python版本:3.6.8virtualenv版本:16.7.7virtualenvwrapper版本:1.2.5 方式一:直接使用virtualenv 1 ...
- vue路由传参和获取参数
参考链接 https://router.vuejs.org/zh/guide/essentials/passing-props.html#%E5%B8%83%E5%B0%94%E6%A8%A1%E5% ...
- Python3---标准库---urllib
前言 该文章主要说明Python3 标准库urllib的使用. 修改时间:20191216 修改时间:20191217 修改时间:20191218 添加urllib.parse.urlencode,u ...
- Set a Many-to-Many Relationship设置多对多关系 (EF)
In this lesson, you will learn how to set relationships between business objects. For this purpose, ...
- vue-svgicon基本使用
在项目开发中,经常会用到svg图标,之前用的都是vue-svg-icon,最近在npm中搜索svg图标解析插件,发现vue-svgicon用的相对较多,对比以下,vue-svgicon用法较为灵活,方 ...
- vue发送ajax请求
一.vue-resource 1.简介 一款vue插件,用于处理ajax请求,vue1.x时广泛应用,现不被维护. 2.使用流程 step1:安装 [命令行输入] npm install vue-re ...
- JS If...Else
JS If...Else 条件语句用于基于不同的条件来执行不同的动作. 条件语句 通常在写代码时,您总是需要为不同的决定来执行不同的动作.您可以在代码中使用条件语句来完成该任务. 在 JavaScri ...