1
头图

Does gRPC service need to add HTTP interface?

While go-zero brings you a minimalist RESTful and gRPC service development experience, the community has put forward new expectations for us:

  • I want to write code only once
  • Both the gRPC interface
  • also HTTP interface
  • both. . . also. . .

Makes sense too! See what users say:

User A: a set of logic, api and rpc together

User B: If go-zero can simplify this step, I feel that it will become one of the best microservice frameworks in the go ecosystem

So, I fell into deep thinking: users can never be wrong, but should we provide it?

So, you saw this article. . .

We first provide gRPC services

We are all too familiar with this kind of service. Create a new directory, call it grpc-restufl , and put a sum.proto file in it

 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) {}
}

One-click generation, you know. . .

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

look what's there

 .
├── 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

Implement the business logic and modify the internal/logic/addlogic.go Add method in ---6422816d0b5e33c6c47aba93e3e359e8--- as follows:

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

It can be run, and the business logic is also available (although it is very simple, it is a demonstration...)

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

For students who are familiar with go-zero, there is no bright spot (new knowledge) so far, and then GET new skills~

Provide HTTP interface

update go-zero

First of all, we update go-zero to master version, because gateway not been officially released, we will meet you in early August

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

Modify the proto file

Modify sum.proto , I created a new one sum-api.proto , as follows:

 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: "*"
        };
    }
}

Generate proto descriptor file

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

Modify the configuration file

Modified internal/config/config.go as follows (in part):

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

Modified etc/sum.yaml as follows:

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

Modify the main function

Create gateway and use ServiceGroup to manage gRPC server and gateway server part, the code is as follows:

 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()

you're done

Let's start the service

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

Test it with 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"
}

Look at our gateway and gRPC . The link information in the log can be matched with what the client receives, like!

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

concluding remarks

You see, to our gRPC service plus HTTP interface can be completed in five minutes? is not it?

In addition, don't underestimate this simple gateway , if the configuration is connected to the back gRPC service discovery, it will be automatically load balanced, and you can also customize the middleware. Control how to control.

Are you a little excited?

By the way, the complete code for this example is at:

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

project address

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

Welcome go-zero and star support us!

WeChat exchange group

Follow the official account of " Microservice Practice " and click on the exchange group to get the QR code of the community group.


kevinwan
931 声望3.5k 粉丝

go-zero作者