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.

Reply via email to