13

有一个名为“十二要素应用程序”(http://www.12factor.net/)的优秀文档,其中作者试图定义设计、构建和部署现代应用程序的完美方式。服务。

该文档非常笼统,并且在许多情况下,所描述的做法不是最佳做法,不容易实现或违反 Microsoft 的最佳做法。例如:该文档不鼓励使用配置文件,而是使用环境变量进行配置。这在使用 XML 配置文件的常见(最佳?)实践的 .NET 中似乎是不正确的。

在一个理想的世界中(即忘记预算/技术/技能限制),在一个组织中,Microsoft 平台被选为所有部署的首选平台,.NET/TFS 是选择的开发环境/工具,人们将如何遵循指导在十二因素应用程序中?

有没有这样一个应用程序的好例子(也许是一个具有优秀参考架构的开源应用程序)?

4

4 回答 4

12

我已经阅读了关于配置的部分,作者显然不了解.NET中配置文件的使用。他们表达的问题是我们过去在 .ini 文件中遇到的问题。.NET 不存在这些问题,因为:

  1. “桌面”应用程序的每个部署将有一个配置文件。“app.config”将作为 program.exe.config 存在,部署到与应用程序相同的文件夹中。
  2. 在 Web 应用程序中,web.config 文件的层次结构将再次存在于明确定义的位置,并具有明确定义的名称。
  3. Visual Studio 2010 中的 web.config 转换功能允许将主配置文件检入源代码管理,以及指定如何为每个构建配置(环境)自动编辑主文件的转换文件。所有这些文件都可以存储在源代码管理中。
  4. 虽然默认将凭据存储在此类文件中(因此检查到源代码管理中),但这不是必需的。
  5. 至少在 Web 应用程序的情况下,IIS 的 MSDEPLOY 功能以及 Visual Studio 2010 的 Web 发布管道允许参数化部署。默认情况下,这包括连接字符串的参数化,这是可能出现凭据的主要区域之一。这可以扩展到包括所有凭据或其他敏感数据的参数化,以便开发人员无法访问此信息。这些参数可以作为部署过程的一部分填写。
于 2012-06-22T22:05:01.983 回答
7

12 Factor 对配置有 3 个“要求”。

  1. 不要将配置存储在代码中
  2. 不要将您的配置置于源代码控制中(或采用可能最终进入源代码控制的格式)。他们想要一个“单一代码库”。
  3. 以任何技术堆栈(.NET/Java/Ruby/.. 等)都可以访问的格式放置您的配置。

我想说.NET 配置文件符合其中的一半。

  1. 配置文件不在代码中(通过)。
  2. 配置文件不必在源代码管理中,但它们通常最终会出现(失败)。
  3. 尽管是 XML 格式并且可以被其他技术访问,.NET 配置文件有很多 .NETisms。配置部分的架构由 .NET 类型提供,因此 Java 应用无法验证架构。(半学分)。

虽然我同意他们要求的意图,但我认为他们对环境变量的建议是一个糟糕的建议。他们选择环境变量是因为他们将它们视为最低公分母并且在所有平台上都可用,但它们实际上可能并非在所有平台上都可用。如果您在部分信任的 Web 应用程序中运行(在共享托管平台上很常见),您可能无法访问获取/设置环境变量。

环境变量是按机器设置的。如果我必须对我的生产环境进行配置更改,我想在一个地方对所有服务器进行一次。环境变量不允许你这样做。

虽然我可以理解他们的观点,即您不希望将秘密存储在所有开发人员都可以访问的版本控制中。版本控制配置肯定有好处。当您的生产环境因配置更改而停机时,很容易问..“发生了什么变化”?某人只是通过 ssh 连接到产品机器并设置环境变量而留下的审计线索可能并不那么容易追踪。话虽如此,我通常不会将我的配置文件存储在与其余代码相同的版本控制部分中。我将它们放在安全性受限的文件夹中,以便只有必要的人需要访问。可以想象,您可以更进一步,将它们放在不同的项目中。

我愿意打赌他们违反了自己的不将配置放入文件的规则。例如。他们主页上的第一个要点是“使用声明性格式进行设置自动化,以最大限度地减少新开发人员加入项目的时间和成本;” 我敢打赌,所有那些不应该在任何地方的文件中的配置设置都在厨师食谱中。为了实现自动化的目标,您必须将它们保存在某个文件中的某个位置。如果有人花了很多时间得到正确的厨师食谱,但没有将它存储在某个地方的版本控制中,我会感到惊讶。

我认为他们可能会以不同的方式编写配置页面,只是说将您的配置与代码分开。将其保存在单独的文件中(不要将其嵌入代码中),并将其单独存储在某个地方(不要将其放在同一个存储库中)。您的部署过程会将这些(代码和配置)重新组合到一个可部署的包中,但在此之前它们应该是分开的。

我对配置的建议是将配置视为“附加资源”并将其存储在后备存储(数据库)中。这使您的应用层更加无状态,这是他们的另一个目标。

于 2012-06-28T18:23:38.787 回答
5

我认为设计存在许多问题,有点幼稚。

例如,在“支持服务”部分,他们声明您应该能够在不考虑代码更改的情况下交换数据存储。

问题是,为了利用任何特定数据存储的性能和功能优势,您自然会倾向于利用您开始使用的存储的特定功能。

此外,并非每个数据存储都支持一组通用命令,以便您可以轻松地从一个数据存储移动到另一个数据存储。他们使用 MySql 或 CouchDB 的特定示例很有趣,因为这两个数据库系统在概念上非常不同:一个更像是传统的 RDBMS,另一个是基于文档的。您不能只使用您的表结构并将其直接应用于 CouchDB 并期望向其抛出 SQL 命令。

这意味着您必须放置一个前端,以便用一组公开为 Web 服务的命令来包装每个特定的数据存储区……恕我直言,这使得开发变得更加困难,而收益却很少(如果有的话)。

现在,如果他们将其限制为将类似服务器(本地 mysql)交换为远程服务器(Amazon RDS),那么通过 url 访问数据存储资源的要求就无关紧要了。此外,不需要为该移动发生任何代码更改的要求,因为您不应该仅仅为了支持在不同的服务器上运行您的确切数据库而更改代码。


以上只是我老实说的第一个领域。正如 John Saunders 所说,配置也显示出对 .Net 等技术完全缺乏了解。坦率地说,整件事看起来像是由一个在 Ruby 世界里有一段时间的人写的,还没有看过那里还有什么。

于 2012-06-29T01:55:10.930 回答
0

我认为要在 Microsoft Windows 平台上遵循他们的指导,必须对该平台有深入的了解。

根据您关于第三个因素的建议,即在环境中存储配置的建议,我们应该问自己,Windows 平台中的环境变量到底是什么。答案是 Windows 注册表。现在,我确实在开发一个使用 Windows 注册表的服务器应用程序,并且考虑到我的角色(我确实关心持续集成、构建和安装程序),我真的非常讨厌我们必须这样做使用 Windows 注册表,但这就是您在 Windows 平台中所做的。

Windows 注册表显然在与语言和操作系统无关的标准上失败了,但是即使您使用普通的环境变量,在 Windows 平台上,这些都是在 Windows 注册表项中实现的。

我不时犯下将凭据存储在 SCM 中的罪行(顺便说一下,近年来主要是 TFS),但从来没有针对应用程序本身,主要是针对构建基础架构(即永远不会部署在客户站点或部署,并且与应用程序代码完全隔离)。

您可以使用 app/web.config 来存储凭据(还有加密功能),但这通常是个坏主意。

此外,如果您使用数据库作为后端(关系型、非关系型,实际上是任何类型的数据库),一些配置很可能会在那里结束,一些配置可能更适合存储在那里(即在多租户应用程序上) , 你真的希望隔离租户相关的配置,而且通常共享配置最终集中在租户 0 的特殊存储中),只要你可以存储和检索(即在注册表中)打开门带来的密钥你在那里。

关于第二个问题,作为 12factor 宣言的新手(但从我目前所读到的内容,而不是基本概念),我目前无法为您提供关于 .Net 参考架构的建议。

关于第二个问题的更新

另外,关于另一个问题,我想说第二个因素,即依赖关系,如果我们采用字面和严格的方法,可能会阻止我们在 Microsoft 平台上找到一个好的参考实现。

Windows Installer 和更高级别的安装创作工具(Wix、InstallShield 等)与 RubyGems 或 CPAN 无法真正相提并论,而且 NuGet 在普及方面还没有。

您可以寻找查看 NuGet 提要的参考实现,即使作者不知道 12factor,宣言要求非常明智的事情,优秀的开发人员将大多遵循这些或非常相似的概念。

作为这种方法的一个例子,我建议你看一下AyendeRavenDB,你可以通过 NuGet 得到它,我怀疑它会勾选大多数,如果不是全部的话,12factor guy box ( introfeaturessource代码)。

于 2012-06-29T09:47:37.677 回答