New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integrate with generic host (IHost interface) in asp.net core 2.1 #48
Comments
I will use this feature in Microsoft Intune which builds on top of Service Fabric + Asp.net Core. Within Intune we have many Microservice teams and one common infra team, I want to leverage the flexible extensions support provided by the generic host and hook it up with Service Fabric, so that each Microservice team register their custom logic follow the generic host extension point, while as common infra team we could control certain common function consistently. I'm still working on get the 2 tied together, I will share some sample code to demonstrating this later this month. |
thanks @OlegKarasik for the link of your implementation on the similar idea to link generic host and service fabric, glad to know that I'm not alone here. I have implemented above already and is using it in Microsoft Intune, but after discussing with @amanbha and @vturecek from Service Fabric team, they are hesitate to take the contribution for this yet in favor of Service Fabric Mesh as the future. I could understand where they're from for that decision, since Service Fabric Mesh has a complete different app model, in fact with SF Mesh you could just use regular generic host and regular asp.net core directly. Several of internal Microsoft members from different teams has also reached out to me directly asking about the reference implementation details. I need all of you help to vote for this idea to show enough support, hoping that someday we could publish this as a public reference implementation and with the spirit of open source and community support this could become matual over time. |
and for reference, here is the core interface that I used to implement this to link generic host with service fabric by translate the host service provider to service replica service provider, rest of interface are just the public one from generic host or from service fabric. public interface IServiceProviderAdapter
{
/// <summary>
/// translate the host service provider to service replica (partition for statefull service or instance for stateless service) service provider
/// </summary>
/// <param name="hostServiceProvider">the service provider from process host.</param>
/// <param name="serviceContext">The service context used to create service replica.</param>
/// <returns>the service provider used for service replica dependency resolution.</returns>
IServiceProvider CreateReplicaServiceProvider(IServiceProvider hostServiceProvider, ServiceContext serviceContext);
} |
@chuanboz Thanks for the great comment! I didn't dive deep into Mesh but as far as I understand (and hope) it isn't a replacement for Service Fabric (because if I am not mistaken there is no way to create stateful services in Mesh). I think when we would have a first release of Mesh then Service Fabric team will have some time to take a look at what community did to integrate generic host and Service Fabric. |
This definitely still needs to be implemented - from https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/generic-host?view=aspnetcore-3.0 :
Note that IHostedService is very similar to ICommunicationListener. While addressing this, I would also like to see separation between building the app (configuration, services, http pipeline) and creating listeners. For example, it should be easy to create both HTTP and HTTPS listeners using the same configuration, DI container, and HTTP pipeline. The current design of I'm willing to provide this as a contribution, if it would be considered. |
@johncrim Thanks for offering to contribute, sure, we would consider your contribution as long as tis not a breaking change. Please feel free to create a PR. |
@johncrim , in your design to use IHostedService as ICommunicationListener, can you clarify the following:
I'm asking because we implemented this already with a different model as your above and want to check if we could possible converge over time and have one shared public supported experience eventually. |
Hi @johncrim @amanbha, Does it looks like something you are looking for? (You can check projects Wiki for more detailed information about all the features). |
Here's my analysis + opinion on what can and should be done. The work to provide a good generic host design seems bigger than I initially expected, based on the design of Current Design + Limitations
In other words, the current design of
Also note that a "CommunicationListener" object in ServiceFabric libs doesn't explicitly do anything with communications. It has lifecycle methods (open/close/abort) and an endpoint string (open returns the endpoint string). In my opinion the key flaw with the current design of At worst, this existing design appears to be at odds with the intended design of service fabric core, given that it doesn't support multiple endpoints providing access to multiple service types. At best, it's wasteful and is likely to cause confusion when some developers can't figure out that there are multiple WebHosts/DI containers/etc being created. I would also characterize the current setup process as clunkier than it needs to be and misleads developers who are new to Service Fabric. Design Proposal Putting aside the need to be backwards compatible, I think it's worth discussing an "ideal" design within generic hosts. Then we can come back to the topic of making it backwards compatible. Principles:
The obvious common use case is 1 service type, 1 communication listener, 1 DI container, and 1 WebHost per service process. "Advanced" scenarios include:
Here's what I think is the correct object hierarchy within a generic host:
It should be possible to put 1 or more WebHosts within the ServiceFabric IHostedService, but I think a better default is 1 WebHost per Host. With a little additional work, it should be possible to use a separate DI container and web host pipeline, and port per SF service. To put this in terms of app setup code, I envision something like the following: var hostBuilder = new HostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
// Host configuration
.ConfigureAppConfiguration(config =>
{
config.AddEnvironmentVariables()
.AddCommandLine(args)
.AddServiceFabricConfiguration();
})
// Host level services
.ConfigureServices(services => /* ... */)
// Web host pipeline exposes APIs used by all the SF services
.ConfigureWebHost(webhostBuilder =>
{
webhostBuilder.UseStartup<ServerStartup>()
.UseKestrel();
})
.ConfigureServiceFabricHost((hostContext, sfHostBuilder) =>
{
sfHostBuilder.RegisterService<MyStatelessService>("StatelessServiceTypeName", (serviceContext, sfServiceBuilder) =>
{
sfServiceBuilder.UseEndpoints(serviceContext.CodePackageActivationContext.GetEndpoints(), ServiceFabricEndpointPrefix.None);
});
sfHostBuilder.RegisterService<MyStatefulService>("StatefulServiceTypeName", (serviceContext, sfServiceBuilder) =>
{
sfServiceBuilder.UseEndpoints(serviceContext.CodePackageActivationContext.GetEndpoints(), ServiceFabricEndpointPrefix.Partition);
});
});
using (var host = hostBuilder.Build())
{
host.Start();
Console.WriteLine($"SF Node started.");
Console.WriteLine("Use Ctrl-C to exit.");
await host.WaitForShutdownAsync();
} One question that came up when thinking this through: What should control the lifetime of the WebHost(s)? The WebHost could run within the ServiceFabricHostedService (a new IHostedService that would be created), so it is started only when one or more service types are started; or it could run within the GenericWebHostService, which is the setup for normal ASP.NET servers; or both could be supported. Unfortunately, if one wants to setup a WebHost within a generic host, the current design (as of ASP.NET Core 3.0 preview 7) requires that the WebHost is run within a GenericWebHostService - it doesn't appear to be a supported scenario to setup a WebHost within a generic host, and then start and stop it within a custom Also unfortunately, the only way to preserve backward compatibility with the current design of My preference would be to support running WebHosts both within the standard AspNetCore hosted service, and within the ServiceFabricHostedService; and have the remainder of the integration functionality (middleware, communication listeners, etc) work with both setups. It's clear to me that the current design of the Existing Solutions The coherent solutions [https://github.com/coherentsolutionsinc/aspnetcore-service-fabric-hosting] project that @OlegKarasik linked looks well done. The docs appear good, and the setup looks more like what I would expect. I'm not yet clear on whether it has support for sharing a WebHost between service types; and it doesn't look like there is any middleware that replaces Next Steps For my use cases, I'm going to evaluate the coherent solutions lib and/or implementing a generic I don't think I can help with this issue given the current limitations in the GenericWebHost and the need to keep What do you all think? |
@chuanboz - to answer your earlier questions:
IMO both should be possible. I do think that the generic host design generally favors a single, host-level DI container/IServiceProvider, because it's simplest, and scoping can be added where necessary to control the lifetime of injected objects. But I also think that one should be able to create a separate webhost and DI container per service type if required.
ServiceFabric (the system) already controls the lifetime of the executable (aka code package). Your executable won't be started until SF decides it needs the service types declared in your But in general I think both scenarios should be supported. You should be able to run a webhost pipeline per service instance (and have the service start/stop the webhost), and you should be able to share a webhost pipeline between any number of services. |
Agree on those principles, and I'd like to add one more: Introduce fewer new concept for the integration.
There is 1 use case even for 1 service type 1 listener, that the service instance could have failures to instantiate initially but subsequencial instantiate could success, in such case the host process does not need to be restarted, only the service instance needs to be restarted, to avoid the cost of creating new process.
the service fabric hosting model supports to restart the service instance multiple times upon failures to instantiate the service types. If you use HostedService, how do you plan to support to restart the instance. IHostedService is one direction of StartAsnc->StopAsync.
Agree on new libraries should be introduced. I used Microsoft.ServiceFabric.AspNetCore.Hosting and Microsoft.ServiceFabric.AspNetCore.Hosting.Abstractions to align with asp.net core extensions naming pattern, but Microsoft.ServiceFabric.AspNetCore.GenericHost would also work and actually a good name.
Agree on new library route, that's also what I used.
I like your overall thinking and principles, but I have concern to use IHostedService to host WebHost, I see that would work with simple scenario but not work with more complex scenarios. take a look of https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-hosting-model |
Hi @johncrim, Thanks you for such a detailed walk through and warm words about the project :)
Can you elaborate a bit more on this? Looks like I don't really understand the concept of shared WebHost.
The Please feel free to ask any question about the project. |
@OlegKarasik and @johncrim , can you clarify what's issues you're trying to address with the generic integration? In other words, let's say this is implemented, how do you plan to use it, and how that make your experience better? I want to understand better of the user scenario and use case. For us, it's mainly for integration test support without the service fabric dependency, and also to launch the service directly without service owner to change their code, and faster debuging without deployment, with a mock service fabric clusters. |
@chuanboz
|
thanks @OlegKarasik for the details reponse and link to well structured and maintained wiki. Seems we have many in common, especially your point 2, 3,and 4 that's the driving factor for me. @johncrim , can you share your thought on the issues to address and the goal to achieve with this? I briefly meet with Service Fabric team and as @amanbha already called out, they are willing to accept the contribution now as long as it does not introduce breaking change. I will spend sometime to clean up and prepare my current implementation used in Microsoft Intune, and send a PR for discussion. @johncrim and @OlegKarasik , we shall work together and bring up the best of all we have to support majority of sceanrios called out above out of box and make it extensible for service owner to hook up to add remaining themselves. |
I agree with @OlegKarasik and @chuanboz RE all the benefits of the generic host approach (global/shared DI), simplified + more intuitive configuration/startup code (eg more along the lines of "normal" ASP.NET Core apps), better support for testing/mocking, and removing what appear to be legacy design requirements (eg subclassing I wrote my own SF host integration library, to allow using the generic host model in ASP.NET Core. This replaces the 2+ SF integration libraries (Microsoft.ServiceFabric.Services and Microsoft.ServiceFabric.AspNetCore.Kestrel, which depend on Microsoft.ServiceFabric), and uses a direct dependency on Microsoft.ServiceFabric, which is the primary .NET/C++ interop API to ServiceFabric. It provides these benefits:
Oleg's library is much more feature complete than my library is - but my library meets our needs for now, and the small size is a virtue. I will share it on github as soon as I can. One point which seems contentious (and which I don't think we're all in agreement on) is backward compatibility, and along with it the need to preserve IMO backward compatibility of existing Microsoft.ServiceFabric.AspNetCore.* libraries should be achieved by not significantly changing them. |
i would love to see this as well, thank you @johncrim @OlegKarasik and @chuanboz for pushing for it. we're also looking for to run multiple services in a single host as you describe, as well as sharing a webhost. for us the shared webhost scenario is basically multiple services sharing a port, so instead of having service1 at 10.0.0.1:5000 and service2 at 10.0.0.1:5002 we'd like to have service1 at 10.0.0.1:4000/Service1 and 10.0.0.1:4000/Service2. We want to do this to create a way for services to happen to be on the same host to be able to call each other really quickly, via a custom in-process path. (thats not really part of the generic host stuff, i just wanted to give some background) Mesh is not really usable for us since it lacks support for the app models the SF team has pushed for years.. (as well as the inability to host multiple services in a single host) if you need any help or scenario validation, i'd love to help out :) |
@aL3891 Sounds interesting. What about web host configuration? Do these service also share all the DI stuff? |
That would be the case in my solution yeah (i havent gotten it working yet) but there would only be one kestrel instance running per host, and in the default case when a new replica came online, it would just be another route in the already running kestrel server. we'd have some custom middleware that a replica would interact with via DI and basically tell the middleware "i'm running on this host now" Those last parts havent really materalized yet, but even in a more traditional one-kestrel-per-replica scenario, we'd want to share some DI services globally on the host. |
I'm preparing my changes to send out for review and discussion, I see 2 open issues and want to seek feedbacks:
I propose to add this constraints for the new library as I see anyone that could benifet from the new library would already use asp.net core anyway, that will reduce the support cost as well as development cost for the new library. |
@chuanboz I concur with having these constraints for the new binary and its nuget package. |
This is initial change for generic hsot integration. microsoft#48 Added abstractions, concreate implementation and test support packages. still need further change to demonstrate the usage as well as add automat integration test.
I've added the initial changes that I have used, I will spend more test to add integration test to cover the changes, but the major part of change including integration test support and visual studio F5 support are there. End user experience is like this: private static void Main()
{
var hostBuilder = CreateHostBuilder();
hostBuilder.Build().Run();
}
public static IHostBuilder CreateHostBuilder()
{
return new HostBuilder()
.UseServiceFabricHost()
.UseServiceFabricRuntime()
.ConfigureWebHost(b => b.UseStartup<Startup>())
;
} details see develop...chuanboz:GenericHost @johncrim , @OlegKarasik and @aL3891 , let me know your feedback. After all the changes are done, I expect the following experience to be true:
thanks, |
it's a great discussion so far, and we all got better understanding of the scenarios, requirement. I'd propose let's first work together to agree on the user experience without tie to specific implementations, and then discuss on major technical design, and eventually agree on a standard implementation that's extensible to meet everyone of us' use cases. |
Imo the high level requirements are:
Regarding the actual asp.net integration, i'm not actually sure this neccearily needs to be tied to the GenericHost implementation as a whole. Personally i feel like that is something you'd build on top of the requirements above. Things like sharing a webhost are great and a core scenario for us, but i feel like doing that is something that the user will have to build into their solution, rather than something that can be done "under" the user services. Things like the asp.net service fabric middleware can pull the partition info out of DI (and the "low" level generic host library should make sure to register them). This also means that i dont think all the generic host stuff should neccarily be in this repo Specifically, i think the packages/repos should look like this (actual name pending): ServiceFabric.GenericHost.NativeLives in service-fabric. Contains the base implementation for generic host integration as well as support for "native" SF services and generic host (IStatefulServiceReplica/IStatelessServiceInstance) and registration of multiple services in a single host. References only Microsoft.ServiceFabric. ServiceFabric.GenericHost.ReliableServicesLives in service-fabric-services-and-actors-dotnet. Adds support for StatelessService and StatefulService. References Microsoft.ServiceFabric.Services. Potentially also contains ways to specify multiple ICommunicationListeners via GenericHost. ServiceFabric.GenericHost.ActorsLives in service-fabric-services-and-actors-dotnet. Adds support for registering actors. ServiceFabric.AspnetIntegrationLives in service-fabric-aspnetcore. Contains the asp.net middleware as well as infrastructue to host asp.net in service fabric (in a very similar way as is done today). Contains additional things that you can use when defining listeners via the host using ServiceFabric.GenericHost.ReliableServices. One thing i'm think about right now is what the experience should be when registering an actor service, should you register each layer separetly or should the higher level bring in the lower level. ie:
or
i'm leaning towards the second option. |
closed by mistake, re-opening it + @masnider as well. |
Ping in this issue. Work still going on? |
Yes, for my part I think it would be premature to close this. I have been working with my own SF integration library (which runs in an IHostedService and takes a direct dependency on Microsoft.ServiceFabric (6.5.641)), but I both wanted to test it out a while and make sure it holds up. I would like to merge efforts with the other contributors on this thread, but am not quite ready and/or have not had the time to separate it in a presentable form. |
Yes, the work is still in progress. I am planning to release a new version of my library before end of the year with support for stateless service local debugging (ability to debug ASP.NET Core stateless service without running SF cluster). |
i'm very close to deploying my version of this, https://github.com/aL3891/ServiceFabricGenericHost, to production as well, (like next week), i havent tested the actor parts extensivley yet though, but stateless and stateful services are there at least and actors should work too :) The api might might go a though a little churn as well, but its pretty close to locked |
Hi All, As I mentioned previously I have release a new version of CoherentSolutions.Extensions.Hosting.ServiceFabric with so-called local runtime which enables local debugging for simplest stateless service scenarios. Feel free to try and share your feedback (or report issues). Here are sample application and wiki page with implementation details. While current version supports I would say essential things I am planning to improve local runtime to allow more scenarios in future to be debugged and verified locally. |
I found this old but still open issue and I wonder if it's related with the problems I'm having to get Autofac in an AspNet Core 3.1 application working for service fabric and Test Support, as I asked here. Can I ask you guys how do you use the TestServer with an aspnet core project that runs in Service Fabric when there is such a difference in the way the |
something new on GenericHost with ServiceFabric? |
Hi all, |
Just noting we discussed briefly on community call 51, still need to get work booked to get this completed. Will update when we get something committed. |
is that completely ignored here? |
since 18 Feb no update? :-( |
I noticed that recently a pull request #96 was merged into the develop branch, which enables the support of the IHost. |
Hi @ThiemeNL and everyone,
|
Been almost a month and release of .net 6 has been out about a week now and I noticed PR 96 as well. Any updates? This may not be the right place for this, but are there any plans for a Service Fabric Template for .net 6 hosting Blazor Web Assembly for Visual Studio 2022? |
@PavanKunapareddyMSFT When do you expect to release an updated |
Generic host support seems to be included in the latest version libraries (5.2.1363). Not mentioned in release notes though. |
@PavanKunapareddyMSFT Would you be able to give us an update on:
please? |
asp.net core is refactor with generic host in aspnet/Hosting#1163 that has better support on DI and lifecycle management etc, but I do not see an integration for the ServiceFabric-AspnetCore.
the ask is to provide a ServiceFabricHost that implement IHost interface, to wrap the generic logic to register service type and also creating service instance.
here are specific difference for Service Fabric that deserve its own ServiceFabricHost:
-- Service instance scope (* unique for Service Fabric)
---Request scope
----Transient scope
for regular console host, the IHostedService shall be started right after host start; but for Service Fabric, it shall be registered with service factory and won't start the IHostedService directly; All IHostedService will be started as part of ICommunicationListener.OpenAsync; and IHostedService could be started multiple times within the same process, each time whenever there is a new service instance created.
here are sample scenario usage:
The text was updated successfully, but these errors were encountered: