golang 工程组件:grpc-gateway 环境安装+默认网关测试

grpc-gateway

grpc-gateway 顾名思义是专门是grpc的网关。也是一个protobuf的编译器,是一个proto的插件。 grpc-gateway就是将http请求处理后转发到对应grpc服务上。很多浏览器,或者客户端开箱不支持grpc,只支持传统的restful API。 grpc网关而且也支持负载,兼容不同版本。

官方文档

grpc-gateway

源码

架构

大致流程如下

  • 写好服务的proto文件。(代理+grpc)

  • 根据proto文件生成反向代理服务代码

  • 根据proto文件生成grpc服务存根

  • 启动反向代理和grpc

  • 客户端使用http json访问 或别的restful api形式

环境安装

protobuf

protobuf链接

下载对应环境的porotbuf。解压后bin路径配置环境变量

插件安装

博主 go 用的 1.19 + windows,预先安装好protobuf

复制代码
go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc- gateway@v2.12.0 
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28 
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2

可以把对应GO_PATH bin下插件的二进制文件拷到对应go安装的bin目录下

grpc+默认网关测试

proto文件

echo.proto

protobuf 复制代码
syntax = "proto3";
package  echo;
option go_package = "echo/proto";


message User{
  int64 id = 1;
  string name = 2;
  int32 age = 3;
  string phone = 4;
  Addr addr = 5;
}
message Addr {
  string province = 1;
  string city = 2;
  string county = 3;
}

service Echo{
  rpc Get(User) returns (User) {}
  rpc AddOrUpdate(User) returns (User) {}
  rpc Delete(User) returns (User) {}
}
生成grpc stub
复制代码
# 生成message 
protoc --proto_path=proto --go_out=proto --go_opt=paths=source_relative proto/echo.proto 
# 生成grpc service 
protoc --proto_path=proto --go-grpc_out=proto --go-grpc_opt=paths=source_relative proto/echo.proto
生成默认网关
go 复制代码
# 生成gateway protoc --proto_path=proto  --grpc-gateway_out=proto  --grpc-gateway_opt logtostderr=true  --grpc-gateway_opt paths=source_relative  --grpc-gateway_opt generate_unbound_methods=true  proto/echo.proto
grpc服务器代码

server.go

go 复制代码
package server

import (
    "context"
    "echo/proto"
    "fmt"
)

type echoServer struct {
    proto.UnimplementedEchoServer
}

func NewServer() proto.EchoServer {
    return &echoServer{}
}
func (s *echoServer) Get(ctx context.Context, in *proto.User) (*proto.User, error) {
    fmt.Printf("%+v\n", in)
    return in, nil
}
func (s *echoServer) AddOrUpdate(ctx context.Context, in *proto.User) (*proto.User, error) {
    fmt.Printf("%+v\n", in)
    return in, nil
}
func (s *echoServer) Delete(ctx context.Context, in *proto.User) (*proto.User, error) {
    fmt.Printf("%+v\n", in)
    return in, nil
}
gateway代码

这里直接用官网http代理的代码。需要修改端口和引用自己的grpc服务和网关package

gateway.go

go 复制代码
package gateway

import (
    "context"
    "flag"
    "net/http"

    "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    "google.golang.org/grpc"
    "google.golang.org/grpc/credentials/insecure"
    _ "google.golang.org/grpc/grpclog"

    gw "echo/proto"  // Update
)

var (
    // command-line options:
    // gRPC server endpoint
    grpcServerEndpoint = flag.String("grpc-server-endpoint",  "localhost:50051", "gRPC server endpoint")
)

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

    // Register gRPC server endpoint
    // Note: Make sure the gRPC server is running properly and accessible
    mux := runtime.NewServeMux()
    opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
    // 注册对应grpc服务端点handler
    err := gw.RegisterEchoHandlerFromEndpoint(ctx, mux,  *grpcServerEndpoint, opts)
    if err != nil {
        return err
    }

    // Start HTTP server (and proxy calls to gRPC server endpoint)
    return http.ListenAndServe(":8081", mux)
}
测试

main.go

go 复制代码
package main

import (
    "context"
    "echo/echo_server/gateway"
    "echo/echo_server/server"
    "echo/proto"
    "fmt"
    "google.golang.org/grpc"
    "log"
    "net"
    "os"
    "os/signal"
    "time"
)

func main() {
    // 先启动grpc service
    go func() {
        if err := run(); err != nil {
            log.Fatal(err)
        }
    }()
    time.Sleep(time.Second * 2)
    //后启动gateway
    go func() {
        if err := gateway.Run(); err != nil {
            log.Fatal(err)
        }
    }()

    ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
    defer stop()
    <-ctx.Done()
}

func run() error {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatal(err)
    }
    s := grpc.NewServer()
    userServiceServer := server.NewServer()
    proto.RegisterEchoServer(s, userServiceServer)
    fmt.Println("listening ")
    return s.Serve(lis)
}
默认路由

路由为proto文件中{包名}.{服务名}/{方法}。 gateway对外默认是post方法

复制代码
PS D:\GIT\gorun\grpc-gateway-practice\echo> Invoke-RestMethod -Uri "http://10.5.81.57:8081/echo.Echo/Get" -Method Post


id    : 0
name  :
age   : 0
phone :
addr  :

用postman更方便些

总结

  • grpc-gateway 只是提供一个反向代理,可以通过配置进行grpc版本兼容。

  • grpc-gateway对外提供restful API风格的http接口,更好兼容各种客户端接入,无需grpc客户端

相关推荐
chuan.bai1 小时前
Java RAG 实战(第 11 篇):RAG 知识工作台网页
java·开发语言·人工智能
离陌在学C#3 小时前
C# 事件(Event)详解:从概念到实战
开发语言·c#
Terra.K4 小时前
Java异常学习[特殊字符]
java·开发语言·学习
葡萄城技术团队5 小时前
InfluxDB 2\.x 深度解析:核心架构、Flux 函数与制造业落地指南(三)
java·开发语言·架构
counting money5 小时前
Java IO流详解:从InputStream到文件操作实战
java·开发语言·python
wuyk5556 小时前
98.C语言易混难点:字符数组与字符串指针的底层差异
c语言·开发语言·c++·stm32·嵌入式硬件·算法
峥无6 小时前
从0到1手撕红黑树:封装实现 my_map 与 my_set(SGI-STL 源码级深度解析)
开发语言·c++·笔记·算法·stl
波特率1152006 小时前
C++新特性---属性说明符与标准属性
开发语言·c++
程序员小八7776 小时前
上海百度B端java后端日常实习一面
java·开发语言
wp123_16 小时前
IPX8 防水 Type‑C连接器:安费诺 124018792112A 与 TONEVEE TY48087‑24A 技术梳理
c语言·开发语言