为什么要把服务拆成分布式的?
2022-02-16 11:23:57 14 举报
AI智能生成
将服务拆分成分布式的主要有以下几个原因:首先,可以提高系统的可扩展性,当业务量增长时,可以方便地增加新的节点来提高处理能力;其次,可以提高系统的稳定性和可用性,当某个节点出现故障时,其他节点可以接管其工作,保证服务的连续性;再次,可以实现数据的并行处理,提高处理效率;最后,可以更好地支持微服务架构,使得每个服务都可以独立开发、部署和扩展。总的来说,分布式服务可以使系统更加灵活、稳定和高效。
作者其他创作
大纲/内容
微服务架构
微服务架构设计原则
单一职责
什么是单一职责呢?
一个单元(类,方法,服务)只关注系统中独立的,有边界的一部分
有什么好处呢?
帮助研发更优雅的开发,更便捷的交付
服务自治
什么是服务自治呢?
每个微服务应当有独立的业务能力,依赖和运行环境,应该和其他服务高度解耦
有什么好处呢?
每个微服务从开发、测试、构建和部署都应该独立运行,而不依赖其他服务
轻量级通信
什么是轻量级通信?
体量较轻
跨语言,跨平台
有哪些呢?
REST协议
AMQP
STOMP
MQTT
服务划分的粒度
什么时候确定粒度?
微服务设计阶段
如何确定边界?
领域驱动设计中的“边界上下文”
复杂软件设计之道(领域驱动设计全面解析与实战)彭晨阳
如何考核粒度的优越性?
当微服务的开发测试构建部署成本也来越低时,好的微服务就形成了
通用架构设计原则
N+1设计
系统中每个组件都应该避免单点故障
回滚设计
确保系统可以向前兼容,在系统升级时可以回滚版本
禁用设计
应该提供可以控制具体功能是否可用的配置,当系统出现故障时可以快速下线
监控设计
在设计阶段就要考虑如何监控
资源隔离设计
避免单一业务占用全部资源
异地多活数据中心设计
若系统需要极高可用性,比如5个9(意味着业务最多中断5分钟),那么考虑实施异地多活,起码在一个机房故障的时候不中断业务
可用性几个9怎么计算故障时间
3个9
(1-99.9%)*365*24=8.76小时,表示该系统在连续运行1年时间里最多可能的业务中断时间是8.76小时。
4个9
(1-99.99%)*365*24=0.876小时=52.6分钟,表示该系统在连续运行1年时间里最多可能的业务中断时间是52.6分钟。
5个9
(1-99.999%)*365*24*60=5.26分钟,表示该系统在连续运行1年时间里最多可能的业务中断时间是5.26分钟。
采用成熟的技术
架构可以水平扩展
只有能做到水平扩展,才能有效避免瓶颈问题
采用商业硬件
商业硬件有效避免硬件故障概率
非核心则购买
非核心功能占用大量研发资源才能解决,考虑购买成熟产品
快速迭代
快速迭代开发小功能模块,尽早上线发现问题降低交付风险
无状态设计
服务接口应该做成无状态的,当前接口的访问不依赖与上次接口访问的状态
微服务架构最佳实践
每个微服务单独的存储
保持代码类似的成熟度 ???
每个微服务都是单独构建
部署到容器中
将服务器视为无状态的
https://zhuanlan.zhihu.com/p/59046576
微服务优缺点
自由使用不同的技术
增加故障排除的挑战
每个微服务都侧重于单一功能
由于远程调用而增加延迟
微服务可单独部署
增加了配置和运维工作量
服务可以随时发布
难以保证服务稳定
难以调试
高频面试题
进大厂必须掌握的50个微服务面试问题
单体应用
什么是单体应用
烟囱应用
多个模块公用一个数据库
单体应用的问题
应用边界模糊,功能归属混乱
数据有时候通过数据共享,有时候通过接口调用传输,包含了很多本来就不属于它的逻辑
管理后台在一开始的设计中保障级别低
加入数据分析和促销等其他模块后出现性能瓶颈,影响了其他应用
数据库表结构被多个应用依赖,无法重构和优化
所有应用都在一个数据库上操作,无法重构和优化
特别是数据分析跑起来的时候,数据库性能急剧下降
开发、测试、部署,维护愈发困难
即使改动一个小功能,都要整个应用一起发布
有时候发布会不小心会带来一个未经过测试的代码,或者修改了一个功能后,另一个意想不到的地方出错了,为了减轻发布可能产生的影响和线上业务停顿的影响,所有应用都要在凌晨三四点发布,发布后为了验证应用正常运行,还得盯着第二天白天的用户高峰期
团队出现推诿扯皮现象
关于一些公共的功能建设在哪个应用上的问题常常要争论很久,最后干脆各干各的,或者放个地方但是都没人维护
反思
虽然快速的根据业务变化建设了系统,不过紧迫且繁重的任务容易使人陷入局部的、短浅的思维方式,从而做出妥协的决策。
在这种架构中,每个人都只赶住自己的一亩三分地,却反全局,长远的设计
长此以往,系统建设将会越来越困难,甚至陷入不断推翻、重建的循环
如何改变
第一步,抽象
在编程世界中,最重要的就是抽象能力
微服务改造的过程实际上也就是抽象的过程
如何设计系统
墨菲定律
任何事物都没有表面看起来那么简单
所有的事务都比你预计的时间长
可能出错的事总会出错
如果你担心某种事情发生,那么它更有可能会发生
为什么有墨菲定律
数理统计
在数理统计中,有一条重要的统计规律,假设某意外时间在一次活动中发生的概率为p(p>0),则在n次活动中至少一次发生的概率为:P=1- (1-p)的n次方,由此可见,无论p多么小,当n越来越大,P越来越接近与1
墨粉定律的意义
警示作用
墨菲定律是一种客观存在。要在企业管理,日常工作和生活防范墨菲定律可能导致的恶性后果,比如在行为,技术,机制和环境等多方面因素入手,从而对其在思想心里上的重视无疑放在首位
借鉴意义
在心理学上有一定根据,即负面心理暗示会对人的心态和行为造成不良影响。要打破墨菲定律诅咒,就要走坚定的自信,稳定的心态,积极的信息暗示,以肯定是的语言做标书,对自卑感等负面情况或不良念头零容忍,一旦察觉立马打消
如何划分系统
康威定律
系统架构是公司组织架构的反应
应该按照业务闭环进行系统拆分/组织架构拆分,实现闭环/高内聚/低耦合,减少沟通成本
如果沟通出现问题,那么应该考虑进行系统和组织架构的调整
在合适的时机进行系统拆分,不要一开始就把系统/服务拆分的非常细,虽然闭环,但是每个人维护的系统多,维护成本高
如何应对康威定律
https://www.jdon.com/56029
4.按康威定律划分系统的结果是什么
抽象出个公用业务能力,做成几个公共服务
如商品服务,用户服务,促销服务,订单服务。数据分析服务等
应用后台只需要从这个服务获取所需要的数据,从而删除了大量冗余的代码
仍然存在的问题是什么?
只是将服务拆开了,但是数据库仍然是公用的,所以一些烟囱式系统的缺点仍然存在
数据库成为性能瓶颈,并且存在单点故障的风险
数据管理趋向混乱,即使一开始有良好的模块化设计,随着时间推移,总会有一个服务直接从数据库获取另一个服务的数据
数据库表结构可能被多个服务依赖,牵一发而动全身,很难调整
思考
如果一直保持公用数据库的模式,整个架构hi越来越僵化,失去了微服务的意义
因此,需要拆分数据库
所有持久层相互隔离,由各个服务自己负责,为了提高系统的实时性,加入了消息队列
微服务架构
特点
业务逻辑按照康威定律和业务边界拆分
数据库拆分
什么是微服务架构
https://www.zhihu.com/question/65502802
微服务带来的好处是什么?
各个服务可以使用异构的技术
比如数据分析可以使用数据仓库作为持久层,以便于高效的做一些统计计算
商品服务和促销服务访问频率很大,引入加入了缓存机制等
还有一些抽象公共逻辑的方法就是把这些公共逻辑做成公共的框架等
微服务架构让整个系统的分工更加明确,责任更加清晰,每个人专心负责为其他人提供更好的服务,仅仅因为能力强或者人心,还莫名背锅
单体应用时代,公共服务没有明确的归属,最后要么各做各的,每个人都重新实现要么找一个人维护
最后的结果就是大家都不愿意做公共的服务,长此以往,团队里面的人渐渐各自为政,不再关心全局的设计,从政角度来说组织架构要做出相应的调整。所以说微服务架构改造需要管理者的支持
微服务引入的问题是什么?
拆分数据库带来的坏处是什么
跨库级联的问题
通过服务查询数据颗粒度的问题
通过一个服务崩溃来说明
在单体应用时代,排查问题通常是看下日志,定位错误信息和调用堆栈
定位问题非常困难
服务拆分成多个服务,定位问题很困难
服务雪崩效应
一个服务故障可能会产生雪崩效应,导致整个系统故障
如何处理故障
如何应对
服务容量规划
请求量评估
权限控制,服务治理
拆分成微服务后,出现大量的服务,大量的接口,使得整个调用关系乱糟糟的。
如何应对
网关
在调用者和被调用者中间加一层网关,每次调用时进行权限校验
网关也可以作为一个提供服务接口文档的平台
如何使用网关
要决定在多大粒度上使用
最粗粒度的方案
整个微服务一个网关,微服务外部通过网关访问微服务,微服务内部则直接调用
最细粒度的方案
所有调用,不管是微服务内部调用或者来自外部的调用,都必须通过网关
折中的方案
按照业务领域将微服务分成几个区,区内直接调用,区间通过网关调用。
服务发现
服务发现
动态扩容
如何处理故障
一个是尽量减少故障发生的概率
事前监控
物理层监控
zabbix
容器监控
prometheus
中间件监控
redis
监控内存占用之,网络流量
数据库
监控连接数、磁盘空间
慢sql、qps突变、内存、cpu、线程等突变
等等
应用监控
服务可用性监控
健康检查
服务性能监控
skywalking
链路监控(调用量突变、接口耗时监控告警)
elk
监控并发数、响应延迟、错误率
服务健壮性监控
elk
日志监控(异常监控告警)
业务监控
业务调用量突变
业务数据监控
定位问题
调用链路
分析问题
日志
第二个是降低故障造成的影响
容错
集群部署
服务自愈
服务熔断
什么是熔断
当多次访问一个服务失败(调用超时/调用失败)时,应熔断,标记该服务已停止工作,直接返回错误。直至该服务恢复正常后再重新建立连接。
熔断运行机制
子主题
举个例子
比如网上超市下单界面有一个推荐商品凑单的功能,当推荐模块挂了后,应熔断,标记该服务已经停止工作,直接返回错误,直到健康检查得到阈值后才允许重新连接。
如何做到呢?
yml配置开启Hystrix熔断功能,进行容错处理
feign.hystrix.enable=true
引入hystrix依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
客户端启动类加上熔断器注册
@EnableHystrix // 或者 @EnableCircuitBreaker
降级的两种使用方法
直接使用fallbackMethod指定fallback方法
在需要熔断降级的方法上加上如下注解
@HystrixCommand(
fallbackMethod = "fallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "200")
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "20"),
@HystrixProperty(name = "maximumSize", value = "50"),
@HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize", value = "true")
}
)
fallbackMethod = "fallback",
commandProperties = {
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "200")
},
threadPoolProperties = {
@HystrixProperty(name = "coreSize", value = "20"),
@HystrixProperty(name = "maximumSize", value = "50"),
@HystrixProperty(name = "allowMaximumSizeToDivergeFromCoreSize", value = "true")
}
)
编写降级方法,在这里方法名称为fallbackMethod 指定,即fallback,
public 业务Response fallback(业务Request request, Throwable e)
public 业务Response fallback(业务Request request, Throwable e)
注意点
降级方法要和业务方法在一个类中,且返回值一样
使用FeignClient调用,指定降级类
@FeignClient(name = "approval-center-api" , fallback = ApprovalCenterRemoteHystrixClient.class)
fallback指定的类就是降级类
熔断的意义
分布式环境下,服务直接相互调用,一个复杂的业务可能要调用多个服务,例如A -> B -> C -> D,当某个服务出现异常(调用超时、调用失败等)将导致整个流程阻塞崩溃,严重的整个系统都会崩掉,为了实现高可用,必要的保护机制必不可少
服务降级
什么是服务降级
当下游服务停止工作后,如果该服务并非核心业务,则上游服务应该降级,以保证核心业务不中断。
降级的运行机制是什么?
举个例子
比如网上超市下单界面有一个推荐商品凑单的功能,当推荐模块挂了后,下单功能不能一起挂掉,只需要暂时关闭推荐功能即可。
如何做到呢?
限流
什么是限流?
限流的运行机制是什么?
举个例子
如何做到呢?
Sentinel: 分布式系统的流量防卫兵
教程: https://blog.didispace.com/spring-cloud-learning/
限流算法
令牌桶限流法
有个任务线程以恒定速率向令牌桶添加令牌
一个请求会消耗一个令牌,令牌桶里的令牌大于0,才会放行,反正不允许通过
一个请求会消耗一个令牌,令牌桶里的令牌大于0,才会放行,反正不允许通过
guava限流
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>26.0-jre</version>
</dependency>
SpringCloud分布式下实现限流,需要把令牌桶的维护放到一个公共的地方,比如Zuul路由
如何进行服务容量评估
如何评估集群的最大容量和线上实际运行的负荷,也就是如何做好容量评估;
如何确定弹性扩缩容的时机以及机器数,也就是如何做好调度决策。
https://blog.csdn.net/qq_43684922/article/details/107525056
收藏
0 条评论
下一页