微服务---分布式系统的延伸,如何做服务拆分和系统设计以及架构
概述
微服务架构只是将一个单体应用程序拆分为多个相对独立的服务,每一个服务拥有独立的进程和数据,每一个服务都是以轻量级的通信机制进行交互的,一般为HTTP API(现今最流行的是REST风格)。
一般来说,这些服务都是围绕着业务模块来建设的,是独立的产品,因此完全可以独立地自动化部署和维护,这样更加有利于我们进行更小粒度的开发、维护和部署。这些服务可以由不同的语言编写,采用不同的数据存储,最低限度地集中管理。
微服务是一个模糊的概念,而不是一个标准,没有明确的定义。微服务它属于分布式范畴,我们可以把微服务看成是分布式系统设计和架构的理念之一,并并不是说能解决所有的分布式系统的问题,它只是寻求一个平衡点,让架构师能够更为简单、容易地构建分布式系统。
微服务设计原则
要架构并开发一个微服务系统,首先要考虑的是服务拆分方法,其次是微服务的设计和整体架构。
服务拆分
服务拆分是微服务系统开发的第一步,也是最重要的一步。
首要考虑的是按业务拆分,这就要求架构师,先分析业务需求,做好业务边界,然后再按照业务模块对系统进行拆分。
服务拆分需要考虑以下几点:
- 服务的独立性
拆分出来的服务,应该是独立的,它可以独立运行,支撑某一块业务,是一个独立的产品,应该具备高内聚和低耦合的特点,同时它会保留一些明确的接口,提供给第三方进行服务调用 - 明确服务粒度
比如一个用户服务,当系统中用户角色变多,业务变复杂,会拆分出普通会员服务、商户服务、专家服务等等细分粒度。 - 团队分配
因为每一个服务是一个独立的产品,原则上要求独立团队负责开发、运维和部署,为了节约成本,一般会是一个团队负责多个业务微服务,按业务和工作量合理分配。 - 演进型
微服务的拆分不是一成不变的,它会随着时间的变化而变化的。正如第二点所述,业务一开始不复杂的情况下,可能就划分出一个用户服务,当业务发展中,越来越复杂,用户数据越来越大,需要按用户角色和业务拆分成多个细分服务,所以在设计的时候,需要考虑未来可能的细化方向。 -
避免循环依赖和双向依赖
一个业务不能同时由两个系统维护,必须有清晰的边界。比如电商场景中,商品和财务都是有相关性的,有时候财务报表需要按照商品的交易情况等维度来统计,这里需要明确商品相关的信息操作只在商品服务中处理,财务服务需要商品相关信息,需要有明确的接口和同步时间界限,以避免在财务服务中去维护商品的内容。
系统设计
当服务划分好之后,就能清晰得看到各个独立的服务了,接下来进入系统设计。
系统设计中需要考虑以下几点:
- 高可用性
高可用性是微服务设计的第一原则。为了尽可能保证微服务能够持续稳定地提供给用户服务,任何一个服务都应该至少有2个实例,任何一个实例出现故障,都可以被微服务系统发现,并且微服务系统可以通过自我修复排除故障节点。 - 伸缩性
根据业务的发展,对服务的增加和减少有弹性的支持。 - 容错性
在高并发情况下,通过限流、熔断和服务降级来保证服务之间的故障不蔓延 -
弱一致性
在之前的分布式事务中提到过,微服务不推荐使用强一致性,因为强一致性缓慢且复杂。弱一致性则相对简单,响应速度快。 - 性能
微服务推荐的是使用REST风格的请求来暴露服务接口,但是REST风格缓慢,在一些性能要求高的场景可以选择使用RPC。
下边两点属于运维范畴 - 基础设施自动化
可使用DevOps的理念进行开发和测试,也可使用容器(如Docker等)简化微服务的部署,使用这些工具可进一步简化开发、测试、部署和运维工作,使得工作更少,更加智能 - 可监控
服务实例都是可以监控的,出现故障可以及时发现,并且提示运维人员进行维护
微服务架构
接下来开始系统架构,如图
微服务系统架构
图中,我们会用到许多组件,来帮我们组成一个微服务系统
- 服务注册中心
可选组件:Eureka、Nacos、Consul,推荐Nacos - API网关组件
可选择 SpringCloud gateway - 配置中心
可选组件:Nacos、Config、Consul,推荐Nacos - 服务限流
可选组件: sentinel - 负载均衡
可选组件:Ribbon - 远程调用
可选组件:Fegin/OpenFegin - 服务监控
可选组件:SpringBootAdmin - 分布式事务管理
可选组件: Seata
API网关:API网关可以实现路由、限流和降级的功能
服务和实例:服务是根据服务拆分方法得到的一个独立的产品,它有明确的业务规则、边界和接口。服务是由多个实例来完成的,多个实例可以满足高可用和高性能的需求
服务调用:各个服务通过服务调用来完成企业的业务。在一般情况下,我们可以使用基于REST风格的服务调用(如Ribbon和OpenFeign),它具备更高的可读性和独立性,但是性能不高,如果需要提升性能的,还可以考虑远程调用(RPC)技术
微服务系统如何优化提高性能?
优化主要集中在以下几点:
- 数据库技术
- 缓存技术
- 动静分离
- 服务调用
- 数据库优化
主要对索引、SQL和锁的优化,以及数据库读写分离,分库分表等
索引:不是越多越好,数据量少的表可以不用索引,一般来说,表主要是考虑在常用的检索字段上添加索引,每表索引应该在5个以下,索引只需要满足大部分的查询即可,而不是全部查询
SQL:SQL语句的有这里不铺开叙述
锁:有些sql会使表锁定,比如update语句,需要优化sql语句避免表锁定。
数据库读写分离:参考《如何搭建经典的MySQL 主从复制架构》
分库分表:参考《分布式系统中,数据库的分表、分库和分区基本概念梳理》
《Springboot整合 ShardingSphere 实现分库分表》 - 使用缓存
缓存一般是将数据存放在内存中,而数据库的数据却存放在磁盘中,内存的速度是磁盘的几倍到几十倍,所以如果大部分的数据是从内存读取,就能够显著提升性能。一般我们会选择Redis作为缓存数据存储服务。
3.服务调用优化
对于性能要求高的服务,可以采用RPC替代REST调用
- 动静分离
把常常访问的静态内容,存储于CDN服务器上
微服务系统如何保证服务高可用?
在高并发出现各种不稳定因素时,需要使用一定的技术手段,保证服务的可用性。目前流行的方法有限流和服务降级、隔离术、网关过滤和断路器。
-
限流和服务降级
Spring cloud Gateway结合 Alibaba Sentinel -
隔离术
隔离术是处理高并发高的一种常用方法。隔离分为物理隔离和逻辑隔离两大类。
机房隔离就属于物理隔离。目前主要用的是线程隔离,可采用组件有:Resilience4j(舱壁) -
网关过滤
网关过滤也是常用的处理高并发的技术之一,通过它可以区分请求的有效性。
判断请求是否有效的办法,常见的有这么几种:验证码(如图片验证码、短信验证码和拖动验证码等)、用户黑名单、限制用户单位时间戳的请求数、实名制、区分僵尸用户和IP封禁等。
一般,可以使用redis 存储ip黑名单,然后验证过后拒绝请求。 -
断路器
因服务依赖引发的服务器雪崩现象,在高并发时,更容易产生这个现象,因此,往往还需要使用断路器,保护那些可能引发问题的服务调用。
总结
微服务作为近几年的新潮技术,席卷了整个IT行业,笔者也是因为微服务而接触了SpringBoot,开启了SpringCloud的学习。