Skip to content

Performance implications of using the grpc-gateway for a REST API  #1458

Closed
@cyantarek

Description

Hi, I'm using the grpc-gateway "runtime" package to expose REST endpoint from proto buffers.
When I deployed to production, I observed very poor performance, something like 400 req/s.

So I started benchmarking in localhost using "bombardier" as benchmarking tool. Here's the result:

Bombarding http://localhost:5400/v1/link/ping with 1000000 request(s) using 100 connection(s)
 1000000 / 1000000 [===============] 100.00% 58s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     17102.51    1810.68   25905.78
  Latency        5.85ms     1.00ms    59.33ms
  HTTP codes:
    1xx - 0, 2xx - 1000000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:     6.31MB/s

No database or I/O calls, just ping response by calling the service layer function. Still the throughput is very low.

So I wrote my custom HTTP endpoint that will call the same service layer functions that the gRPC function is using. And now look at the benchmark:

Bombarding http://localhost:5400/v1/link/ping with 1000000 request(s) using 100 connection(s)
 1000000 / 1000000 [=============] 100.00% 7s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec    147464.89   22618.44  190638.47
  Latency      677.75us   551.27us    48.33ms
  HTTP codes:
    1xx - 0, 2xx - 1000000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:    35.51MB/s%

Boom! 6x faster than using the grpc-gateway "runtime" package.

I went further down into the rabbit hole. the grpc gateway runtime package has a http mux frontend that receives request from HTTP client and then calls the grpc server as a client.

So I try to simulate it manually. In my code, instead of calling the service layer function from the HTTP endpoint handler, I call the grpc server as a client.

And now the benchmark looks like this:

Bombarding http://localhost:5400/v1/link/ping with 1000000 request(s) using 100 connection(s)
 1000000 / 1000000 [==================] 100.00% 28s
Done!
Statistics        Avg      Stdev        Max
  Reqs/sec     35193.17    3242.29   46530.99
  Latency        2.84ms   459.67us    53.38ms
  HTTP codes:
    1xx - 0, 2xx - 1000000, 3xx - 0, 4xx - 0, 5xx - 0
    others - 0
  Throughput:     8.59MB/s%

Still not great, but its 2x better (35k req/s) than grpc gateway runtime (17k req/s)

So, gRPC gateway uses this flow:

HTTP Request -> REST Handler gRPC Client -> Call gRPC Server -> Returns response to the REST Handler gRPC Client -> Returns to the original caller

It looks like this is not the most efficient way to put a REST frontend before the gRPC server.

Anyway, I think you guys should take a look at this issue. Or maybe I'm doing something wrong

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions