我们有大约100个微服务正在运行。每个微服务都有一整套配置文件,例如applicationmanifest.xml,settings.xml,node1.xml等。
这将成为配置噩梦。
在探索this后,有人建议:
您可以将配置保留在有状态服务中,然后更改参数 通过你的API。
我看到的问题是,现在存在单点故障:提供配置值的服务。
是否有集中式解决方案来为每个微服务维护如此多的配置数据?
答案 0 :(得分:1)
虽然中央配置服务似乎是这样做的,但如果你这样做,你会引入一些问题,你必须每次都做对了)。如果你有一个中央配置服务,它必须使用正确的配置更新你开始代码升级,当然你必须保持以前的配置,以防你的部署回滚。这是我在Service Fabric团队工作时提供的配置幻灯片。
Service Fabric具有版本配置功能,您应该使用它,但不能以Service Fabric建议的方式使用。对于我的项目,我使用Microsoft.Extensions.Configuration进行配置。捕获配置事件
context.CodePackageActivationContext.ConfigurationPackageAddedEvent += CodePackageActivationContext_ConfigurationPackageAddedEvent;
context.CodePackageActivationContext.ConfigurationPackageModifiedEvent += CodePackageActivationContext_ConfigurationPackageModifiedEvent;
context.CodePackageActivationContext.ConfigurationPackageRemovedEvent += Context_ConfigurationPackageRemovedEvent;
这些事件处理程序中的每一个都可以调用加载像这样的配置
protected IConfigurationRoot LoadConfiguration()
{
ConfigurationBuilder builder = new ConfigurationBuilder();
// Get the name of the environment this service is running within.
EnvironmentName = Environment.GetEnvironmentVariable(EnvironmentVariableName);
if (string.IsNullOrWhiteSpace(EnvironmentName))
{
var err = $"Environment is not defined using '{EnvironmentVariableName}'.";
_logger.Fatal(err);
throw new ArgumentException(err);
}
// Enumerate the configuration packaged. Look for the service type name, service name or settings.
IList<string> names = Context?.CodePackageActivationContext?.GetConfigurationPackageNames();
if (null != names)
{
foreach (string name in names)
{
if (name.Equals(GenericStatelessService.ConfigPackageName, StringComparison.InvariantCultureIgnoreCase))
{
var newPackage = Context.CodePackageActivationContext.GetConfigurationPackageObject(name);
// Set the base path to be the configuration directory, then add the JSON file for the service name and the service type name.
builder.SetBasePath(newPackage.Path)
.AddJsonFile($"{ServiceInstanceName}-{EnvironmentName}.json", true, true)
.AddJsonFile($"{Context.ServiceTypeName}-{EnvironmentName}.json", true, true);
// Load the settings into memory.
builder.AddInMemoryCollection(LoadSettings(newPackage));
}
}
}
// Swap in a new configuration.
return builder.Build();
}
您现在可以使用.Net配置与Configuration进行交互。最后要介绍的是配置文件的格式。在PackageRoot中|配置目录,您只需包含配置文件。我碰巧使用服务名称+数据中心。
内部文件看起来像这样,每个服务结构类都有一个JSON属性。
{
"Logging": {
"SeqUri": "http://localhost:5341",
"MaxFileSizeMB": "100",
"DaysToKeep": "1",
"FlushInterval": "00:01:00",
"SeqDefaultLogLevel": "Verbose",
"FileDefaultLogLevel": "Verbose"
},
"ApplicationOperations": {
"your values here": "<values>"
},
如果你坚持这么久,最大的好处就是配置与代码同时部署,如果代码回滚,配置也会如此,让你处于知道状态。
答案 1 :(得分:0)
注意:在使用单一配置服务是否可靠或是否使用静态与动态配置之间,您的问题似乎很模糊
有关静态与动态配置的争论,请参阅my answer的OP's other question。
配置服务听起来很合理,特别是当您认为Service Fabric的设计是可靠的,甚至是有状态的服务时。
MSDN:
Service Fabric使您能够构建和管理可扩展且可靠的应用程序,这些应用程序由在共享计算机池上高密度运行的微服务组成,称为集群
开发高度可靠无状态和有状态微服务。 Tell me more...
状态服务将状态存储在事务中的reliable distrubuted dictionary中,如果事务成功,则会保存数据。
OP:
我看到的问题是,现在只有一点失败:提供配置值的服务。
不一定。它不是真正的单点故障服务,而是由Service Fabric和您选择的Azure数据中心部署选项定义的“fault domain”。
MSDN:
故障域是协调故障的任何区域。单个机器是故障域(因为它可能由于各种原因而自行故障,从电源故障到驱动器故障到坏的NIC固件)。连接到同一以太网交换机的机器与共享单一电源或单个位置的机器位于同一故障域中。由于硬件故障重叠是很自然的,因此故障域本质上是分层的,在Service Fabric中表示为URI。
由于Service Fabric使用此信息安全地放置服务,因此正确设置Fault Domains非常重要。 Service Fabric不希望放置服务,以便丢失故障域(由某个组件的故障引起)导致服务中断。在Azure环境中,Service Fabric使用环境提供的Fault Domain信息代表您正确配置群集中的节点。对于Service Fabric Standalone,故障域是在设置群集时定义的
因此,您可能希望在两个独立的故障域上运行至少两个配置服务。