今天,对软件的需求变化比以往任何时候都快。这就要求有一个合适的架构来实现灵活的变更。然而,考虑到Web应用的角度,灵活性往往受到阻碍。随着时间的推移,各种意想不到的依赖关系会使架构看起来像一个大泥球(Big Ball of Mud,BBoM)。
类似BBoM的庞大单体架构显示出的复杂性急剧增加。这需要各个团队之间的协调努力,才不会导致生产力降低。作为对策,企业引入了Scrum敏捷方法来优化他们的软件工程流程。但是,经常缺乏技术自主权。
1
敏捷性和微服务
在敏捷软件开发中,一个理想的架构足够灵活,可以处理快速调整的需求。遵循敏捷宣言的原则,最好的架构以功能需求驱动的方式出现。但架构也需要前期设计的努力,以实现预期的灵活性。由于需求的不确定性,严格的瀑布式的前期大型设计(Big Design Upfront ,BDUF)被忽略了。BDUF不适合大量连贯工作量的敏捷思想,也称为the batch size。
微服务方法限制了batch size,因为每一个微服务只涵盖整个应用的一部分。所有部分共同涵盖不同的业务功能,例如在电商应用中显示产品的详细信息。重要的一点是,单一业务能力的责任转移到一个需要跨职能一致和需要DevOps文化的团队。
因此,微服务是一个模块化的概念,可以解释技术层面和组织层面。这个想法是围绕清晰分离的业务能力建模一个架构,每个业务能力都是作为一个微服务实现的。通过实施自己的架构与系统的其他部分分离,允许建立大规模的软件增量与小型和独立的团队。微服务最适宜的企业是,旨在缩短业务上线时间,但无法应对当前架构和组织结构快速变化需求的那些企业。
向微服务迁移有许多挑战。以下提供了从BBoM引入微服务的几点指南。
2
微服务迁移的六大影响因素
向微服务的迁移可以完全脱离,也依赖于单体(因素1)。关键的决定是,目标架构的微服务是否包含自己的前端(frontend)(因素2)。在这个阶段,技术和组织方面之间的相互作用已经变得明确。当涉及从巨石中分离出第一个微服务时,应该确保底层的新模型不会被旧的破坏(因素3)。运维中的迁移应该考虑风险,并采取适当的措施(因素4)。通过自动化过程来支持(因素5)。把适当的工作放在优先位置。所需的透明度通过敏捷的组织文化来建立。将敏捷转换与微服务迁移结合起来会带来额外的挑战(因素6)。
1
改变
人们经常认为,完全重写应用程序是充满风险的。但是这个应用程序的发布并不是以一个Big Bang的方式来完成的。相反,可以选择渐进的方法。但是,巨石应用和微服务一起构成应用程序的“微服务 – 单体 - 混合”架构往往是不可避免的。特别是如果有竞争的压力,新的特性必须不断传递给客户,那么混合是唯一的解决方案。迁移是一个长期的过程,可以持续2年以上。
为了缩短应用程序处于混合状态的时间,建议将迁移视为变化的机会。在这种情况下,改变意味着实施新的要求,而且接受现有功能的遗漏。一方面,考虑迁移的应用程序是旧的应用程序的准确副本,减少迁移工作是明智的。另一方面,提供不适用于旧技术堆栈的新功能增强利益相关方的信任。这种迁移可以视为进步而并非停滞。
2
系统分解
有两个必须考虑的决定。首先,是否通过使用现有的代码库或者完全重写功能来提取微服务。其次,定义目标架构,并且必须做出决定,微服务是自带前端,还是多个微服务集成在一个UI单体中。
当使用现有的代码库时,该代码库的副本就是跳板。那么给定的部分已经表现出高度的自主性。而且,当项目范围局限于较少人数开发应用时,这种方法可能会取得成功。当挑战是将多个团队分离时,建议将微服务定义为自己的前端。
图1:2层微服务 VS 全堆栈微服务
这需要进一步讨论如何解释微服务的层次。关于三层架构,可以区分两种微服务类型。一方面是只包含数据和应用程序层的微服务(图1)。另一方面还有从数据层到表现层的微服务。
图2:UI-monolith 与 UI-fragments
当使用“2层微服务”时,在建立前端的这种多微服务时建立了一个UI单体。这带来了将微服务整合到同一个前端的耦合团队的风险。相比之下,提供自己的前端部分的“全栈微服务”(例如UI碎片)则为团队提供了更高程度的自主权(图2)。
3
模型边界保护
作为一个起点,建议从中等复杂度的单个上下文开始。这样做的时候,保护即将实现这个上下文的微服务底层模型很重要。因此,应该规定一条规则,即禁止通过数据层访问(如JDBC或直接API调用)从整体数据访问数据。相反,数据应该从后台异步传输到后台的微服务,同时还要在新旧模式之间进行转换。这可以看作两个数据存储的同步,并符合构建防腐层(ACL)的思想,这是一个域驱动设计(DDD)的概念。在这种情况下,ACL可以作为微服务和巨石的模型完整性保护器(图3)。
图3:ACL作为微服务和单体之间的边界
4
风险监测
任何迁移都有风险。特别是在进行完全重写时,如果新应用程序与现有应用程序相比得到相同的结果,则应使用与业务相关的度量标准(如营业额)进行衡量。然后,通过逐渐将新应用交付给越来越多的客户,控制经济风险。在这一点上,应该考虑诸如Canary Releasing的部署策略。
另外,建议在生产环境中测试微服务,然后再将其推广给客户。这可以通过向微服务提供请求并完全观察他们的行为Shadow Traffic来实现。性能问题可以在不影响应用程序的情况下展开,因为各自的响应被省略。这种做法是由两位专家和文献描述的。
其他措施也可以支持降低云服务迁移过程中的风险。使用诸如特性切换之类的机制在旧的和新的实现之间切换。它们提供了灵活性,仅通过更改配置来控制这一点,而无需重新部署整个应用程序。
5
自动化和测试
为了减少TTM(上市时间),作为微服务的部署流水线,建议将价值流建模和自动化。在这里,要考虑从代码提交到部署构建的每一步。这确保部署可以经常进行。此外,这从一开始就支持高度的测试覆盖,因为测试也是该流水线的一部分。
在考虑自动化测试时,专家会参考所谓的自动化测试金字塔。测试金字塔由三个测试层组成:单元,服务和UI测试。每层测试的数量减少,导致金字塔形状--许多单元测试和少量UI测试。为了确保多个微服务如预期的那样相互整合,依靠UI测试是合理的。但UI测试对于开发和维护来说是脆弱和昂贵的。这就是为什么在没有UI的情况下单独进行测试非常重要:使用模拟对象自主地测试微服务。借助模拟对象,可以模拟与其他微服务或巨石应用的交互。相应的测试被称为,自动测试金字塔内的服务级别测试。
6
敏捷转型
引入敏捷方法并立即迁移到微服务是巨大的变化。因此,建议将其分成几个步骤,并寻求逐渐改变。否则动机和定向障碍的风险太高。通过引入Scrum这样的敏捷方法,理想的微服务出现,是随着时间的推移争取团队的自主性。
尽管Scrum主要是在一个跨职能和以产品为中心的团队中解决软件开发过程,大规模的组织也需要采用。Scrum没有提供解决多个敏捷团队协调的解决方案。还有一些坚定的观点认为,对于大型项目来说,应该避免使用灵活的方法来分割产品。随着时间的推移,出现了不同的Scrum和敏捷方法扩展方法。例如,LeSS(大规模Scrum),Nexus和SAFe(缩放敏捷框架)是根据其市场份额为大型组织提供敏捷性的相关方法。
在更大的组织环境中建立敏捷方法时,建议先从一个团队开始,然后再增加越来越多的团队。同样在LeSS中,这被描述为耗时,但却是以功能为中心的团队,同时打破功能孤岛的安全方式。
透明度
此外,建议记录产生的非功能性工作,例如在积压工作中实施ACL,并合理安排其他要求。在SAFe中,引入了可以代表上述技术和机制的实施以及迁移工作的推动者的故事。它们确保了透明度,展现了业务与IT之间潜在的相互依赖关系。因此,应根据2位专家的建议,与企业和技术负责人进行优先排序。
图4:敏捷和微服务之路
3
总结
微服务包含组织层面和技术方面。这就是为什么引入微服务涉及两种情况下的措施。如果没有单体考虑,微服务的好处是脆弱的。从纯粹的技术角度来看,微服务可以使用瀑布式软件工程方法来实现。但是,为了充分发挥每个微服务的自主性,它们被嵌入到敏捷文化中。
特别是,拥有多个团队的组织可以从微服务的非技术方面获益。从数据层向前端分解一个系统,将团队分离开来。因此,如果多个团队使用一个前端开发应用程序,那么团队边界在架构中反映最好。这些团队可以自主地加速应用程序的部分。在单体应用程序和分层的团队中,这是更困难的。在这里,复杂的依赖需要协调跨越团队边界的活动。因此TTM下降。
由于敏捷团队由开发人员和非技术人员组成,因此IT和业务需要携手合作。微服务的出现是由于敏捷团队争取自主权。当团队决定转向微服务时,迁移本身没有任何价值,可以向客户交付新功能。尽管如此,微服务迁移工作仍需要优先考虑。这需要透明度。只有不断提高透明度,敏捷性和微服务才能彼此加速。否则,长期不会降低TTM的风险很高。
为了避免在引入微服务时构建未来的传统软件,建立敏捷思维和不断重新思考解决方案很重要。
博客:http://www.coder306.cn
想获取更多更有价值的内容请扫描下方二维码加以关注
网友评论