关于go:五分钟给你的-gRPC-服务加上-HTTP-接口

5次阅读

共计 3381 个字符,预计需要花费 9 分钟才能阅读完成。

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 反对咱们!

微信交换群

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

正文完
 0