为什么要拆分?
我们的服务平台运行的好好的,为什么要拆分呢?大家快快乐乐的做业务需求开发多好,按部就班的评需求、做设计、写代码、测试上线,间杂着产品、开发、测试之间的三国杀,喝着咖啡骂着资本家。
当有人提出要技术方案升级的时候,一定是有重大事情要发生。
比如说:
1、业务量即将暴涨;
2、前文分析的缺点暴露出了不可调解的问题;
3、产品部门有新的规划,技术侧需配合调整;
4、来了新的CTO,具备更长远的眼光;
5、业务发展不好,没有KPI输出;
6、没活干了,不忙起来老板要裁员。
怎么拆?
拆分原则,总体上有一些常规的指导思想。单体架构中,业务挤在一起的时候,也是区分了业务模块的,所以拆分的时候,第一直觉也是按照业务模块垂直拆分。存在业务拉扯的部分,需要各方讨论敲定。
常规原则如下:
1、单一职责:具有明确且单一的功能;
2、服务自治:服务的研发、部署互不影响;
3、无循环依赖:保证单向依赖,循环依赖说明服务拆分存在讨论点;
4、避免对现有业务影响;
5、可持续演进:服务拆分不是一步到位的,拆分完的服务也并不是一直不变的;
6、老子拳头大,就要这么分,怎么着?
按照前文分析的架构,支付服务中的接口功能,可以大致分为用户模块和交易模块。用户模块负责商户接入、业务开通、业务配置之类的业务;交易模块负责支付、退款、提现等带资金变动的业务。 拆分标记如下:
当然,实际支付服务肯定比这个复杂,我们只是拿其中比较突出的业务来做讲解。
拆分完大致是这样的场景,重新调整架构图如下:
可以看到,架构图中,新增了基础架构服务模块,其中包含的一些基础架构服务,将用来解决服务拆分带来的问题。
服务拆分带来的问题——对外
网关
使用单体架构时,对外的http接口统一在一个应用内设计。服务拆分完成之后,客户在对接服务时,也需要一个统一的入口。
网关应运而生,它主要作用如下:
1、统一入口:入口聚焦,日志统一记录
2、安全:非法请求拦截
3、权限校验:身份验证
4、流量控制:限流
5、业务路由:请求需要路由到支付服务还是用户服务,由网关根据配置进行路由
6、访问控制:黑白名单
7、负载均衡:
业务回调通知
交易业务中,诸多业务是无法在接口调用的同步返回中获取交易结果的。如商户服务中的业务开通,同步返回的是业务开通的受理情况。业务开通的结果,需要经历各级审核才能确定。
在这个场景下,会让客户在发起业务开通时,传入一个回调地址,商户服务端在确定业务开通的结果之后,通过回调地址将业务开通的结果异步通知给客户。
服务拆分带来的问题——服务之间
服务注册与发现
服务拆分之后,原有的数据库拆分为多个,Java类也拆分到各处,服务之间需要通过接口相互调用,就产生了这样的问题:如何去定位需要调用的服务。服务注册与发现,相当于一个通讯录,通讯录上记录了各种服务接口的IP及端口。
服务注册及发现分为以下几个组件
服务注册中心:维护服务提供者的信息,提供给服务消费者。同时监听服务提供者的变更,推送服务提供者消息到服务消费者。
服务提供者:服务提供者在启动时,向服务注册中心上送自身信息;后续向服务消费者提供服务。
服务消费者:从服务注册中心获取服务提供者的信息列表,缓存在本地,选择其中一个服务提供者,发起服务请求。
配置中心
服务多了起来,每个服务都有自己的配置信息,这些信息通常分散在各个服务的运行环境中。为了集中管理这些配置信息并实现动态调整,我们需要引入配置中心。
配置中心需要具备如下特点:
1、高可用 配置中心服务尽量保证能让业务服务正常访问,无法访问将可能导致拿不到配置信息导致业务无法正常运行。
2、容错性 即便配置中心崩溃,也不影响业务应用。
3、可靠存储 配置数据不丢失。
4、实时生效 业务端实时感知配置变更。
消息队列
各服务之间,除了直接的接口调用,在部分业务场景,也需要通过异步通知触发业务处理。
一个支付业务中很常见的需求,在支付完成后,自动根据分账配置,将交易产生的金额分别转入不同的账户,就需要依赖消息队列来完成异步通知,做到支付和分账两种业务的解藕。
成熟的消息队列,根据使用场景,能给系统架构带来非常多的便利
1、业务解藕
2、异步处理,削峰填谷
3、请求缓冲
4、数据分发
5、分布式事务
全链路跟踪
服务拆分之后,一个请求需要流转众多服务才能完成业务处理。
一般情况下,我们要根据某个请求关键字,在某个服务中查询日志,如果请求流经n个服务,我们可能要定位n个关键字并查询n个服务的日志,来定位问题。
这个时候,需要引入链路追踪,将这个请求的所有流转信息汇总成一条,便于查看和分析。
服务熔断
各服务之间,存在相互调用,形成了服务调用网格。如果底层服务出现问题,导致服务调用出现问题,服务响应延迟或无法访问,服务调用方将根据超时时间进行阻塞,如果调用极度频繁,将导致各服务沿着调用依赖由下向上逐层崩溃。这就是服务雪崩效应。
熔断机制是一种应对雪崩的链路保护机制,调用端可以选择在被调用方响应不正常时,主动快速失败或使用其他的兜底方式,防止崩溃的蔓延。
服务拆分带来的问题——服务内部
服务拆分之后,我们引入了微服务架构体系的众多组件,构成基础架构服务,来面对拆分带来的问题。 各服务自身的升级,如高可用、高性能、分布式缓存、分布式存储等,我们下一章节继续讨论。