orleans icon indicating copy to clipboard operation
orleans copied to clipboard

Multiple clients in one servicecollention

Open spingee opened this issue 2 years ago • 12 comments

Hello, Is it possible to define multiple clients for differnet clusters in one appdomain/servicecolletion. Or another usecase we have localhost/inmemory orleans defined on IHost but want connect to real cluster with different client. Is this possible? Thanks for answer

spingee avatar Jun 06 '23 10:06 spingee

Bumping because I would also like to know if this functionality is currently possible. In v3 it was possible doing something like this library but I haven't figured out a way to do it in v7 since we no longer have access to IClientBuilder.Build().

orionstudt avatar Jul 11 '23 20:07 orionstudt

Ok I found this response which claims that it's doable by having multiple hosts.

It also claims it's easier? Not sure how that would be the case now that you have to manage separate host lifetimes and separate service collections.

orionstudt avatar Jul 11 '23 20:07 orionstudt

You don't necessarily need multiple hosts, but you do need multiple ServiceCollections, one per client, and you would need to plumb the cross-cutting concerns (ILoggerFactory, the ILogger<> registration, etc) from the host to the client container, and then you'd need to register an IHostedService in the host container to start the IHostedService registered by the client.

I think an update to Orleans.MultiClient is the right approach, to essentially implement what I mentioned. In .NET 8, we will have Keyed DI in .NET itself, so it's possible that you could register the relevant IClusterClient and IGrainFactory instances with the host container that way.

ReubenBond avatar Jul 11 '23 20:07 ReubenBond

Right, when I said hosts I guess I meant multiple IHosts.

Is there a functional reason why this is an unsupported configuration? Does Orleans recommend against consuming multiple clusters?

Since with the v7 changes it seems like a design decision away from a configuration that was more possible previously when we had more control over ClientBuilder.

orionstudt avatar Jul 11 '23 20:07 orionstudt

The old approach was just doing this anyway: the ClientBuilder was effectively a HostBuilder, creating/destroying its own container and starting a hosted service. It was confusing for people. The new approach is that you have a host (since you would have a host anyway for the vast majority of apps) and you add the client bits to it - no separate containers, no separate logging configuration, IConfiguration, no separate lifecycle management, etc.

The downside of this otherwise easier approach is that it's not as obvious how to create multiple clients in a single app. Creating multiple HostBuilders is very close to creating multiple ClientBuilders, even if it feels heavier. You have more control now, using the de-bundled approach.

All of this being said, we are open to the idea of having standalone clients or clients registered using Keyed DI (using the technique I mentioned above of referencing shared services across containers). This scenario seems common enough that having in-built support for it could be worthwhile.

ReubenBond avatar Jul 11 '23 21:07 ReubenBond

@ReubenBond That makes sense. It does seem heavier just because as the consumer we're doing more work than we were before but I can see how that is simpler on your end and we get more flexibility overall.

I'm working on an implementation that does just that now - and one thing I'm missing is IClusterClient.Connect() - is that not necessary anymore?

Here in the documentation it looks like both the v7 and v3 docs are referring to the old client builder when talking about a hosted service that handles connecting and closing.

orionstudt avatar Jul 12 '23 13:07 orionstudt

@ReubenBond , is there anywhere we can get a sample of what the recommended approach is for creating clients? Especially external clients? The documentation mentions various ways but I think it would be good if the client portion had more details and a clear sample code. Especially for external clients as that is the more complicated one.

SoucianceEqdamRashti avatar Aug 22 '23 12:08 SoucianceEqdamRashti

Is there any planned worked to use Keyed DI to support multiple clients?

jsukhabut avatar Apr 18 '24 17:04 jsukhabut

@SoucianceEqdamRashti ClusterClient the internal Implementation of IClusterClient implement also IHostedService used to start and stop. So try to get IClusterCLient and try to cast it to IHostedService

MickaelThumerel avatar Jun 11 '24 09:06 MickaelThumerel

We were migrating from 3.x to Orleans 8 and I faced this problem too 😞 Just if anyone is interested we used a frontend cluster talking to several backend clusters (silos). They are separate clusters because we deploy them independently and basically they are different versions of our app. So different versions of mobile clients were eventually talking to different backend clusters. This allowed smooth client releases and upgrades among different platforms.

AntonPetrov83 avatar Aug 20 '24 15:08 AntonPetrov83

We should make this easier... an add-on could achieve this with one DI container per client, and keyed DI to map the client back into the parent container. For example, it could work like so:

  • Map all IHostedService registrations from the client DI container into the parent container - this could also be accomplished by creating a single IHostedService impl in the parent container which resolves all IHostedServices from the client container and manages their lifetimes (StartAsync/StopAsync)
  • Map the core ILogger & IConfiguration services from the parent into the child (for IConfiguration, perhaps it should map a named section?)
  • Map IClusterClient/IGrainFactory from the child into the parent using Keyed DI

Would that fit the use cases here? This would not enable the creation of new clients at runtime but allows them to all be attached to a single host. If the creation of new clients at runtime is required, then that can be achieved with more effort, without the use of keyed DI. If there is a proposal for how people would like this to look & work, that would be very helpful

ReubenBond avatar Aug 20 '24 15:08 ReubenBond

Yes we need creating clients in runtime. And our clustering configuration can change in runtime too, new cluster added, some old cluster removed etc. This makes implementation even harder because of client's lifetime control issues 😬

AntonPetrov83 avatar Aug 20 '24 16:08 AntonPetrov83