微服务中「组件」集成

有品:There is no silver bullet;

一、简介

在微服务工程的技术选型中,会涉及到很多组件的集成,最常用包括:缓存、消息队列、搜索、定时任务、存储等几个方面;

如果工程是单服务,对于集成组件的管理来说并不算复杂;但是在分布式的多服务系统中,随着拆分的服务数量上升,统一管理各种组件的复杂度也会提高;

如上图,是团队内部维护的一份重要的系统清单:描述整个微服务体系中核心组件的依赖情况;【并不完整】

在整个工程内部拆分了几十个服务,基于一份系统架构图和一份组件依赖清单,如果熟悉微服务架构模式,可以非常快速的了解系统的基础原理和结构;

复杂系统对于中间件的依赖很重,需要在实践过程中不断的积累和总结经验,持续优化各种组件的应用策略;

对于组件来说,与项目工程的集成模式,核心的应用场景,以及在业务场景中的迭代优化,是研发需要重点关注的方面;

二、缓存管理

【集成模式】

Redis作为最常见的缓存选型,在与分布式工程集成时,其形式也存在很大的灵活度;

单服务:在分布式工程中,如果服务使用独立的Redis组件,通常是该服务支持的业务场景比较独特,比如高并发或者数据体量较大等;

分布式服务:微服务常见的集成方式,不同的服务使用同一个Redis的不同DB编号,其他服务必须通过该服务的接口访问其缓存数据;

缓存中心:整个工程基于一个缓存中心服务来管理,其适配的业务场景比较特殊,多个服务紧密协作,调度和处理相同的数据主体;

在实际的分布式系统中,通常是模式一模式二两种都采用,而模式三更多的是应对特殊的需求场景;

【应用方式】

虽然Redis可以极大的提升效率,但是在实际的应用中,涉及最多的就是数据缓存和加锁两个核心能力,对于组件的API使用并不算复杂;

无论是在框架层面的浅封装一层,还是围绕Redis组件编写常用的工具方法,都可以很好的实现工程和Redis相关API之间的解耦;不同服务之间缓存数据获取,需要通过各个服务提供的接口进行查询;

三、消息队列

【集成模式】

Kafka作为消息队列的常见技术选型,在与分布式工程集成时,在设计上会围绕消息生产和消费的基本模式;

服务内集成:在各个服务内部直接引入消息组件,服务可能是消息生产者也可能是消费者,当重度依赖消息通信时,流程可维护性比较差;

消息服务封装:单独封装消息生产消费两个服务,来统一调度和管理消息通信,虽然提高了技术面的复杂度,但是极大降低了异步流程的管理难度;

在实际应用时,如果工程内对于消息的使用并不高频,通常是采用模式一的策略,建议做好流程注释和文档维护;如果消息使用非常高频,可以考虑模式二的策略,减轻组件维护的难度;

【应用方式】

生产和消费能力追求平衡,即便有偏差也只能是消息的【消费】大于【生产】的效率,才能避免消息堆积从而影响正常的业务流程;

实践来看单纯的基于MQ的重试机制,并不能稳定的解决分布式架构中复杂流程的中断问题,需要围绕消息的存储设计相应的调度策略,从而推动整个流程的完整执行,无论是向下推进还是向前回滚;

四、搜索引擎

【集成模式】

对于搜索引擎Elasticsearch来说,个人感觉在常规业务场景中是最容易出问题的组件,使用ES索引的数据模型,通常结构复杂并且数据体量偏大,还涉及到大量的检索条件;

服务内管理索引和数据:通常是核心的业务场景,对数据的实时性要求极高,从常规的架构设计来考虑,虽然索引相关的结构和数据可能来自多个数据库,但是其管理的接口会统一封装在业务联系最密切的服务内;

独立组件管理索引数据:基于独立的组件(常用Logstash)进行调度,动态地采集、转换和传输数据,不受格式或复杂度的影响,数据往往以各种各样的形式,或分散或集中地存在于很多系统中;

无论是模式一还是模式二,都是ES常用的集成策略,比如模式一对于核心数据模型的构建,常见于订单或商品等,模式二的经典用法之一ELK日志采集等;

【应用方式】

以服务内部管理索引的方式来说,多数情况下索引的结构会不断的扩展,结构更新必然也会引起数据和检索条件的同步更新,如果是结构新增的方式更新,管理难度并不大,但是已有字段的类型更新,还需要索引重建;

对于ES这种操作起来比较复杂的技术组件,建议是把各种常用的操作编写程序脚本来处理,并且开发相应的管理功能,用更加稳定可控的方式来管理索引的结构和数据调度;

五、定时任务

【集成模式】

Quartz任务调度组件,在分布式系统中并不算复杂,基于定时器去触发各种任务执行即可;

服务内构建定时器:在一些简单的相对独立的服务中,可以在服务内配置定时器,去执行相应的任务流程,这种模式在复杂的分布式系统中很难维护;

独立的任务调度服务:可以统一管理任务的调度策略和执行方式(比如同步或异步),同时对任务调度服务进行监控和维护,以此确保任务调度系统的稳定性和可靠性;

通常模式一只会在个别独立的服务中采用,对于模式二来说,封装独立的任务调度服务,可以统一与其他服务进行集成或者通信,比如通过消息服务及时通知失败的任务等;

【应用方式】

在任务调度服务中,难免要和其他服务进行通信交互,从而触发相关任务的执行,如果系统内部定时任务不多的话,可以采用feign接口的方式触发,如果任务非常多,可以考虑直接构建Http请求的方式,避免服务频繁的升级迭代;

在调度任务中可能存在数据体量比较大的场景,通常就是采用分片算法加线程池并发处理的策略,但是前提也要优化好数据查询和任务处理流程,从整体上提升任务的执行效率;

六、数据存储

【集成模式】

以MySQL为代表的数据存储是系统中最核心的一层,其集成的形式也是灵活多变,与存储层相关的组件更是五花八门;

多服务共用数据库:对于模式一来说,在相对简单的系统中比较常用,或者服务和数据库本身偏向通用的功能性质,可以采用这种策略;

服务和库的拆分模式二是分布式架构中最常用的设计,每个服务都具有自己相应的独立数据库,其他服务想要访问必须通过调用相应服务提供的接口才可以;

多数据源模式:在一个服务内集成多个数据源,像模式三读写分离和模式四分库分表,这是偏数据服务的业务场景中经常使用的模式;

对于系统中的数据源管理本身就是一件复杂的事情,需要兼顾各个方面,比如数据读写性能,数据安全,以及服务的稳定性等;

【应用方式】

在常规的微服务工程中,通常每个服务都会使用各自独立的数据库,在多数据源的集成模式中,常用的逻辑就是动态路由、读写分离、分库分表等,如果逻辑简单可以自定义封装,如果逻辑复杂可以使用成熟的组件;

服务集成多数据源的模式中,存在一个比较明显的复杂问题,如何在不停止服务的情况下,进行数据源的动态管理,此前实践过的模式:提供不同数据源的适配服务来实现各自的策略,在完成数据源的动态调整后,停止其中旧服务即可,虽然流程偏重偏复杂,但是稳定可靠;

七、参考源码

编程文档:
https://gitee.com/cicadasmile/butte-java-note

应用仓库:
https://gitee.com/cicadasmile/butte-flyer-parent

热门相关:亿万盛宠只为你   朕是红颜祸水   小姑子的味道2   幸福泌尿科3   二十岁2001