在具备底层通用技术服务和中端业务服务能力后,可以基于可复用服务快速构建上层应用,但不可能所有场景都简单而且简单可以通过调用一个API接口服务来实现。当有一定的业务规则需要处理时,往往会涉及到调用多个API接口服务,中间还涉及到基本的逻辑处理,往往是判断分支完成。如果让前端应用开发来处理这种事情,就变成需要写大量的脚本代码,并且存在公共领域服务逻辑外泄的问题。服务编排实际上是将基本的业务流程、步骤、规则逻辑进行封装,然后为前端应用开发提供封装后的组合服务或领域服务API接口能力。这与传统SOA架构中提到的通过BPEL编排SOA服务的思想是完全一致的。目前微服务编排引擎的来源对于开源的微服务编排引擎,大家比较熟悉的第一个就是NetflixConductor。我在之前的文章中也写过一篇分析解释,不过这个开源版本本身更多是面向开发者的。难以实现灵活的前端可视化配置,没有可视化设计能力,只有编排完成后的可视化监控。从目前一些主流的微服务编排引擎来看,主要包括以下几类发展演进。一种是在传统工作流引擎或BPM引擎的积累上构建微服务编排引擎,比如目前开源的Zeebe,其开发团队来自知名的Activiti工作流和BPM引擎。二是传统ESB服务总线的上层,它对ESB总线本身具有轻量级的服务编排功能,所以微服务编排引擎是从ESB总线发展起来的。三是基于分布式任务调度系统和自动化事件触发编排开发的微服务编排引擎。应该明白,微服务编排的最终核心还是各种活动或任务的处理。类似于目前在物联网领域广泛使用的Node-Red编排引擎,属于这种方式。如何理解微服务编排场景?当我重新思考这个问题时,我对编排场景进行了进一步的分类和理解。首先第一类是简单的服务组合、服务拆分、数据裁剪、数据映射等,这些内容可以通过服务编排来解决,比如输入一个供应商代码,同时调用两个API接口服务,一个一是查询供应商基本信息,一是查询供应商的订单明细列表信息。调用返回后,将结果集成为Json输出给调用方。对于这类场景,它其实对应的是传统ESB的轻量级服务编排能力,不涉及复杂的业务规则、业务逻辑处理、类似BPEL的自动化业务流处理。二是基于业务流程的多个服务的编排和处理。这种场景与传统SOA架构中的BPEL非常相似。要完成一个业务功能,你会发现需要调用多个接口来完成,而这些API接口的调用本身是有顺序关系的,包括调用逻辑和分支判断。上游API接口服务的输出往往成为下游API服务的输入,形成一个核心的串行逻辑结构。因此,需要通过一个编排功能,将多个服务编排在一起,最终暴露出一个服务。这类场景的典型例子是前端功能的实现。完成相关书籍的录入后,点击一个按钮触发一个事件。传统的代码开发方式必须在按钮触发事件方法中编写具体的代码实现逻辑。这个逻辑本身也涉及调用多个API接口服务,当然也有分支判断逻辑。在新的低代码开发或者serverless下,我们希望点击代码只需要调用一个编排好的组合服务能力。前端开发者无需了解内部多个API服务编排组合的规则逻辑。那么在这种场景下,就需要通过微服务编排引擎,形成一个复合服务API,然后暴露给前端应用。我们最近做了什么?最近在实现微服务编排能力的时候,前期进行??了大量的模型选择。最早的计划是从零开始,基于现有的图形化设计器构建一个服务编排引擎。.但是,分析完成后,从头开始还是有难度的。不仅仅是API服务本身的组装、拆分、规则逻辑处理,更重要的是底层需要一个完整的任务调度引擎或者事件处理引擎。对于消费者系统,你看到的是一个组合服务API,但内部本身是由多个服务组合而成,组合完成,内部就变成了一个消息或事件驱动的异步处理系统。所以在这个过程中,需要处理任务调度、异常容错、分布式事务和回滚机制。从头开始实现所有这些底层逻辑仍然很困难。Node-RED是一种基于流的编程工具,具有可视化编辑器,允许将节点连接在一起以创建流。满足微服务编排最基本的可视化服务编排需求。Node-RED最初是IBM于2013年底开发的一个开源项目,以满足他们将硬件和设备快速连接到Web服务和其他软件的需求——作为物联网的粘合剂,它迅速发展成为一个通用物联网编程工具。因此,经过选择,我们最终选择了Node-Red来实现微服务编排。当时我们规划的接口服务有串行、并行,可以实现数据合并集成、规则处理、异常捕获、日志记录等需求。一般来说,Node-Red处理的是简单的服务组装,组装起来没有问题。但是如果有像BPEL这样的自动化业务流处理,还是不太适合。毕竟开源项目Node-Red的目的还是处理IoT领域常见的任务和事件处理,专注于多个任务或事件的编排,而不是类似业务系统开发中的流程编排功能。微服务下HttpAPI接口布局的要点这里所说的微服务布局,更多的是指微服务对外暴露的HttpAPI接口的可视化布局和组装。这是讲这一点的前提。对于微服务编排引擎底层,我们已经提到,重点是消息中间件、分布式任务调度与执行逻辑、状态机等,那么在微服务API编排时需要具备或扩展哪些关键能力呢?这个底层逻辑,初步思路如下。一是Json格式的处理。也就是说,业务编排中经常会遇到Json格式的拆分、合并、数据映射等操作。编排引擎在这方面必须非常灵活。Json格式的字符串本身也是有规则的,可以模板化,模板化后才方便处理。同时,一个Http接口调用本身就有输入,输入的内容可能会在后续的多个编排节点中使用,所以也需要支持对输入信息进行参数化处理。这些参数是整个组合服务运行实例中的全局参数,可供后续任意节点引用。比如在获取订单信息时,我们希望同时返回该订单对应的供应商的基本信息。即先调用获取订单信息,获取供应商代码后,再调用获取供应商信息。最好将供应商信息结果组装成整个订单信息返回。//调用GetOrderInfo获取Order信息//根据返回的supplierid发起调用GetSuplier接口//将返回的信息组装成完整的Json作为子对象orderInfo{orderidordernamesupplierid{suppliername:suppliertype:address:contactphone:}}可以看出,编排时同时调用多个API接口并不难。难点在于如何完成结果的映射和快速灵活的组装。这种能力更为关键。在传统的SOA服务编排中,往往会使用类似的Xslt模板来完成数据的映射、组装等操作。这种参数化模板映射的思路可以借鉴。二是业务规则和逻辑处理。在传统的SOA服务组装中,一般会结合BPEL和规则引擎来实现复杂的业务规则和逻辑处理。至于微服务编排,是一种轻量级的编排,不适合处理过于复杂的业务规则和逻辑。所以在服务的可视化编排上,可以支持最简单的分支判断逻辑,条件组合逻辑就足够了。对于更复杂的逻辑,建议先实现一个原子服务API接口进行规则处理,再应用到微服务编排中。对于低代码开发平台的应用,前面我也提到了这个观点。即首先,低代码开发平台应该基于服务分层的思想,将前端开发与后端服务能力区分开来,通过服务层进行彻底解耦。二是在服务层提供可视化服务编排能力,为前端应用调用提供编排组合服务,降低前端应用调用难度。但是,如果有复杂的业务规则处理逻辑,则不应该在服务编排中处理,或者单独实现一个规则处理API接口服务,暴露给上层应用或编排设计者。三是分布式事务处理机制由于多个微服务API接口服务的编排,必然会产生分布式事务问题。现在的编排技术本身其实是针对完全同步的等待方式和异步类任务的事件和状态机处理机制。之前我们谈到了两种情况。如果是简单的服务组合和拆分,可以使用同步方式。但如果是类似业务流程处理的多个服务的串行排列,建议使用异步任务事件处理机制。底层还需要消息中间件和中间数据存储机制的支持。在微服务编排的实际分布式事务处理中,最好的方式仍然是基于幂等规则的事务补偿。让我们举一个最简单的例子。保存订单时需要扣除库存。这次涉及到两个接口,SaveOrderAPI接口和FreezeStockAPI接口,还有对应的逆向操作接口ReleaseStockAPI,用于扣库存。那么你在安排微服务的时候,其实就需要安排这三个接口,还需要添加判断规则逻辑,即当SaveOrderAPI失败时,进行ReleaseStockAPI,库存扣减和回滚操作。那么有没有办法简化这个过程。也就是说,在涉及到分布式事务的场景下,我们需要配置这个服务的逆向操作,让任意一个API接口服务同时回滚API接口服务。然后,当下游服务运行异常时,整个微服务调度机制通过查询反向API接口,自动发起多个上游服务的回滚操作。如果回滚操作仍然失败,则发送异常处理通知或邮件通知人工干预。第四点是微服务链路监控。说到微服务,我们经常会说到微服务链路监控。简单来说就是前端调用一个按钮进行处理,但是按钮方法的实现逻辑可能会调用多个微服务API,所以需要对整个链路进行监控,方便分析性能问题和异常问题排查。使用微服务编排后,按钮原有的处理逻辑已经转换为微服务编排设计完成。一个编排好的微服务内部可能会调用多个微服务API接口,形成一条微服务API接口调用链。并且这个内容还需要提供完整的监控和日志查看能力。这类似于工作流引擎中的流程监控。也就是说,微服务编排也是一个流程,是一个自动化的业务流,中间调用了多个API接口服务。因此,需要对整个自动化业务流程进行端到端的监控。通过微服务流程实例进入后,可以详细的看到当前正在执行哪个环节,如果有异常可以快速查看具体的错误异常日志。
