上下文
假设我们有一个拥有多个业务的组织。在本例中,业务A向大学生销售千兆位互联网服务。业务B向老年人销售兆位互联网服务。这些业务销售的相关产品略有不同,每个业务针对不同的人群。
乍看之下,我们似乎可以让一个应用程序处理所有的请求。然而,考虑到每个业务都针对特定的人口统计,它们之间的差异是很自然的--从本质上讲,每个业务都有自己的业务需求。例如,企业A可能会公开一个移动的应用程序,以便客户管理其帐户。企业B可能会公开一个电话号码,客户必须拨打该号码才能管理他们的账户,这样的例子不胜枚举。
在这种情况下,利用微服务的最佳方式是什么?
问题在于,不同的业务中既有常见的功能,也有不常见的功能。
我们可以保持一定程度的DRY,并拥有一组基本微服务(billing-api、order-api等)。这是可行的,但是这导致微服务具有更“一般”的抽象-导致更复杂。假设billing-api服务有一个由企业A和B共享的/charge端点。企业B的要求是始终从订单中扣除5美元:
//billing-api
if (businessB) {
orderCost -= 5;
}
在这个DRY方法中,我们将为每个业务(BFF模式)提供一个API网关,它将聚合不同的微服务来满足它们的业务需求。所有“特定于业务”的逻辑将从基本微服务移动到各自业务的API网关中。在这个折扣示例中,我们可以将此控制反转给消费者,而不是在计费API端点中进行if (businessB)
检查:
//billing-api
const { orderDiscountAmount } = req.body; //body parameters
if (orderDiscountAmount > 0) {
orderCost -= orderDiscountAmount;
}
然后,当调用billing-api端点时,业务B的API网关中的端点将传入orderDiscountAmount 5:
//Business B API Gateway
billingApi({ orderDiscountAmount: 5 });
这看起来不错,但我们所做的只是在计费API端点中使用业务B的逻辑,并创建了一个通用(但强制的)抽象。这是“合理的”,因为业务A可能有一天会使用它-但这可能永远不会真正发生。总的来说,这对端点的开发者和消费者来说感觉像是一个不自然的练习。复杂性和各方的认知负荷都增加了。
我们可以放弃DRY,避免在企业之间共享微服务,以获得最大的灵活性和简单性。然而,如果增加更多的企业(10-20个),那么可能会有大量重复的功能。
在这种情况下,应如何组织团队?
如果我们同意上面的DRY方法,那么团队应该如何组织呢?我们可以有垂直划分的功能团队,但是这是否意味着如果我们有10个业务,团队需要拥有一个功能这种方法的缺点是,功能团队不会成为任何业务领域的Maven--这些团队只能是一个特定业务中的一个特性的Maven。2没有对一个业务的完整背景的了解会使它很难做出正确的决定。
我们可以为每个业务建立一个专门负责UI和API网关的流对齐团队。然后,我们将让平台团队为流对齐团队创建微服务。这样做的缺点是,在流对齐团队和平台团队之间存在一个交接步骤,也就是依赖关系。
我不确定我是否从错误的透镜看待这一切-任何反馈都将不胜感激!
1条答案
按热度按时间inn6fuwd1#
很抱歉,但这不是一个适合Stackoverflow的问题,因为任何答案都是基于观点的,许多方法都可能奏效,并取决于您特定用例的更多细节。所以,如果问题在某个时候被关闭,不要失望。
话虽如此,我并不羞于提供我的意见或至少一些想法对您所描述的情况。
1.我相信你提出的如何建立团队的问题和如何建立架构是紧密联系在一起的,因为架构毫无疑问会有效地跟随组织结构,所以我先对组织结构给予进一步的思考。
1.对每个业务所需的总人力的估计应该会给予你知道你需要多少个团队。尽量保持团队规模较小(比如2-8人)将有助于减少沟通开销。所以如果你认为这是整个业务的规模,那么就没有必要进一步划分责任。
1.职责是最重要的关键字。您必须避免使用公用服务/程序库但拥有多个拥有者或没有拥有者的情况。组织拥有者应该始终只有一个。因此,当组织认识到不同领域的功能重叠时,通常的做法是建立一个团队来负责并将此功能提供给其他人。这可以是共享库的形式,也可以是实际部署的服务的形式,在这两种情况下,重要的是,通过正确地对他们的工作进行版本控制,这种方法将分离使用这种公共功能的团队。
1.在你的问题描述中,问题的核心是业务逻辑,它是复杂的/重叠的。所以我认为最重要的角色是产品管理。他们必须非常好(至少有一点技术性)并将这些混乱的东西整理成可重用的部分和特定于单个业务的东西。如果你有一个完整的产品经理团队,他们需要很好地沟通,并共同构建这一图景。这里最重要的是就未来的 * 愿景 * 进行良好的沟通,而不仅仅是眼前的需求(提供一个很棒的 * 域视图 *)。只有这样,架构和团队才能以最好的方式建立起来。
1.无论初始设置有多仔细,都会发生变化。无论你一开始认为什么是最好的解决方案,在未来的某个时刻都会发生变化。为了做好准备,我总是建议使用最简单的方法--即使这意味着一些代码重复或其他不完善之处。作为软件架构师,我们往往喜欢完美之美。但这在真实的世界中很少是最有效的方法。
1.通过添加一些可配置性来创建一个简单的共享服务/库以适应多种用例是一种常识,但是您必须对库/服务的使用者敏感,并且它应该易于在任何时候重用。复杂,必须拆分为多个部分才能维护,但是从维护者和使用者的Angular 来看,会使决定变得更容易。在可配置服务库的情况下,您还可以使用不同配置进行单独部署,因此使用共同开发的组件,但是为每个用例部署不同的端点。(例如只有几MB的Golang容器),则大量部署的服务不是缺点而是优点,因为它们可以被升级/并且可以轻松地并行运行多个版本。
1.基础设施和服务部署可能遵循也可能不遵循服务的体系结构,作为一般规则,我建议寻找最简单的方法,这通常意味着提供在服务和部署配置之间共享的通用基础架构,而部署配置是服务之间区别的起点。例如,所有服务共享一个通用集群/流/网关/数据库/等。例外情况可能是单个服务的非常特殊的需求,如硬件加密密钥存储或用于机器学习的GPU服务器等。这将是任何合理规模的系统的方法。(当然,如果您要扩展到非常大的规模,为特定服务提供完整的堆栈/集群也是一种非常可行的方法。)
1.持久性设计是最关键的。在发展业务逻辑、重新组织业务逻辑等相对容易的地方,发展历史数据就相当困难了。通常,您可以选择以下两种方式之一进行设计:
1.聪明的算法,愚蠢的数据。
1.聪明的数据,愚蠢的算法。
(Smart指的是更详细/反映更多的业务需求)第二种方法通常最初比较困难,但根据我的经验,当达到一定的复杂性阈值时会有更好的结果。
这些只是我在阅读您的问题时想到的几件事。很抱歉,他们无法回答您关于如何分割计费API的详细问题,但也许您手头还有一些额外的考虑因素。