1

I have a Python gRPC server inside a Kubernetes cluster. The gRPC server implements a Ping method.

The server is load-balanced through Ingress Nginx, using the proper configuration (based on the official docs recommendations).

The server replies correctly to the request.

However, the Nginx logs show that a new HTTP/2 connection is initiated for each RPC call, despite re-using the same channel and the same stub.

NGINX logs

screen shot

│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:46 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:47 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:47 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:47 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:47 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]
│ ingress-nginx-controller-[...] 9.x.x.120 - - [07/Sep/2024:15:52:47 +0000] "POST /My.gRPC.Api/Ping HTTP/2.0" 200 [...]

Client code

The gRPC code that produced the above logs is the following:

import grpc

from my_lib.protos import api_pb2, api_pb2_grpc

host = "grpc.example.com"
credentials = grpc.ssl_channel_credentials()
channel = grpc.secure_channel(host, credentials)

stub = api_pb2_grpc.MyApiStub(channel=channel)
request = api_pb2.PingRequest(echo="ping")

for _ in range(15):
    stub.Ping(request=request)

Server code

The server is also implemented in Python.

import grpc

from my_lib.protos import api_pb2_grpc

class Server(api_pb2_grpc.MyApiServicer):
    async def Ping(self, request, context):
        return api_pb2.PingReply(echo=request.echo)


async def start_server():
    # I tried adding the following option, but no luck.
    options = [("grpc.max_concurrent_streams", 100)]
    server = grpc.aio.server(options=options)
    
    api_pb2_grpc.add_MyApi_to_server(Server(), server)
    # TLS termination is done by NGINX, traffic between NGINX
    # and this container is unencrypted
    server.add_insecure_port("[::]:5050")
    await server.start()

asyncio.run(start_server())

Question

I read everywhere that the HTTP/2 connection is expected to be re-used, and that multiple RPC calls should use the same TCP connection.

Why does a new HTTP connection is opened for each new call in my case ? What am I missing?


Resources I've read (among dozens of others):

7

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.