我们的应用程序和服务使用了大量配置,其中大多数配置目前在java代码中都是硬编码的,并且分布在很多类中。显然,这需要改变,我们希望将其集中在一个地方,并且应该由其中一个服务(比如ConfigurationService)检索和公开,这也包括为其客户端缓存配置以获得更好的性能。我们还需要为长时间运行的应用程序动态重新加载配置,并避免重新启动。我想就我应该用于此目的的存储类型得到一些评论 -
无需构建数据。它可以是一个简单的键值对,也可以是多键,单值对。以下是配置的一些随机示例 -
基本上,形成键的参数的设置和类型不是固定的,这给了我一个暗示,这个配置并不是真正的结构。整个配置的量不会太大。与读取相比,写入很少。
数据库(RDBMS / NoSQL) - 使用数据库表的优点可能是它提供的安全性和备份。由于这看起来不像关系数据,我会考虑使用NoSQL解决方案。我个人并没有真正使用它们,请告诉我哪一种更适合这种数据。由于可能存在许多不同的键,我们应该能够选择精确的键(某种索引)。数据库使用会引入延迟,但可以构建有效的缓存来克服这个问题(因为对配置的写入不会太多)。数据更容易查询。
文件(XML或其他平面文件) - 我们可以使用这些文件保持简单。缓存也可用于文件的情况。只要整个配置可以导入内存(RAM),这也是一个选项(必须实现选择性高速缓存失效)。文件提供版本控制,必须查看权限/安全性。如果XML文件变大,尤其会变得更加混乱。如果我们使用文件,数据可能不容易查询。
假设动态重新加载和缓存失效是单独实现的,哪个应该是更好的存储解决方案?这里应该考虑哪些其他因素?
如果要使用文件来存储此类配置,那么这些用例的文件格式有哪些?
注意:我在SO上询问similar question,但可能没有像我应该的那样清楚地构建问题,因此创建了一个新问题,而不是进行大量编辑。
答案 0 :(得分:2)
答案 1 :(得分:1)
您提供的示例表明您可能需要某种规则引擎。为了表明我的意思,我将您的示例解释为具有以下语义:
if (true) {
Client_Id = "ABC";
}
if (User_Type == "Admin" && Region == "Mumbai" && "User_rating" == "9") {
Commission = "10%";
}
if (User_Id == "123") {
WhitelistedRegions" = ["Mumbai", "Goa"];
}
如果我的解释是错误的,那么也许你可以编辑你的问题来澄清你的意图。另一方面,如果我的解释是正确的,那么我不知道为您的要求量身定制的任何特定配置语法。相反,我怀疑你必须将你想要的语义扼杀到你决定使用的任何配置语法的约束中。
我可能会尝试将您的示例(我的解释)用于Config4*的语法(免责声明:我是其主要开发人员),如下所示:
uid-rule {
# unconditional
client_Id = "ABC";
}
uid-rule {
condition {
User_Type = "Admin";
Region = "Mumbai";
User_rating = "9";
}
Commission = "10%%";
}
uid-rule {
condition { User_Id = "123"; }
WhitelistedRegions = ["Mumbai", "Goa"];
}
我建议您阅读 Config4 *入门手册(HTML,PDF)的第2章,以便您了解上述示例中使用的语法。
我最初尝试将您的示例用于XML语法:
<rules>
<rule>
<property name="client_Id" value="ABC"/>
</rule>
<rule>
<condition name="User_Type" value="Admin"/>
<condition name="Region" value="Mumbai"/>
<condition name="User_rating" value="9"/>
<property name="Commission" value="10%"/>
</rule>
<rule>
<condition name="User_Id" value="123"/>
<property name="WhitelistedRegions" value="Mumbai, Goa"/>
</rule>
</rules>
请注意,Config4 *解析器和XML解析器都不会为您提供开箱即用的语义。相反,你应该编写一个名为RulesEngine
的类。这样的类将:(1)解析配置文件以获取规则并将解析的表示缓存在内存中; (2)提供一个简单的API来查询内存中的规则集; (3)提供重新解析配置文件的reloadConfiguration()
方法。您的应用程序会以某种方式触发reloadConfiguration()
方法的调用(例如,每隔几分钟一次)。
如果您使用XML作为配置语法,那么我建议您通过将XML文件存储在Web服务器上来实现集中化目标。 XML解析器可以在那里检索文件表单。如果您使用Config4 *语法,那么Config4 *与curl
的集成可以做同样的事情。
答案 2 :(得分:0)
有不同的方式来看待这种情况。
我决定存储数据的位置的方式通常基于数据类型。
如果我正确地读取您的数据,它会根据用户位置和评级以及适用于特定用户的区域来指定客户端ID,佣金。对我来说,它更像是一个业务静态数据而不是配置(虽然这不会经常改变)。因此,我更愿意将其保存在数据库中。
我是否需要为用户提供更新此数据的屏幕。如果有用户界面,则无需通过提交故障单或发布流程来在PROD环境中执行此操作。但是拥有一个用户界面会将选择权移到数据库中。
如果没有用户界面,那么文件配置可能是更好的选择。因为您可以在应用程序中使用文件观察程序服务来查看此配置文件。修改文件后,此服务将读取文件并更新配置而不重新启动。在数据库的情况下动态重新加载可能不那么简单。您仍然可以提供管理屏幕来手动触发配置重新加载。
对于文件类型,您可以选择Ciaran提出的选择,但这需要一些额外的学习。考虑到你没有大量的配置,你可以坚持使用xml。
缓存数据我认为不会对数据库和文件之间的选择产生任何影响,因为两者都很容易实现。但是,如果您正在使用一些像hibernate这样的ORM,那么您将免于缓存数据的额外工作,但ORM带来了另一种将数组映射定义到数据库表的复杂性。