批里批里 (゜-゜)つ🍺 干杯~|

七つ一旋桜

园龄:4年2个月粉丝:6关注:3

Day4 使用grpc-gateway构建微服务网关 | 青训营笔记

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

进行微服务开发的时候会用到网关服务,而原生自己实现一个网关服务会显得费时费力,grpc官方提供了一个网关服务插件grpc-gateway

使用这个插件可以像生成grpc服务一样生成网关服务,同时它还支持生成openapi,这样就可以轻松集成swagger进行服务测试了

安装

使用grpc-gateway首先要安装几个代码生成工具,这几个代码生成工具时grpc用来根据protobuf生成代码用的

go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@latest github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2@latest google.golang.org/protobuf/cmd/protoc-gen-go@latest google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest

除此之外还要安装buf工具,下载可以参考官方repo

buf可以使用yaml配置来简化生成代码的流程,只需要配置好yaml就可以使用命令buf generate生成所有要用的代码

生成文件

新建一个项目,目录应该如下如下

├── buf.gen.yaml
├── buf.work.yaml
├── go.mod
├── main.go
└── proto
├── buf.yaml

buf.gen.yaml

version: v1
plugins:
  # 根据protobuf文件生成go结构体
  - remote: buf.build/library/plugins/go:v1.27.1-1
    out: gen/go
    opt:
      - paths=source_relative
  # 生成grpc相关文件
  - remote: buf.build/library/plugins/go-grpc:v1.1.0-2
    out: gen/go
    opt:
      - paths=source_relative
  # 生成网关相关文件
  - remote: buf.build/grpc-ecosystem/plugins/grpc-gateway:v2.6.0-1
    out: gen/go
    opt:
      - paths=source_relative
  # 生成openapi文档
  - remote: buf.build/grpc-ecosystem/plugins/openapiv2:v2.6.0-1
    out: gen/openapiv2

buf.work.yaml

在这个文件中directories用于指定要根据哪些文件夹中的protobuf文件生成代码文件

version: v1
directories:
  - proto

proto/buf.yaml

version: v1
deps:
  # 添加一个会用到的依赖
  - buf.build/googleapis/googleapis

之后在proto文件夹中写protobuf文件

添加protobuf文件之前需要添加两个文件到proto目录下的**google/api**目录中

annotaions.proto

http.proto

定义网关服务的时候会引用这两个文件

使用protobuf定义api的例子如下

syntax = "proto3";
​
package helloworld;
option go_package="./helloworld";
​
​
import "google/api/annotations.proto";
​
service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {
    option (google.api.http) = {
      post: "/v1/example/echo"
      body: "*"
    };
  }
}
​
message HelloRequest {
  string name = 1;
}
​
message HelloReply {
  string message = 1;
}

原先定义一个服务,只需要定义服务的名称,参数列表和返回值列表

想要生成网关服务相关的代码,则还需要定义服务时添加option选项

定义post请求时要像上面代码中定义的一样,在option中定义一个post,其值就是服务对应的网关路由

定义完了之后再当前目录运行

buf generate

就会生成相应的代码在gen文件夹中

实现服务

main.go文件中修改代码

这步就是普通的实现grpc服务的

使用net.Listen设置要监听的端口

然后用helloworldpb.RegisterGreeterServer绑定自己写的服务实现

最后是用s.Serve(lis)启动服务

package main
​
import (
    // ...
    "google.golang.org/grpc"
    helloworldpb "github.com/myuser/myrepo/proto/helloworld"
)
​
type server struct{
    helloworldpb.UnimplementedGreeterServer
}
​
func (s *server) SayHello(ctx context.Context, in *helloworldpb.HelloRequest) (*helloworldpb.HelloReply, error) {
    return &helloworldpb.HelloReply{Message: in.Name + " world"}, nil
}
​
func main() {
    lis, err := net.Listen("tcp", ":8080")
    if err != nil {
        log.Fatalln("Failed to listen:", err)
    }
​
    s := grpc.NewServer()
    helloworldpb.RegisterGreeterServer(s, &server{})
    log.Println("Serving gRPC on 0.0.0.0:8080")
    log.Fatal(s.Serve(lis))
}

添加网关

修改main.go

因为网关服务和grpc服务需要并行执行,因此需要用到协程

将最后的log.Fatal(s.Serve(lis))放在一个新的协程中运行

如下

go func() {
   log.Fatal(s.Serve(lis)) 
}()

然后在main函数后添加如下内容来注册网关服务

// 创建连接
conn, err := grpc.DialContext(
    context.Background(),
    "0.0.0.0:8080",
    grpc.WithBlock(),
    grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
    log.Fatalln("Failed to dial server:", err)
}
​
gwmux := runtime.NewServeMux()
// 注册网关服务
err = helloworldpb.RegisterGreeterHandler(context.Background(), gwmux, conn)
if err != nil {
    log.Fatalln("Failed to register gateway:", err)
}
​
gwServer := &http.Server{
    Addr:    ":8090", // 定义网关服务的端口
    Handler: gwmux,
}
​
log.Println("Serving gRPC-Gateway on http://0.0.0.0:8090")
log.Fatalln(gwServer.ListenAndServe())

然后启动服务即可

本文作者:七つ一旋桜

本文链接:https://www.cnblogs.com/poifa/p/17716923.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   七つ一旋桜  阅读(42)  评论(0编辑  收藏  举报  
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起