【问题标题】:Choosing right storage for configuration为配置选择正确的存储
【发布时间】:2012-12-12 19:11:55
【问题描述】:

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

数据种类 -

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

  • “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 上询问了 similar question,但可能没有像我应该的那样清楚地提出问题,因此创建了一个新问题,而不是进行大量编辑。

【问题讨论】:

  • 一些问题:1) 您的“应用程序和服务”是否具有凝聚力,以至于拥有一个单一的配置服务才有意义? 2) 您的设计选择是否没有外部限制? 3) 谁来修改配置以及如何修改?
  • 1) 我们使用带有 gwt RPC 的 GWT 应用程序,它与基于 spring 的后端服务(远程处理)进行通信,所以通常所有后端服务 API 都被 RPC 使用,我们可以在这里做类似的事情,有一个后端的配置服务并将其 API 暴露给 RPC。 2)除了我上面提到的,不是真的。此外,我们也可以灵活地考虑使用不同的数据存储,如 NoSQL(目前我个人认为这将是一种矫枉过正)。 3)目前,开发者和内部用户修改配置,但有一个前端应用来做是一个可行的选择。

标签: database configuration nosql storage


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您提供的示例表明您可能需要某种规则引擎。为了说明我的意思,我将您的示例解释为具有以下语义:

    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* 入门手册的第 2 章(HTMLPDF),以便您了解上述示例中使用的语法。

    我最初将您的示例硬塞进 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 的集成可以做同样的事情。

    【讨论】:

      【解决方案3】:

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

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

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

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

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

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

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

      【讨论】:

      • 感谢您的回复。该示例只是我们拥有/需要的配置部分之一,所有这些都不是真正的业务静态数据。
      • 那么您可能希望将数据分成两个类别,并为每个类别分别实现。然后,您可以提供一个公共层来访问数据,以便它对调用者是透明的。
      • 典型的业务数据访问不是问题,这个问题是关于其他用例的详细设计(如问题所述)。
      猜你喜欢
      • 2019-03-07
      • 2011-09-22
      • 2013-12-02
      • 2020-10-01
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      相关资源
      最近更新 更多