• 五分钟给你的 gRPC服务 加上 HTTP 接口


    gRPC 服务要加 HTTP 接口?

    go-zero 给大家带来极简的 RESTful 和 gRPC 服务开发体验的同时,社区又给我们提出了新的期望:

    • 我想只写一次代码
    • 既要 gRPC 接口
    • 也要 HTTP 接口
    • 既要。。。也要。。。

    也有道理嘛!你看用户怎么说:

    用户A:一套逻辑,api和rpc一起

    用户B:go-zero要是能简化这一步我感觉会成为go生态中最好的微服务框架没有之一

    于是,我陷入了深深的思考:用户从来是不会错的,但是我们要不要提供呢?

    于是,你看到了这篇文章。。。

    我们先提供 gRPC 服务

    对于这种服务,我们太熟了。新建一个目录,就叫 grpc-restufl 吧,里面放个 sum.proto 文件

    syntax = "proto3";
    
    package sum;
    option go_package="./pb";
    
    message Numbers {
        int64 a = 1;
        int64 b = 2;
    }
    
    message SumRequest {
        Numbers numbers =1;
    }
    
    message SumResponse {
        int64 result = 1;
    }
    
    service Sum {
        rpc Add(SumRequest) returns (SumResponse) {}
    }
    

    一键生成,你懂的。。。

    $ goctl rpc protoc --go_out=. --go-grpc_out=. --zrpc_out=. sum.proto
    

    看看都有了啥

    .
    ├── etc
    │   └── sum.yaml
    ├── go.mod
    ├── internal
    │   ├── config
    │   │   └── config.go
    │   ├── logic
    │   │   └── addlogic.go
    │   ├── server
    │   │   └── sumserver.go
    │   └── svc
    │       └── servicecontext.go
    ├── pb
    │   ├── sum.pb.go
    │   └── sum_grpc.pb.go
    ├── sum
    │   └── sum.go
    ├── sum.go
    └── sum.proto
    

    实现一下业务逻辑,将 internal/logic/addlogic.go 里的 Add 方法修改如下:

    func (l *AddLogic) Add(in *pb.SumRequest) (*pb.SumResponse, error) {
        return &pb.SumResponse{
            Result: in.Numbers.A+in.Numbers.B,
        }, nil
    }
    

    可以跑了,业务逻辑也是有了的(虽然很简单,演示嘛。。。)

    $ go mod tidy && go run sum.go
    Starting rpc server at 127.0.0.1:8080...
    

    对于熟悉 go-zero 的同学来说,至此无亮点(新知识),接下来 GET 新技能~

    提供 HTTP 接口

    更新 go-zero

    首先,我们更新 go-zero 至 master 版,因为 gateway 还没正式发版,八月初会正式跟大家见面

    $ go get -u github.com/zeromicro/go-zero@master
    

    修改 proto 文件

    修改 sum.proto,我新建了一个 sum-api.proto,如下:

    syntax = "proto3";
    
    package sum;
    option go_package="./pb";
    
    import "google/api/annotations.proto";
    
    message Numbers {
        int64 a = 1;
        int64 b = 2;
    }
    
    message SumRequest {
        Numbers numbers =1;
    }
    
    message SumResponse {
        int64 result = 1;
    }
    
    service Sum {
        rpc Add(SumRequest) returns (SumResponse) {
            option (google.api.http) = {
                post: "/v1/sum"
                body: "*"
            };
        }
    }
    
    折叠

    生成 proto descriptor 文件

    protoc --include_imports --proto_path=. --descriptor_set_out=sum.pb sum-api.proto
    

    修改配置文件

    修改后的 internal/config/config.go 如下(部分):

    type Config struct {
        zrpc.RpcServerConf
        Gateway gateway.GatewayConf
    }
    

    修改后的 etc/sum.yaml 如下:

    Gateway:
      Name: gateway
      Port: 8081
      Upstreams:
        - Grpc:
            Endpoints:
              - localhost:8080
          ProtoSet: sum.pb
    

    修改 main 函数

    创建 gateway 并用 ServiceGroup 来管理 gRPC servergateway server,部分代码如下:

        gw := gateway.MustNewServer(c.Gateway)
        group := service.NewServiceGroup()
        group.Add(s)
        group.Add(gw)
        defer group.Stop()
    
        fmt.Printf("Starting rpc server at %s...\n", c.ListenOn)
        fmt.Printf("Starting gateway at %s:%d...\n", c.Gateway.Host, c.Gateway.Port)
        group.Start()
    

    大功告成

    让我们来启动服务

    $ go run sum.go
    Starting rpc server at 127.0.0.1:8080...
    Starting gateway at 0.0.0.0:8081...
    

    curl 测试一下

    $ curl -i -H "Content-Type: application/json" -d '{"numbers":{"a":2,"b":3}}' localhost:8081/v1/sum
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    Traceparent: 00-ad5b7df7a834a1c05ee64999e3310811-195ba1f4f9956cc4-00
    Date: Mon, 18 Jul 2022 14:33:11 GMT
    Content-Length: 20
    
    {
      "result": "5"
    }
    

    再看我们的 gatewaygRPC 的日志里的链路信息和客户端收到的都能对应上,赞!

    {"@timestamp":"2022-07-18T22:33:11.437+08:00","caller":"serverinterceptors/statinterceptor.go:76","content":"127.0.0.1:61635 - /sum.Sum/Add - {\"numbers\":{\"a\":2,\"b\":3}}","duration":"0.0ms","level":"info","span":"b3c85cd32a76f8c9","trace":"ad5b7df7a834a1c05ee64999e3310811"}
    {"@timestamp":"2022-07-18T22:33:11.438+08:00","caller":"handler/loghandler.go:197","content":"[HTTP] 200 - POST /v1/sum - 127.0.0.1:61662 - curl/7.79.1","duration":"0.7ms","level":"info","span":"195ba1f4f9956cc4","trace":"ad5b7df7a834a1c05ee64999e3310811"}
    

    结束语

    你看,给我们的 gRPC 服务加上 HTTP 接口是不是五分钟就可以完成了?是不是?

    另外,不要小看这个简单的 gateway,配置里如果是对接后面的 gRPC 服务发现的话,会自动负载均衡的,并且还可以自定义中间件,想怎么控制就怎么控制。

    是不是有点心动了呢?

    对了,这个示例的完整代码在:

    https://github.com/kevwan/grpc-restful

    项目地址

    https://github.com/zeromicro/go-zero

    欢迎使用 go-zerostar 支持我们!

    微信交流群

    关注『微服务实践』公众号并点击 交流群 获取社区群二维码。

  • 相关阅读:
    pytorch学习------实现手写数字识别
    maptalks三维地图网址
    【重温设计模式】迭代器模式及其Java示例
    一个基于NetCore模块化、多租户CMS系统
    【学习笔记】同一个 solution 的不同 project 使用相同的头文件
    小知识(7) wangEditor富文本编辑器简单引入(vue3)
    python二次开发Solidworks:扫描
    Android系统-默认相关配置修改大集合
    ubuntu20.04配置vscode
    自定义映射resultMap
  • 原文地址:https://www.cnblogs.com/kevinwan/p/16492868.html