Run a REST->GRPC gateway (reverse proxy) to one or more GRPC services, as a single separate process.
This simple package consists of 2 parts:
- a bash script to create a REST proxy for one or more grpc services, based on the .proto file
- a go package to easily create a stand-alone process.
It is based on the grpc-gateway package. If you want to integrate REST functionality in your GRPC server process itself, you should not use this package. Instead, just use that package directly, possibly running the the REST interface on the same port as grpc with cmux.
If you want to run a stand-alone process as a REST->GRPC gateway, you don't want to be concerned with running mux'es etc. With this package you can quickly generate your REST server and use your regular HTTP tooling, e.g. your load- and performance testing tools. Of cousre, when using the gateway as a proxy for performance testing with a HTTP load generator, keep in mind the following important points:
- you probably want to run the gateway on the host of your load generator, so the HTTP latency is minimized and the GRPC latency and the bandwidth is realistic
- this gateway itself induces latency and could be a capacity bottleneck itself. This will mainly be relevant when you serialize big JSON data structures, or when your grpc server has a very high performance calls (low response time). So do some benchmarking of the gateway itself, to estimate it's significance. The gateway from the
example/
directory (which has, admittedly, very small json i/o structures) is benchmarked to do 2000 rps with <1 ms latency, and for larger request/response structures more latency may be introduced.
- Go language
- Follow the installation steps here: https://github.com/grpc-ecosystem/grpc-gateway#installation
Use the grpc-gateway code to generate the proxy code, which exports a Register[YOURSERVICE]Handler() method.
The commands are in the generate-proxy.sh script, which generates:
- the .pb.gw.go, which is the only one strictly necessary: you will use the RegisterXXXHandler() method.
- the .pb.go , which you should have already used and implemented a GRPC service for (unless you implemented the GRPC service in another language)
- the .swagger.json, which documents your REST service and is nice to generate documentation (hint: do paste it in http://editor.swagger.io ).
Then implement your gateway process as follows:
gateway := restgrpc.NewGateway()
// register a grpc endpoint
gateway.AddService(restgrpc.NewEndpoint(
// some fancy name you choose
"Compute",
// remote endpoint for grpc server
"localhost:50051",
// the handler that is generated by the protoc plugin `grpc-gateway`
compute.RegisterComputeServiceHandler),
)
// register another grpc endpoint
gateway.AddService(restgrpc.NewEndpoint(
"SayHello",
"localhost:50052",
sayhello.RegisterSayHelloHandler,
))
// connect to remote service, and expose them on :8080.
// this is a blocking call.
err := gateway.Bind(":8080");
You can check the example implementation in the example/
directory. All commands are assumed to be run in that dir, so cd example
.
Generate the grpc go files (pb.go), gateway files (pb.gw.go) and swagger spec (.swagger.json) with the make
command:
Then run the 2 grpc servers and the proxy:
go run grpcComputeServer.go
go run grpcSayHelloServer.go
go run proxy.go
Now you can make HTTP requests:
curl -X POST -d '{ "name":"mr. Johnson"}' http://localhost:8080/v1/example/politeGreeting
{"message":"Good day, mr. Johnson"}
curl -X POST -d '{ "name":"Johnnie"}' http://localhost:8080/v1/example/coolGreeting
{"message":"Yo Johnnie, what up!"}
curl -X POST -d '{ "a":"2", "b":"3", "c":"4"}' http://localhost:8080/v1/example/compute
{"result":"10","ser":"hello there!! 2 * 3 + 4 = 10"}
The gateway does not reconnect to the GRPC server when it loses the connection.
Feedback? Most appreciated :-)