图片来自 Pexels
正当我沉迷在源码中不能自拔的时候,总监突然来到我旁边轻声的对我说道:最近这段时间大家的任务也不是特别多,空闲时间比较足,你这边能不能做点技术分享什么的,一来可以联络一下同事之间的感情,二来也可以增加同事之间的学习氛围。
这里面肯定不时出现太多的代码,既然这样,那我就讲一讲分布式的架构演进吧,这个话题既高端,也能让大部分的人听懂,我就是个天才。
单体服务
我们一起来看看当时的架构是什么样的:
①引入 Nginx
然后流程就被设计成了这样:
②引入 Redis 单体
我在程序和数据库之间增加一个中间件:Redis,使用它来降低数据库的访问,这样性能自然会得到提升。
③引入 MySQL 读写分离
④引入服务器集群
集群算是做完了,总算可以满足领导的要求了,为了搞定这一套一套的升级,不知道熬了多少夜,看到电脑旁边掉落的那几根头发,我满意的点了点头。
分布式架构
我们的产品现在比较火热,不管是注册人数还是日活跃人数都是比较高的,为了让程序能有更好的健壮性,我希望我们可以对这个项目进行重构,以分布式的架构,今天开会就是我们一起来做个技术选型,你们对分布式熟悉吗?
分布式系统(distributed system)是建立在网络之上的软件系统。正是因为软件的特性,所以分布式系统具有高度的内聚性和透明性。
嗯,不错,不过这个解释比较官方,还有没有比较通俗易懂的解释?
分布式将一个大的系统拆分成无数个细微的子系统,让每一个系统都负责一定的职责,他们相互独立,但是又相互联系。
哟,不错哦,这个同事可以,晚上加鸡腿,那有人可以举个例子吗?
从前有一个有一个饭店,里面只有老板和一个员工,这个员工负责饭店所有的事情,包括但不限于:厨师、服务员、收银员、清洁工等,在炒菜的时候就不能去收钱,在打扫卫生的时候就不能炒菜,这个员工干了一个月之后,突然有一天,他病倒了,餐厅的生意就停滞了,这个时候老板就想到了一个人不行,那我多招几个人,一个人负责一个职位,这样即使某个人请假或者离职了,对我的生意影响不是很大,比如:清洁工离职了,虽然没有人打扫卫生,但是这并不影响我开门做生意,分布式就是这个道理。
这个例子讲的不错,你晚上不用加班了,如果你要是能画一个分布式的基础图出来,我今晚请大家撸串。
Me:我专治各种不服,于是我就给技术总监"上了一课",请看图:
为什么要使用分布式架构
不错,画的很好,但是你们知道我们为什么要将单体的服务重构为分布式吗?答对有鸡腿。
-
Spring Cloud 专注于提供良好的开箱即用经验的典型用例和可扩展性机制覆盖
-
分布式/版本化配置
-
服务注册和发现
-
路由
-
Service-to-Service 调用
-
负载均衡
-
断路器
-
分布式消息传递
想不到我们这个团队人才辈出啊,不错不错,看来我都没有讲下去的必要了啊,大家对分布式都相当熟悉了啊,那分布式架构存在缺点或者不足吗?
同事 D:
分布式基础组件
技术总监:既然大家对分布式都这么熟悉了,那我也就不在多说了,我们接下来直接来说说关于分布式组件的选型吧,大家有什么意见都可以提出来,首先谁来说一下分布式组件都有哪些?请开始你们的表演。
那我就不客气了,由于我们都是对 Spring Cloud 比较熟悉,现在他也是比较主流,那我介绍一下 Spring Cloud 的基础组件吧。
Spring Cloud Config:配置管理工具包,让你可以把配置放到远程服务器,集中化管理集群配置,目前支持本地存储、Git 以及 Subversion。
Spring Cloud Bus:事件、消息总线,用于在集群(例如,配置变化事件)中传播状态变化,可与 Spring Cloud Config 联合实现热部署。
Eureka:云端服务发现,一个基于 REST 的服务,用于定位服务,以实现云端中间层服务发现和故障转移。
Hystrix:熔断器,容错管理工具,旨在通过熔断机制控制服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
Zuul:Zuul 是在云平台上提供动态路由,监控,弹性,安全等边缘服务的框架。Zuul 相当于是设备和 Netflix 流应用的 Web 网站后端所有请求的前门。
Archaius:配置管理 API,包含一系列配置管理 API,提供动态类型化属性、线程安全配置操作、轮询框架、回调机制等功能。
Consul:封装了 Consul 操作,Consul 是一个服务发现与配置工具,与 Docker 容器可以无缝集成。
Spring Cloud for Cloud Foundry:通过 Oauth2 协议绑定服务到 CloudFoundry,CloudFoundry 是 VMware 推出的开源 PaaS 云平台。
Spring Cloud Sleuth:日志收集工具包,封装了 Dapper 和 log-based 追踪以及 Zipkin 和 HTrace 操作,为 Spring Cloud 应用实现了一种分布式追踪解决方案。
Spring Cloud Data Flow:大数据操作工具,作为 Spring XD 的替代产品,它是一个混合计算模型,结合了流数据与批量数据的处理方式。
Spring Cloud Security:基于 Spring Security 的安全工具包,为你的应用程序添加安全控制。
Spring Cloud Zookeeper:操作 Zookeeper 的工具包,用于使用 Zookeeper 方式的服务发现和配置管理。
Spring Cloud Stream:数据流操作开发包,封装了与 Redis、Rabbit、Kafka 等发送接收消息。
Spring Cloud CLI:基于 Spring Boot CLI,可以让你以命令行方式快速建立云组件。
Ribbon:提供云端负载均衡,有多种负载均衡策略可供选择,可配合服务发现和断路器使用。
Turbine:Turbine 是聚合服务器发送事件流数据的一个工具,用来监控集群下 Hystrix 的 Metrics 情况。
Feign:Feign 是一种声明式、模板化的 HTTP 客户端。
Spring Cloud Task:提供云端计划任务管理、任务调度。
Spring Cloud Connectors:便于云端应用程序在各种 PaaS 平台连接到后端,如:数据库和消息代理服务。
Spring Cloud Cluster:提供 Leadership 选举,如:Zookeeper,Redis,Hazelcast,Consul 等常见状态模式的抽象和实现。
Spring Cloud Starters:Spring Boot 式的启动项目,为 Spring Cloud 提供开箱即用的依赖管理。
-
Spring Cloud Config
-
Spring Cloud Bus
-
Hystrix
-
Zuul
-
Ribbon
-
Feign
技术总监:不错,组件分析的不错,但是你的讲解比较官方,下面我们来一个一个的讲解一下我们经常使用的这些组件。
①Eureka
请看下图:
②Spring Cloud Config
我能不能将这些变动较大的配置集中管理,不同环境的管理者分别对他们进行修改,就不需要再服务中做改动了,Config 就做到了。
③Netflix Zuul(网关)
既然我们将一个服务拆分成了很多微服务,那岂不是要暴漏很多接口给浏览器?这样会不会造成安全隐患呢?有谁可以来说说这个问题。
我们可以通过 Nginx 反向代理,开放二级域名,然后将域名映射到微服务中。
这个方案也可以,也是不需要使用的,但不是最完善的,还有没有更好的方案?
我觉得我们可以使用网关,它既可以做分流转发,也可以做权限控制,使用 Nginx+网关,我觉得是比较好的一种方案,以下是网关 Zuul 的介绍。
Zuul 是 Netflix 的基于 JVM 的路由器和服务器端负载均衡器。
-
认证 -洞察
-
压力测试
-
金丝雀测试
-
动态路由
-
服务迁移
-
负载脱落
-
安全
-
静态响应处理
-
主动/主动流量管理
我们在日常开发过程中并不会使用那么多,基本上就是认证、动态路由、安全等等,我画了一张关于网关的架构图,请看:
你们真的太优秀了,没错,Nginx 只能为我们做反向代理,不能做到权限认证,网关不但可以做到代理,也能做到权限认证、甚至还能做限流,所以我们要做分布式项目,少了他可不行。
④Spring Cloud Bus
application.yml
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/test
driver-class-name: com.mysql.cj.jdbc.Driver
比如上面这行配置大家都应该很熟悉,这是数据库的连接信息,如果它发生改变了怎么办呢?
我们可以通过 Spring Cloud Bus 来解决这个问题,Spring Cloud Bus 将轻量级消息代理链接到分布式系统的节点。然后可以将其用于广播状态更改(例如,配置更改)或其他管理指令。
这是一个很简单的原理,理解起来可能也不会怎么难,画个图来理解一下:
⑤Feign
漂亮,和你们讲技术就是省事,刚才我们说到了注册中心可以方便服务于服务之间的通信,但是他们具体是怎么通信的你们有谁知道吗?
由于我们刚刚讲的分布式架构是 Spring Cloud,所以这里推荐使用:Feign。
Spring Cloud 集成 Ribbon 和 Eureka 以在使用 Feign 时提供负载均衡的 HTTP 客户端。
不错,那如果服务的调用出现问题怎么办?比如调用超时,这个时候后我们如何处理?
⑥Netflix Hystrix(熔断)
这个 Cloud 也给我们考虑到了,我们只需要引入熔断即可。
我们可以改造一下刚刚的调用架构:
分布式大致架构差不多了,还有一些组件这里也不做做介绍了,使用的时候可以自己了解一下,不是很难。
MQ(消息中间件)
同事 B:我们可以通过消息中间件来实现,使用异步讲给用户的反馈和发送短信分离,只要用户点了发送短信,直接返回成功,然后再启动发送验证码,60 秒重发一下,就算发送失败,用户还可以选择重新发送。
分布式事务
漂亮,MQ 不但可以解耦服务,它还可以用来削峰,提高系统的性能,是一个不错的选择。
我这里有两种方案,第一种是通过 MQ 来保证一致性,另外一种就是通过分布式事务来确保一致性。
①MQ 确保一致性
-
生成一个订单表,记录着转入转出的状态。
-
向 MQ 发送一条确认消息。
-
开启本地事务,执行转出操操作,并且提交事务。
系统中会一直定时扫描订单中状态,没有成功的就做补偿机制或者重试机制,这个不是唯一要求。
②Seata(分布式事务)
-
事务协调器(TC):维护全局事务和分支事务的状态,驱动全局提交或回滚。
-
事务管理器 TM:定义全局事务的范围:开始全局事务,提交或回滚全局事务。
-
资源管理器(RM):管理分支事务正在处理的资源,与 TC 进行对话以注册分支事务并报告分支事务的状态,并驱动分支事务的提交或回滚。
-
TM 要求 TC 开始一项新的全球交易。TC 生成代表全局事务的 XID。
-
XID 通过微服务的调用链传播。
-
RM 将本地事务注册为 XID 到 TC 的相应全局事务的分支。
-
TM 要求 TC 提交或回滚 XID 的相应全局事务。
-
TC 驱动 XID 对应的全局事务下的所有分支事务以完成分支提交或回滚。
完整的分布式架构
完整的分布式架构如下图:
服务宕机,所以一般情况下,网关都是集群部署,不止网关可以集群,其他的服务都可以做集群配置,比如:注册中心、Redis、MQ 等等都可以。
总结
①单体服务与分布式服务区别
单体服务与分布式服务对比如下图:
②什么时候使用分布式/集群?
-
单机无法支持的时候。
-
想要更好的隔离性(功能与功能)。
-
想要更好用户体验的时候。
-
想要更好的扩展性。
-
想要更快的响应,更搞得吞吐量。
③使用分布式注意事项
④关于组件停更消息
所以也没必要听到组件停更的消息就担心 Cloud 会不会凉,放心,它至少最近几年是不会凉的。
编辑:陶家龙
出处:https://juejin.im/post/5ea6acb8e51d454ddf2346ee#heading-18
精彩文章推荐:
Spring Boot 要怎么学?要学哪些东西?要不要先学 SSM?松哥说说看法
274 页 pdf 文档,Spring Boot 教程也有离线版了
喜欢就点个"在看"呗^_^
本文分享自微信公众号 - 江南一点雨(a_javaboy)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。