分布式、微服务
首先明确一个概念,分布式
例如,有一个电商系统,用户 > 订单 > 库存 > 仓储 > 积分
这些业务都在在一个服务中的,耦合极其严重,每次开发、打包、部署、极其繁琐
最主要的一个问题的,如果其中某个服务出现了问题,必然会影响其余服务
分布式通常按业务拆分成多个子系统
每个业务服务子系统部署在单独的机器上
一次下单请求调用多个服务协作共同完成
每个服务只处理自己范围内的业务
业界主流的分布式解决方案 Dubbo / Spring Cloud
现在把上面的电商系统,拆分成 订单服务、库存服务、存储服务、积分服务
这些服务部署在不同的机器上
Spring Cloud 为我们提供了分布式业务场景中的各个解决方案
1、注册中心Eureka
注册中心是一个单独的服务,主要负责服务的注册与发现
订单服务、库存服务、存储服务、积分服务这些服务在启动的时候,会向注册中心提供自己的服务地址
例如 [订单服务:192.168.52.101:8080],[库存服务:192.168.52.102:8080]
这个过程称之为服务注册
Eureka的另外一个功能的服务发现
各个服务会通过服务发现,把维护在Eureka注册中心里的服务地址拉取到自己本地
服务之间调用的时候,就可以直接从自己本地拿到对方服务的地址
2、Ribbon负载均衡
Ribbon 的核心功能的负载均衡
内部提供了多种负载均衡算法
默认采用轮询的方式
Ribbon会向Feign提供各个服务器地址进行远程调用,如果涉及到某个服务是集群方式,单个应用部署在多个机器上
例如[订单服务:192.168.52.101:8080],[库存服务:192.168.52.102:8080 / 192.168.52.103:8080]
例如库存服务有多个,则会采用轮询的方式向 Feign 提供 服务地址
3、Feign 远程调用
服务之间相互调用的时候,会通过 Feign 进行 http 进行调用
Feign通过接口的方法调用Rest服务
遵循了面向接口编程的方式
4、Hystrix 断路器
这块是属于高可用方面的解决方案
单点故障之后的解决方案
涉及到服务降级、服务限流、服务熔断、近实时监控
5、zuul 路由网关
现在的项目一般都是采用前后端分离的方式
如果没有网关这块,那么前端要维护上百个后端接口,这么多接口直接对外暴露,极其繁琐,复杂
zuul 所有的请求都可以通过这个入口,来进行访问后端服务
zuul 主要涉及到代理、路由、过滤三大功能
两个核心功能
服务注册与发现
心跳与故障
我们服务启动之后会在Eureka中注册
在Eureka中有一个注册表
表中维护了我们的服务地址
其余服务启动的时候,会去Eureka中拉取注册表
拉取的这个间隔可以进行配置
在Eureka中有一个多级缓存的概念( ReadOnly缓存 / ReadWrite缓存 )
内部维护的3块区域 【ReadOnly缓存】 >> 【ReadWrite缓存】 >> 【注册表】
目的是为了优化并发冲突
如果没有这3块区域,边写边读的并发操作,锁的冲突对系统是有一定的影响的
在服务发现的时候,会去 【ReadOnly缓存】 中拉取 注册表信息
在服务 注册 / 修改 的时候,会在【注册表】中注册服务信息,会立马同步到 【ReadWrite缓存】
在 【ReadOnly缓存】 到 【ReadWrite缓存】之间 会有一个线程 定时同步注册表信息,这个时间也是可以配置的
所以说,我们在新加入一个服务,可能调用的时候,不会立马感知到
这是因为 【ReadOnly缓存】 还没有同步最新的 注册表
在服务注册之后
服务会定时向注册中心发送心跳( 可以配置时长,例如:30s)
会有一个线程定时去检查服务的心跳
如果发现某个服务在过去60秒 (这个也是可以配置的) 没有发送心跳
那么就认为这个服务挂了,会从【注册表】中把这个服务给删除
删除之后,会把 【ReadWrite缓存】 给清空
等到下一次 【ReadOnly缓存】 同步 【ReadWrite缓存】的时候,缓存中都是空的
等到服务再去 【ReadOnly缓存】 中获取 【注册表】 的时候,发现是空的,然后会继续往上找
【ReadOnly缓存】 >> 【ReadWrite缓存】 >> 【注册表】
如果你基于Spring Cloud对外发布一个接口,实际上就是支持http协议的,对外发布的就是一个最最普通的Spring MVC的http接口
feign它对一个接口打了一个注解,他一定会针对这个注解标注的接口生成动态代理
然后你针对feign的动态代理去调用他的方法的时候,此时会在底层生成http协议格式的请求,/order/create?productId=1
底层的话,使用HTTP通信的框架组件,HttpClient
先得使用Ribbon去从本地的Eureka注册表的缓存里获取出来对方机器的列表
然后进行负载均衡,选择一台机器出来,接着针对那台机器发送Http请求过去即可
配置一下不同的请求路径和服务的对应关系,你的请求到了网关,它直接查找到匹配的服务
然后就直接把请求转发给那个服务的某台机器
Ribbon从Eureka本地的缓存列表里获取一台机器,负载均衡,把请求直接用HTTP通信框架发送到指定机器上去