天天看點

五分鐘給你的 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 server​

​​ 和 ​

​gateway 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"
}      

再看我們的 ​

​gateway​

​​ 和 ​

​gRPC​

​ 的日志裡的鍊路資訊和用戶端收到的都能對應上,贊!

{"@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​

​ 服務發現的話,會自動負載均衡的,并且還可以自定義中間件,想怎麼控制就怎麼控制。

是不是有點心動了呢?

對了,這個示例的完整代碼在:

​​github.com/kevwan/grpc…​​

項目位址

繼續閱讀