Re: [go-nuts] go-grpc question

23 views
Skip to first unread message

Josh Humphries

unread,
Oct 17, 2018, 9:25:40 AM10/17/18
to nakuld...@gmail.com, grpc.io

In general, connections are not cheap, but stubs are. Actual implementations for some languages differ, but Go complies with this.

What that means is that, generally speaking, you should not try creating the *grpc.ClientConn for each request. Instead create it once and cache it. You can create the stub just once and cache it (they are safe to use concurrently form multiple goroutines). But that is not necessary; you could also create the stub for each request, using the cached connection.

In practice, creating a new connection for each request will have overhead in terms of allocations, creating and tearing down goroutines, and also in terms of latency, to establish a new network connection every time. So it is advisable to cache and re-use them. However, if you are not using TLS, it may be acceptable to create a new connection per request (since the network connection latency is often low, at least if the client and server are in the same region/cloud provider). If you are using TLS, however, creating a connection per request is a bit of an atrocity: you are not only adding the extra latency of a TLS handshake to every request (typically 10s of milliseconds IIRC), but you are also inducing a potentially huge amount of load on the server, by making it perform many more digital signatures (one of the handshake steps) than if the clients cached and re-used connections.

Historically, the only reason it might be useful to create a new connection per request in Go was if you were using a layer-4(TCP) load balancer. In that case, the standard DNS resolver would resolve to a single IP address (that of the load balancer) and then only maintain a single connection. This would result in very poor load balancing since 100% of that client's requests would all route to the same backend. This would also happen when using standard Kubernetes services (when using gRPC for server-to-serve communication), as kubedns resolves a service name into a single virtual IP. I'm not sure if the current state of the world regarding TCP load balancers and the grpc-go project, but if it's still an issue and you run services in Kubernetes, you can use a 3rd party resolver: https://github.com/sercand/kuberesolver.

----
Josh Humphries
jh...@bluegosling.com


On Wed, Oct 17, 2018 at 2:13 AM <nakuld...@gmail.com> wrote:
Hello,

I intend to use grpc between two fixed endpoints (client and server) where the client receives multiple requests (the client serves as a proxy) which in turn sends a grpc request to the server. I wanted to know of the following would be considered good practice:

a) For every request that comes in at the client, do the following in the http handler:
       a) conn := grpc.Dial(...)            // establish a grpc connection
       b) client := NewClient(conn)    // instantiate a new client
       c) client.Something(..)             // invoke the grpc method on the client

i.e Establish a new connection and client in handling every request

b) Establish a single grpc connection between client and server at init() time and then inside the handler, instantiate a new client and invoke the grpc method
       a) client := NewClient(conn)    // instantiate a new client
       b) client.Something(..)             // invoke the grpc method on the client 

c) Establish a connection and instantiate a client at init() and then in every handler, just invoke the grpc method.
       a) client.Something(..)

The emphasis here is on performance as I expect the the client to process a large volume of requests coming in. I do know that grpc underneath creates streams but at the end of the day a single
logical grpc connection runs on a single TCP connection (multiplexing the streams) on it and having just one connection for all clients might not cut it. Thoughts and ideas appreciated !

Thanks,
Nakul


--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Robert Engels

unread,
Oct 17, 2018, 9:30:45 AM10/17/18
to Josh Humphries, nakuld...@gmail.com, grpc.io
Hi, my understanding, and it seems to be correct in testing is that grpc always makes a new connection (via tcp) due to load balancing. The only way I’ve been able to get grpc to use a single connection is if I use the “streaming” mode.

What am I doing wrong then?
Reply all
Reply to author
Forward
0 new messages