了解多租户和并行开发 understanding-multitenancy-and-concurrent-development

简介 introduction

当多个团队将他们的代码部署到相同的AEM环境时,他们应遵循以下惯例,以确保团队可以尽可能独立地工作,而无需踩到其他团队的脚步。 尽管永远无法完全消除,但这些技术将最大限度地减少跨团队依赖性。 对于成功的并发开发模型,开发团队之间的良好通信至关重要。

此外,当多个开发团队在同一个AEM环境中工作时,可能会出现一定程度的多租户问题。 关于在AEM环境中尝试支持多个租户的实际考虑已进行了大量研究,特别是关于管理治理、运营和发展时面临的挑战。 本文探讨了在多租户环境中实施AEM的一些技术挑战,但其中许多建议将适用于具有多个开发团队的任何组织。

预先需要注意的是,虽然AEM可以支持在单个环境中部署多个站点甚至多个品牌,但它并不提供真正的多租赁。 某些环境配置和系统资源将始终在环境中部署的所有站点之间共享。 本文就如何最大限度地减少这些共享资源的影响提供了指导,并为简化这些领域的交流与合作提供了建议。

优势和挑战 benefits-and-challenges

实施多租户环境存在许多挑战。

其中包括:

  • 其他技术复杂性
  • 增加开发开销
  • 跨组织依赖共享资源
  • 操作复杂性增加

尽管面临各种挑战,但运行多租户应用程序确实有好处,例如:

  • 降低硬件成本
  • 缩短未来站点的上市时间
  • 降低未来租户的实施成本
  • 跨业务的标准架构和开发实践
  • 公共代码库

如果企业需要真正的多租赁,并且不了解其他租户并且不共享代码、内容或共同作者,则单独的作者实例是唯一可行的选项。 应将总体开发工作量的增加与基础架构和许可成本的节省进行比较,以确定此方法是否最适合。

开发技术 development-techniques

管理依赖关系 managing-dependencies

在管理Maven项目依赖项时,所有团队务必要在服务器上使用相同版本的给定OSGi捆绑包。 为了说明当Maven项目管理不善时可能出现什么问题,我们举了一个示例:

项目A依赖于foo库1.0版;foo 1.0版嵌入到其到服务器的部署中。 项目B依赖于foo库1.1版本;foo 1.1版本嵌入到其部署中。

此外,我们还假定此库中的API在版本1.0到版本1.1之间发生了更改。此时,这两个项目中的其中一个将不再正常工作。

要解决此问题,我们建议将所有Maven项目设为一个父级反应栈项目的子级。 此Reactor项目有两个用途:如果需要,允许一起构建和部署所有项目,并且包含所有子项目的依赖关系声明。 父项目定义依赖项及其版本,而子项目仅声明它们所需的依赖项,从父项目继承版本。

在此方案中,如果处理项目B的团队需要foo版本1.1中的功能,那么在开发环境中,此更改将很快中断项目A。此时,团队可以讨论此更改,并使项目A与新版本兼容,或者为项目B寻找替代解决方案。

请注意,这并不排除这些团队共享此依赖关系的必要性,它只是快速及早地突出显示问题,以便团队可以讨论任何风险并商定解决方案。

防止代码重复 preventing-code-duplication-nbsp-br

在处理多个项目时,请务必确保代码不重复。 代码复制会增加出现缺陷的可能性、更改系统的成本以及代码库中的整体刚度。 要防止重复,请将公共逻辑重构为可跨多个项目使用的可重用库。

为了满足此需求,我们建议开发和维护所有团队都可以依赖并参与的核心项目。 在执行此操作时,请务必确保此核心项目反过来不依赖于任何单个团队的项目;这样可以在促进代码重用的同时实现独立部署。

核心模块中常见的一些代码示例包括:

  • 系统范围的配置,例如:

    • OSGi配置
    • Servlet过滤器
    • ResourceResolver映射
    • Sling转换器管道
    • 错误处理程序(或使用ACS AEM Commons错误页处理程序1)
    • 用于权限敏感型缓存的授权servlet
  • 实用程序类

  • 核心业务逻辑

  • 第三方集成逻辑

  • 创作UI叠加图

  • 创作所需的其他自定义项,如自定义构件

  • 工作流启动器

  • 跨站点使用的常见设计元素

模块化项目体系结构

这并不能消除多个团队依赖同一组代码并可能需要更新同一组代码的需求。 通过创建核心项目,我们减小了团队之间共享的代码库大小,从而减少了对共享资源的需求,但并未消除对共享资源的需求。

为了确保对此核心包所做的更改不会中断系统的功能,我们建议由高级开发人员或开发人员团队进行监督。 一种选择是让一个团队管理此包的所有更改;另一种选择是让团队提交由这些资源审查和合并的拉取请求。 重要的是,治理模型要由团队设计和同意,并且开发人员应遵循该模型。

管理部署范围 managing-deployment-scope

由于不同的团队将其代码部署到同一存储库,因此它们不会覆盖彼此的更改非常重要。 AEM提供了一种在部署内容包(即过滤器)时控制此操作的机制。 xml文件。 过滤器之间不应重叠,这一点很重要。 xml文件,否则,一个团队的部署可能会擦除另一个团队以前的部署。 要说明这一点,请参阅以下精心编制的过滤器文件与有问题的过滤器文件的示例:

/apps/my-company与/apps/my-company/my-site

/etc/clientlibs/my-company与/etc/clientlibs/my-company/my-site

/etc/designs/my-company与/etc/designs/my-company/my-site

如果每个团队明确将其过滤器文件向下配置到他们正在处理的站点,则每个团队可以独立部署其组件、客户端库和站点设计,而无需擦除彼此的更改。

由于这是全局系统路径而不是特定于某个站点,因此应将以下servlet包含在核心项目中,因为此处所做的更改可能会影响任何团队:

/apps/sling/servlet/errorhandler

叠加 overlays

叠加经常用于扩展或替换现成的AEM功能,但使用叠加会影响整个AEM应用程序(即,任何叠加的功能更改均可用于所有租户)。 如果租户对覆盖层的要求不同,情况会更加复杂。 理想情况下,业务组应该一起工作以就AEM管理控制台的功能和外观达成一致。

如果不同业务部门之间无法达成共识,可能的解决方案是根本不使用叠加。 相反,请创建功能的自定义副本,并通过每个租户的不同路径公开该副本。 这允许每个租户具有完全不同的用户体验,但这种方法也会增加实施和后续升级工作的成本。

工作流启动器 workflow-launchers

在存储库中进行指定的更改时,AEM会使用工作流启动器自动触发工作流执行。 AEM提供了多个现成的启动器,例如,用于针对新的和更新的资源执行演绎版生成和元数据提取过程。 虽然这些启动器可以保持原样,但在多租户环境中,如果租户具有不同的启动器和/或工作流模型要求,则可能需要为每个租户创建和维护单个启动器。 这些启动器需要配置为在其租户的更新上执行,同时保持其他租户的内容不变。 通过将启动器应用到特定于租户的指定存储库路径,可轻松实现此目标。

虚 URL vanity-urls

AEM提供了虚名URL功能,可以根据每个页面进行设置。 在多租户场景中,此方法关心的是,AEM无法确保以这种方式配置的虚名URL之间的唯一性。 如果两个不同的用户为不同的页面配置相同的虚路径,则可能会遇到意外行为。 因此,我们建议在Apache Dispatcher实例中使用mod_rewrite规则,这些规则允许将配置中心点与仅出站资源解析程序规则结合使用。

组件组 component-groups

在为多个创作组开发组件和模板时,请务必有效使用componentGroup和allowedPaths属性。 通过将这些组件有效地与站点设计结合使用,我们可以确保品牌A的作者只能看到为其站点创建的组件和模板,而品牌B的作者只能看到其组件和模板。

测试 testing

虽然良好的架构和开放的通信渠道有助于防止将缺陷引入站点的意外区域,但这些方法并非万无一失。 因此,在将任何内容发布到生产环境之前,必须完全测试平台上正在部署的内容。 这要求各团队在其发布周期中进行协调,并强化了使用尽可能多功能的一套自动化测试的需求。 此外,由于一个系统由多个团队共享,因此性能、安全性和负载测试比以往任何时候都更加重要。

操作注意事项 operational-considerations

共享资源 shared-resources

AEM在单个JVM中运行;任何部署的AEM应用程序除了在AEM的正常运行中已占用的资源之外,还会彼此固有地共享资源。 在JVM空间本身内,线程没有逻辑分离,并且AEM可用的有限资源(如内存、CPU和磁盘I/O)也共享。 任何占用资源的租户都不可避免的会影响到其他系统租户。

性能 performance

如果不遵循AEM最佳实践,则可以开发一些使用超出正常范围的资源的应用程序。 例如,触发许多繁重的工作流操作(如DAM更新资产)、对许多节点使用MSM推送修改操作或使用昂贵的JCR查询实时呈现内容。 这些不可避免地会对其他租户应用程序的性能产生影响。

日志记录 logging

AEM为强大的记录器配置提供了现成的界面,利用这些界面可在共享开发环境中发挥我们的优势。 通过为每个品牌指定单独的记录器,根据包名称,我们可以实现一定程度的日志分离。 虽然系统范围内的操作(如复制和身份验证)仍会记录到中央位置,但非共享自定义代码可以单独记录,从而简化每个品牌技术团队的监控和调试工作。

备份和恢复 backup-and-restore

由于JCR存储库的性质,传统备份在整个存储库中工作,而不是在单个内容路径中工作。 因此,不可能根据租户轻松分离备份。 相反,从备份中恢复将回滚系统中所有租户的内容和存储库节点。 虽然可以使用VLT等工具执行目标内容备份,或者通过在单独的环境中构建包来挑选要恢复的内容,但是
方法不容易包含配置设置或应用程序逻辑,并且管理起来可能比较麻烦。

安全性注意事项 security-considerations

ACL acls

当然,可以使用访问控制列表(ACL)来控制谁有权根据内容路径查看、创建和删除内容,这需要创建和管理用户组。 维护ACL和组的困难取决于强调确保每个租户对其他人的了解为零以及部署的应用程序是否依赖共享资源。 为确保ACL、用户和组的高效管理,我们建议建立一个具有必要监督的集中式组,以确保这些访问控制和主体以可提高效率和安全性的方式重叠(或不重叠)。

recommendation-more-help
a483189e-e5e6-49b5-a6dd-9c16d9dc0519