My company’s project adopts Restful-based microservice architecture. As the communication between microservices becomes more and more frequent, I hope to use rpc for internal communication and external communication. Still use Restful. So I thought of Google’s grpc.
There are many advantages of using grpc. Binary data can speed up the transmission speed. Multiplexing based on http2 can reduce the number of connections between services. The same method of calling as a function is also effective. Improved development efficiency.
However, using grpc will also face a problem. Our microservices must provide a Restful interface externally. If grpc is used for internal calls, in some cases two sets of API interfaces must be provided at the same time. , This not only reduces the development efficiency, but also increases the complexity of debugging. So I wondered if there is a conversion mechanism so that Restful and gprc can be converted to each other.
I saw a solution on the Internet, https://github.com/grpc-ecosystem/grpc-gateway. Simply put, there is a gateway server responsible for conversion and proxy forwarding.
As shown below:
Install
First install ProtocolBuffers 3.0 and above.
mkdir tmp
cd tmp
git clone https://github.com/google/protobuf
cd protobuf
./autogen.sh
./configure
make
make check
sudo make install
Then use go get to get grpc-gateway.
go get -u github.com/grpc-ecosystem/grpc-gateway/protoc-gen-grpc-gateway
go get -u github.com/grpc-ecosystem/grpc-gateway/ protoc-gen-swagger
go get -u github.com/golang/protobuf/protoc-gen-go
It is best to put the directory of the compiled binary file in $ In PATH
, you can put $GOPATH/bin
into $PATH
.
Example
This example is based on the example in my previous blog “The use of Google’s grpc in glang”, if necessary, please understand the previous blog first.
The address for obtaining the sample code: https://github.com/andyidea/go-example.
The code file structure is as follows
└── src
└── grpc-helloworld-gateway
├── gateway
│ └── main.go
├── greeter_server
│ └── main.go
└── helloworld
├── helloworld.pb.go
├── helloworld .pb.gw.go
└── helloworld.proto
Let’s take a look at the protocol file first. There are some changes to helloworld.proto, the introduction of Google’s official api-related extensions, which provides support for grpc’s http conversion.
The specific changes are as follows:
syntax = "proto3";
option java_multiple_files = true;
option java_package = "io.grpc.examples .helloworld";
option java_outer_classname = "HelloWorldProto";
package helloworld;
import "google/api/annotations.proto";
< br />// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {
option (google.api. http) = {
post: "/v1/example/echo"
body: "*"
};
}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
Compared with the previous proto file, the new file has been added
import "google/api /annotations.proto";
and
option (google.api.http) = {
post: "/v1/example/echo"
body : "*"Here, an extended configuration for http has been added.
Then compile the proto file and generate the corresponding go file
cd src/grpc-helloworld-gateway
protoc -I/usr/local/include- I. \
-I$GOPATH/src \
-I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--go_out=Mgoogle /api/annotations.proto=github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/google/api,plugins=grpc:. \
helloworld/helloworld.protohere The helloworld/helloworld.pb.go file is generated.
helloworld.pb.go is required by the server service. In the next step, we need to use protoc to generate the go files required by the gateway.
cd src/grpc-helloworld-gateway
protoc -I/usr/local/include -I. \
-I$GOPATH/src -I$GOPATH /src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis \
--swagger_out=logtostderr=true:. \
helloworld/helloworld.protohere The helloworld/helloworld.pb.gw.go file is generated. This file is the protocol file used by the gateway to convert between grpc and http.
After the protocol file is processed, the gateway code needs to be written.
The gateway code is as follows:
package main
import (
"flag"
"net/http"
"github.com/golang/glog"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"golang.org/x/net/context"
"google.golang.org/grpc"
gw "grpc-helloworld-gateway/helloworld"
)
var (
echoEndpoint = flag .String("echo_endpoint", "localhost:50051", "endpoint of YourService")
)
func run() error {
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
mux := runtime.NewServeMux()
opts := []grpc. DialOption{grpc.WithInsecure()}
err := gw.RegisterGreeterHandlerFromEndpoint(ctx, mux, *echoEndpoint, opts)
if err != nil {
return err
}< br />
return http.ListenAndServe(":8080", mux)
}
func main() {
flag.Parse()
defer glog.Flush()
if err := r un(); err != nil {
glog.Fatal(err)
}
}First echoEndpoint stores the server information that needs to be connected, and then the information Register and bind the newly created server with RegisterGreeterHandlerFromEndpoint in gw.go. At this time, the lower layer will connect to the remote server address provided by echoEndpoint, so that the gateway will act as a client to establish a connection with the remote server, and then start the newly created with http server and gateway serve as the server to provide http services to the outside world.
The code is now complete, let’s test it.
Start the greeter_server service first, and then start the gateway. At this time, after gatway connects to the greeter_server, it establishes an external http monitoring.
Then we use curl to send http requests
curl -X POST -k http://localhost:8080/v1/example/echo -d'{"name": "world "}
{"message":"Hello world"}The process is as follows: curl uses post to send a request to the gateway, and the gateway acts as a proxy to transform the request and forward it to greeter_server through grpc , Greeter_server returns the result through grpc, and after the gateway receives the result, it converts it into json and returns it to the front end.
In this way, the conversion process from http json to internal grpc is completed through grpc-gateway.