6

我们有使用大量配置的应用程序和服务,其中大部分当前是硬编码在 java 代码中并分布在很多类中。显然,这需要更改,我们希望将其集中在一个地方,并且应该由其中一项服务(例如 ConfigurationService)检索和公开,该服务还包含为其客户端缓存配置以获得更好的性能。我们还需要为长时间运行的应用程序动态重新加载配置并避免重新启动。我想就我应该为此目的使用的存储类型发表一些评论 -

数据类型 -

数据不需要结构化。它可以是一个简单的键值对,也可以是多键单值对。以下是一些随机配置示例 -

  • “Client_Id”->“ABC”(简单键值)
  • [“User_Type”:“Admin”,“Region”:“Mumbai”,“User_rating”:“9”] -> [“Commission”:“10%”](多键值)
  • ["User_Id" -> "123"] -> ["WhitelistedRegions"->"Mumbai, Goa"] (基于上下文的配置,值是一个列表)

存储解决方案 -

基本上,形成密钥的参数的集合和类型是不固定的,这给了我一个暗示,这个配置并不是真正结构化的。整个配置的体积不会很大。与读取相比,写入将非常少。

  • 数据库 (RDBMS / NoSQL) - 使用数据库表的优势可能是它提供的安全性和备份。由于这看起来不像关系数据,因此我会考虑使用 NoSQL 解决方案。我个人并没有真正使用过它们中的任何一个,请告诉我哪一个更适合这种数据。由于可能有很多不同的键,我们应该能够选择精确的键(某种索引)。数据库使用会引入延迟,但可以构建有效的缓存来克服这个问题(因为不会对配置进行太多写入)。数据更容易查询。

  • 文件(XML 或其他平面文件) ——我们可以使用这些文件保持简单。缓存也可以用于文件的情况。只要可以将整个配置导入内存 (RAM),这也是一个选项(必须实现选择性缓存失效)。文件提供版本控制,必须研究权限/安全性。如果 XML 文件变大,它们尤其会变得更加混乱。如果我们使用文件,数据可能不容易查询。

假设动态重新加载和缓存失效是分开实现的,哪个应该是更好的存储解决方案?这里还应该考虑哪些其他因素?

如果要使用文件来存储此类配置,那么对于此类用例,更好的文件格式是什么?

注意:我在 SO 上问了一个类似的问题,但可能没有像我应该的那样清楚地提出问题,所以创建了一个新问题,而不是进行大量编辑。

4

3 回答 3

2

请帮自己一个忙,并评估ArchaiusCurator是否适合您的需求。Archaius 可能更适合应用程序和容器配置,而 Curator 可能更适合机器级配置。

于 2012-12-27T19:23:25.630 回答
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* 入门手册(HTMLPDF )的第 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可以做同样的事情。

于 2012-12-13T22:24:02.843 回答
0

有不同的方式来看待这种情况。

  1. 我决定将数据存储在何处的方式通常基于数据类型。

    如果我正确读取您的数据,它会指定客户 ID、基于用户位置和评级的佣金以及适用于特定用户的区域。对我来说,它更多的是业务静态数据而不是配置(尽管这不会经常更改)。因此,我更愿意将其保存在数据库中。

  2. 我是否需要为用户提供一个屏幕来更新这些数据。如果有 UI,您无需通过提出票证或发布过程即可在 PROD 环境中执行此操作。但是拥有 UI 会将选择转移到数据库。

  3. 如果没有 UI,那么文件配置可能是更好的选择。因为你可以在你的应用程序中有一个文件观察服务来观察这个配置文件。修改文件后,此服务将读取文件并更新配置而无需重新启动。在数据库的情况下动态重新加载可能不那么简单。您仍然可以提供一个管理屏幕来手动触发配置重新加载。

  4. 对于文件类型,您可以选择 Ciaran 提出的选择,但这需要一些额外的学习。考虑到您没有大量配置,您可以坚持使用 xml。

  5. 缓存数据我认为不会对数据库和文件之间的选择产生任何影响,因为两者都很容易实现。但是,如果您使用一些像 hibernate 这样的 ORM,您将免于缓存数据的额外工作,但 ORM 带来了定义到数据库表的类映射的另一个复杂性。

于 2012-12-25T10:21:11.073 回答