有没有办法完全不告诉服务有关设置,而只在应用程序级别提供它们?
我仍然对 servicefabric 配置的工作方式不满意。
据我所知,我必须在服务的 settings.xml 中指定所有可能的配置值。然后我可以覆盖应用程序的 ApplicationParameters 中的那些。根据文档,这看起来也适用于环境变量。
造成的复杂情况是,在许多情况下,我们的配置用于为数组组合选项。
例如考虑 json:
{
"AuthorizationOptions": {
"Policies": [
{
"Name": "User",
"Groups": [ "Domain Users" ]
}
]
}
}
有2个数组;这是必要和有用的。要在服务结构配置中表达这一点,它会转换为:
<Section Name="AuthorizationOptions">
<Parameter Name="Policies:0:Name" Value="User"/>
<Parameter Name="Policies:0:Groups:0" Value="Domain Users"/>
</Section>
虽然与结构化对象相比翻译并不令人愉快,但它是完全可用的。
但是,如果我不在服务中指定部分和参数,我似乎无法在应用程序中覆盖它们。因此,在这种情况下,我必须定义服务中每个策略的策略和组的确切数量,并且应用程序可以修改策略名称或组值,但不能修改策略总数或组总数。
有没有办法完全不告诉服务有关设置,而只在应用程序级别提供它们?
如果不是,存在哪些替代方案可以使服务可跨应用程序重用,我可能想使用这些替代方案以不同方式提供此类动态配置?
可能有助于回答这个问题的最后一部分是我正在使用一些 pre-release code将服务结构设置转换为 Microsoft.Extensions.Configuration.IConfiguration。但是,这只是采用它找到的设置;这不是我遇到的覆盖问题的原因。
示例服务 Settings.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Section Name="AuthorizationOptions">
<!-- I should not have to provide these at the application level!
However, it fails to deploy if I don't. -->
<Parameter Name="Policies:0:Name" Value="User"/>
<Parameter Name="Policies:0:Groups:0" Value="Domain Users"/>
</Section>
</Settings>
示例应用程序 ApplicationManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="ServiceFabric.ExampleType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="Service.Example_ASPNETCORE_ENVIRONMENT" DefaultValue="" />
<Parameter Name="Service.Example_InstanceCount" DefaultValue="-1" />
<Parameter Name="Service.Example_AuthorizationOptions_Policies_0_Name" DefaultValue="Users" />
<Parameter Name="Service.Example_AuthorizationOptions_Policies_0_Groups_0" DefaultValue="Domain Users" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="Service.ExamplePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="AuthorizationOptions">
<Parameter Name="Policies:0:Name" Value="[Service.Example_AuthorizationOptions_Policies_0_Name]" />
<Parameter Name="Policies:0:Groups:0" Value="[Service.Example_AuthorizationOptions_Policies_0_Groups_0]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
<EnvironmentOverrides CodePackageRef="code">
<EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[Service.Example_ASPNETCORE_ENVIRONMENT]" />
</EnvironmentOverrides>
</ServiceManifestImport>
<DefaultServices>
<Service Name="Service.Example" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="Service.ExampleType" InstanceCount="[Service.Example_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
示例应用程序 ApplicationParameters (Local.1Node.xml):
<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/ServiceFabric.Example" xmlns="http://schemas.microsoft.com/2011/01/fabric">
<Parameters>
<Parameter Name="Service.Example_ASPNETCORE_ENVIRONMENT" Value="Development" />
<Parameter Name="Service.Example_InstanceCount" Value="-1" />
<Parameter Name="Service.Example_AuthorizationOptions_Policies_0_Name" Value="Users" />
<Parameter Name="Service.Example_AuthorizationOptions_Policies_0_Groups_0" Value="Domain Users" />
</Parameters>
</Application>
示例应用程序 PublishProfiles (Local.1Node.xml):
<?xml version="1.0" encoding="utf-8"?>
<PublishProfile xmlns="http://schemas.microsoft.com/2015/05/fabrictools">
<ClusterConnectionParameters />
<ApplicationParameterFile Path="..\ApplicationParameters\Local.1Node.xml" />
</PublishProfile>
应该是无关的,但是设置的示例消费:
internal sealed class Example : StatelessService
{
public Example(StatelessServiceContext context)
: base(context)
{ }
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new ServiceInstanceListener[]
{
new ServiceInstanceListener(serviceContext =>
new HttpSysCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
{
ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting HttpSys on {url}");
return new WebHostBuilder()
.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.Negotiate; // Microsoft.AspNetCore.Server.HttpSys
options.Authentication.AllowAnonymous = false;
}).ConfigureServices(services => services.AddSingleton<StatelessServiceContext>(serviceContext))
.UseContentRoot(Directory.GetCurrentDirectory())
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.SetBasePath(Directory.GetCurrentDirectory());
config.AddServiceFabricConfiguration(FabricRuntime.GetActivationContext(), options => {
options.IncludePackageName=false;
});
})
.UseStartup<Startup>()
.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
.UseUrls(url)
.Build();
}))
};
}
}
从那时起,一切都按预期在 IConfiguration 对象中。
最佳答案
配置服务结构应用程序的方法有很多种,每种方法都会给您带来不同的挑战。
SF 团队推荐文档中的方法,因为您可以对配置进行更好的版本控制,并且更难犯错误,因为它在文件中明确声明,由于限制,我使用了几种不同的方法像您一样,以下方法可能会解决您的问题:
像原始方法一样配置,但将复杂类型存储为 JSON 值:这是最接近推荐设计的解决方案,您仍然可以在源代码管理上控制配置版本。 p>
它会是这样的:
设置.xml:
<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns... namespaces here...>
<Section Name="AuthorizationOptions">
<Parameter Name="Policies"/>
</Section>
</Settings>
应用程序 list .xml:
<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest ApplicationTypeName="ServiceFabric.ExampleType" ApplicationTypeVersion="1.0.0" xmlns:...namespaces....>
<Parameters>
<Parameter Name="Service.Example_ASPNETCORE_ENVIRONMENT" DefaultValue="" />
<Parameter Name="Service.Example_InstanceCount" DefaultValue="-1" />
<Parameter Name="Service.Example_AuthorizationOptions_Policies" DefaultValue="[]" />
</Parameters>
<ServiceManifestImport>
<ServiceManifestImport>
<ServiceManifestRef ServiceManifestName="Service.ExamplePkg" ServiceManifestVersion="1.0.0" />
<ConfigOverrides>
<ConfigOverride Name="Config">
<Settings>
<Section Name="AuthorizationOptions">
<Parameter Name="Policies" Value="[Service.Example_AuthorizationOptions_Policies]" />
</Section>
</Settings>
</ConfigOverride>
</ConfigOverrides>
<EnvironmentOverrides CodePackageRef="code">
<EnvironmentVariable Name="ASPNETCORE_ENVIRONMENT" Value="[Service.Example_ASPNETCORE_ENVIRONMENT]" />
</EnvironmentOverrides>
</ServiceManifestImport>
<DefaultServices>
<Service Name="Service.Example" ServicePackageActivationMode="ExclusiveProcess">
<StatelessService ServiceTypeName="Service.ExampleType" InstanceCount="[Service.Example_InstanceCount]">
<SingletonPartition />
</StatelessService>
</Service>
</DefaultServices>
</ApplicationManifest>
ApplicationParameters.xml
<?xml version="1.0" encoding="utf-8"?>
<Application Name="fabric:/ServiceFabric.Example" xmlns:...namespaces....>
<Parameters>
<Parameter Name="Service.Example_ASPNETCORE_ENVIRONMENT" Value="Development" />
<Parameter Name="Service.Example_InstanceCount" Value="-1" />
<Parameter Name="Service.Example_AuthorizationOptions_Policies" Value="[{'Name': 'User','Groups': ['Domain Users']}, {'Name': 'Admin','Groups': ['Administrators']}]" />
</Parameters>
</Application>
在您的服务代码中:
public class Policy
{
public string Name { get; set; }
public string[] Groups { get; set; }
}
var settings = this.Context.CodePackageActivationContext.GetConfigurationPackageObject("Config").Settings;
var authOptions = settings.Sections["AuthorizationOptions"].Parameters["Policies"].Value;
var obj = JsonConvert.DeserializeObject<Policy[]>(authOptions);
You could go a level further and store the entire
AuthorizationOptions
as a JSON, but like said previously, more generic it become, easier will be to commit mistakes and harder to find configuration issues.
关于azure-service-fabric - 动态 Servicefabric 设置和覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52858324/