【发布时间】:2018-11-20 18:01:56
【问题描述】:
我目前正在从事一个 POC 项目,我正在尝试弄清楚如何在不同端点之间共享服务依赖项以控制应用程序状态并处理所有服务请求(我们称之为 ControlService) - 特别是当其中一个这些端点是 KestrelCommunicationListener / HttpSysCommunicationListener 并与 FabricTransportServiceRemotingListener(或任何其他类型的自定义侦听器)结合使用
Autofac 看起来很有希望,但是这些示例没有显示如何在启动时构建容器而不是主入口点时让 HTTP 侦听器工作 - 我是否需要将容器传递给 MyFabricService 以便它可以通过到启动注册并被添加到启动注册?
我已经看到使用 container.Update() 或使用 container.BeginLifetimeScope() 动态添加注册的引用,但它们都使用内置于 main 的容器,然后我不确定如何添加 API由 HTTP 侦听器创建到原始容器。
我可能没有很好地解释它,所以总而言之,我希望有类似以下服务的东西,可以通过 n 接收通信。不同的端点 - 处理消息,然后通过 n 发送消息。客户端(也称为其他服务端点)
如果有什么不清楚的地方,很高兴澄清 - 甚至可以使用另一个创意图表 :)
更新:
来自 Program.Main()
ServiceRuntime.RegisterServiceAsync("ManagementServiceType",
context => new ManagementService(context)).GetAwaiter().GetResult();
这是我的面料服务
public ManagementService(StatefulServiceContext context)
: base(context)
{
//this does not work but is pretty much what I'm after
_managementService = ServiceProviderFactory.ServiceProvider.GetService(typeof(IManagementService)) as IManagementService;
}
protected override IEnumerable<ServiceReplicaListener> CreateServiceReplicaListeners() =>
new ServiceReplicaListener[]
{
//create external http listener
ServiceReplicaListenerFactory.CreateExternalListener(typeof(Startup), StateManager, (serviceContext, message) => ServiceEventSource.Current.ServiceMessage(serviceContext, message), "ServiceEndpoint"),
//create remoting listener with injected dependency
ServiceReplicaListenerFactory.CreateServiceReplicaListenerFor(() => new RemotingListenerService(_managementService), "ManagmentServiceRemotingEndpoint", "ManagementServiceListener")
};
ServiceReplicaListener
public static ServiceReplicaListener CreateExternalListener(Type startupType, IReliableStateManager stateManager, Action<StatefulServiceContext, string> loggingCallback, string endpointname)
{
return new ServiceReplicaListener(serviceContext =>
{
return new KestrelCommunicationListener(serviceContext, endpointname, (url, listener) =>
{
loggingCallback(serviceContext, $"Starting Kestrel on {url}");
return new WebHostBuilder().UseKestrel()
.ConfigureServices((hostingContext, services) =>
{
services.AddSingleton(serviceContext);
services.AddSingleton(stateManager);
services.AddApplicationInsightsTelemetry(hostingContext.Configuration);
services.AddSingleton<ITelemetryInitializer>((serviceProvider) => new FabricTelemetryInitializer(serviceContext));
})
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddServiceFabricConfiguration(serviceContext);
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddDebug();
})
.UseContentRoot(Directory.GetCurrentDirectory())
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseStartup(startupType)
.UseUrls(url)
.Build();
});
});
}
启动
public class Startup
{
private const string apiTitle = "Management Service API";
private const string apiVersion = "v1";
private readonly IConfiguration configuration;
public Startup(IConfiguration configuration)
{
this.configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
var modules = new List<ICompositionModule>
{
new Composition.CompositionModule(),
new BusinessCompositionModule()
};
foreach (var module in modules)
{
module.AddServices(services, configuration);
}
services.AddSwashbuckle(configuration, apiTitle, apiVersion, "ManagementService.xml");
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddApplicationInsights(app.ApplicationServices);
// app.UseAuthentication();
// app.UseSecurityContext();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
// app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseCors("CorsPolicy");
app.UseMvc();
app.UseSwagger(apiTitle, apiVersion);
//app.UseMvc(routes =>
//{
// routes.MapRoute(
// name: "default",
// template: "{controller=Home}/{action=Index}/{id?}");
//});
}
}
所有服务依赖项都使用startup.cs中的Microsoft.Extensions.DependencyInjection(不是autofac)添加到CompositionModules中
这很好用并创建了我的 HTTP 侦听器 - 我现在只需要一种方法来访问在我的 http 侦听器/webhost 启动期间添加到容器中的服务。
【问题讨论】:
-
您能否详细说明一下您的依赖项的实例化位置?您是否需要能够在 WebHostBuilder.ConfigureServices 中的 *Listener 内执行注册?
-
@OlegKarasik 我用一些示例代码编辑了这个问题
-
IManagementService是否有一些依赖项应该通过正在配置的依赖注入容器来解决?示例:ManagementService(IEnvironmentService)其中IEnvironmentService用于KestrelListener中的WebHost可以是WebHostEnvironmentService和RemotingListener-RemotingWebHostEnvironmentService。 -
我认为我的示例代码有点误导抱歉 - IManagementService 是我所有业务逻辑的存放位置,本质上是我示例图中的“ControlService”。 ControlService 可能包含多个依赖项,但我不认为它需要对托管环境的依赖,因为它本质上只是处理在多个端点上收到的请求。
标签: dependency-injection autofac azure-service-fabric