On Wed, Oct 17, 2018 at 5:04 PM <nakuldesa...@gmail.com> wrote: > Hi Josh, > > Thanks for getting back ! Wouldn't having a single TCP connection be a > bottleneck (assuming no layer-4 load balancer) especially if there is a > slow reader, tcp flow control would limit other streams on that connection. > In that case wouldn't having more connections help ? >
A *grpc.ClientConn is not a single TCP connection to a *server*: it is a "logical" connection to a *service*. It can manage a very large number of actual sockets. It supports pluggable name resolution as well as load balancing, for routing requests in the presence of multiple physical connections. But, as I mentioned, you may have an issue if using the default DNS resolver and a hostname that resolves to just a single IP address: that will cause the grpc.ClientConn to maintain only a single connection. (By default, the DNS resolver will try to maintain one connection to every IP address returned -- unless something has changed recently.) In that case, yes, there could be a bandwidth bottleneck, especially if the network link is not reliable (e.g. over internet/WAN, vs. between machines in the same datacenter/region). For machines in the same datacenter, (at least in my experience) the poor load balancing has been a bigger concern. IIRC, I don't think it's that hard to create a custom resolver that resolves a single IP address but instructs the client to use multiple connections. (I haven't worked in those particular nooks and crannies of the project in a while, though.) > > Thanks, > Nakul > > On Wednesday, October 17, 2018 at 6:26:00 AM UTC-7, Joshua Humphries wrote: >> >> *+grp...@googlegroups.com* >> >> *moving golan...@googlegroups.com to BCC* >> >> 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. >>> >> -- > 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+unsubscr...@googlegroups.com. > For more options, visit https://groups.google.com/d/optout. > -- 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+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.