为什么要学习Spring Cloud?
? 在项目开发中随着业务越来越多,导致功能之间耦合性高、开发效率低、系统运行缓慢难以维护、不稳定。微服务架构可以解决这些问题,而Spring Cloud是微服务架构最流行的实现。并且Spring Cloud可以集成多种语言!!!这也成了学习Spring Cloud的重要理由之一。
初识Spring Cloud
? Spring Cloud使用HTTP方式来实现服务间的调用。HTTP其实是一种网络传输协议,基于TCP,工作在应用层,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用HTTP协议,也可以用来进行远程服务调用。缺点是消息封装臃肿,优势是对服务的提供和调用方没有任何技术限定,自由灵活,更符合微服务理念。现在热门的REST风格,就可以通过HTTP协议来实现。
Spring Cloud重要组件
(1).注册中心
概述
? 所谓微服务技术,就是将大业务分割成小业务,每个小业务分给不同的团队进行完成,这大大提高了开发的效率。那么如何实现不同团队的交互呢,不同业务如何进行联系呢? ? Spring Cloud整合了Eureka作为注册中心。 ? 所谓注册中心就好比是所谓的中间商,我们来举个例子进行快速的理解。一对内向的陌生男女如何成为男女朋友呢,一个个都不好意思说,这个时候就需要红娘的介绍,我们把一个个微小的服务看作几个极其内向的男生和女生,注册中心就好比是红娘的作用,可以根据他们的条件,自动匹配,介绍他们认识,他们无需自己去寻找服务。同时服务的提供者通过HTTP方式向Eureka刷新自己的状态(你脱单了还来介绍干嘛)。
工作原理
? 我们现在来看一下红娘的, 啊不,Eureka注册中心的工作原理。
额外操作
? 如果红娘一个人忙不过来怎么办呢?那当然是找别的人一起来帮忙呗。Eureka也是,多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任意一个节点,都可以获取到完整的服务列表信息。而作为客户端,需要把信息注册到每个Eureka中。 ? 这样,我们就建立了一个高可用的Eureka Server集群。
注意!!!在配置Eureka时,若使用jdk11进行配置,则无法开启tomcat服务,需要加入JAXB依赖!!!
(2).负载均衡Ribbon
基本概述
? 现在问题来了,Eureka如何知道到底该访问哪一个服务呢?也就是说,我们的红娘怎么去为俊男靓女匹配对象呢? ? 一般这种情况呢,我们就需要编写负载均衡的算法,在多个实例列表中进行选择,不过Eureka已经帮我们集成了负载均衡组建:Ribbon,简单修改代码即可使用。 ? 有了Ribbon,我们不再需要手动获取ip和端口,直接通过服务名称即可进行调用。
源码研究
? 为什么只输入了service名称就可以访问了呢?之前还要获取ip和端口。显然是有组件根据service名称,获取到了服务实例的ip和端口。因为 服务使用的是RestTemplate,spring使用LoadBalancerInterceptor拦截器 ,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。
负载均衡策略
? Ribbon默认的负载均衡策略是简单的轮询,我们可以测试一下: 编写测试类,在刚才的源码中我们看到拦截中是使用RibbonLoadBalanceClient来进行负载均衡的,其中有一个choose方法,是这样介绍的: ? 这个就是负载均衡获取实例的方法,我们现在对其进行测试。可以看到结果,确实是轮询的方式。 ? SpringBoot也为我们提供了修改负载均衡规则的配置入口,格式是:{服务名称}.ribbon.NFLoadBalancerRuleClassName: 其中默认是轮询的方式,可以将其设置为IRule的实现类com.netflix.loadbalancer.RandomRule。结果便会变成随机。
(3).Hystrix
基本概述
? 当我们的业务逐渐庞大,由于服务间调用关系的错综复杂,一个请求,可能需要调用多个微服务接口才能实现,会形成非常复杂的调用链路,要是某个服务出现了异常,请求发生了阻塞,服务器不释放该线程不会释放,越来越多的线程会造成阻塞,便发生了雪崩效应。 ? Hystix解决雪崩问题的手段,主要包括:
实现原理
? 示意图如下: 解读:
- Hystrix为每个依赖服务调用分配一个小的线程池,如果线程池已满调用将被立即拒绝,默认不采用排队,加速失败判定时间。
- 用户的请求将不再直接访问服务,而是通过线程池中的空闲线程来访问服务,如果线程池已满,或者请求超时,则会进行降级处理。
那么什么是服务降级呢? ? 服务降级可以优先保证核心服务。用户的请求故障时,不会被阻塞,更不会无休止的等待或者看到系统崩溃,至少可以看到一个执行结果(例如返回友好的提示信息2333)。 ? 服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。 触发Hystrix服务降级的情况:
服务断熔
状态机有3个状态:
- Closed:关闭状态(断路器关闭),所有请求都正常访问。
- Open:打开状态(断路器打开),所有请求都会被降级。Hystrix会对请求情况计数,当一定时间内失败请求百分比达到阈值,则触发熔断,断路器会完全打开。默认失败比例的阈值是50%,请求次数最少不低于20次。
- Half Open:半开状态,不是永久的,断路器打开后会进入休眠时间(默认是5S)。随后断路器会自动进入半开状态。此时会释放部分请求通过,若这些请求都是健康的,则会关闭断路器,否则继续保持打开,再次进行休眠计时。
(4).Feign
基本概述
? 作为程序员的我们,无时无刻都在想着怎么偷懒😄。在之前使用Ribbon的负载均衡功能,大大简化了远程调用的代码。但是随着服务的增多,我们也需要编写大量的重复代码,格式相同,无非参数不一样。这个时候,使用Feign就可以帮助我们进行这些无意义的操作。
Feign的客户端
- 首先这是一个接口,Feign会通过动态代理,帮我们生成实现类。这点跟Mybatis的mapper很像
- @FeignClient ,声明这是一个Feign客户端,同时通过 value 属性指定服务名称
- 接口中的定义方法,完全采用SpringMVC的注解,Feign会根据注解帮我们生成URL,并访问获取结果
- @GetMapping中的/user,请不要忘记;因为Feign需要拼接可访问的地址
? 有了该接口,我们就可以通过spring注入的方式进行调用,在控制器当中引用queryById的方法。 注意!!!我们还需要在该服务的启动类的注解加上@EnableFeignClients来开启feign的功能
(5). Spring Cloud Gateway网关
基本概述
? Spring Cloud Gateway组件的核心是一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。 Spring Cloud Gateway是加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点IP端口信息,从而加强安全保护。Spring Cloud Gateway本身也是一个微服务,需要注册到Eureka服务注册中心。 ? 网关的核心功能是:过滤和路由。我们可以用来进行访问权限的设置(鉴权)和根据路由与断言进行转发效果。 ? 核心概念:
- 路由(route) 路由信息的组成:由一个ID、一个目的URL、一组断言工厂、一组Filter组成。如果路由断言为真,说明请求URL和配置路由匹配。
- 断言(Predicate) Spring Cloud Gateway中的断言函数输入类型是Spring 5.0框架中的ServerWebExchange。Spring Cloud Gateway的断言函数允许开发者去定义匹配来自于HTTP Request中的任何信息比如请求头和参数。
- 过滤器(Filter) 一个标准的Spring WebFilter。 Spring Cloud Gateway中的Filter分为两种类型的Filter,分别是Gateway Filter和Global Filter。过滤器Filter将会对请求和响应进行修改处理
架构雏形
? 不管是来自于客户端(PC或移动端)的请求,还是服务内部调用。一切对服务的请求都可经过网关,然后再由网关来实现 鉴权、动态路由等等操作。Gateway就是我们服务的统一入口。 ? Gateway可以通过服务的名称,去Eureka注册中心查找服务对应的所有实例列表,然后进行动态路由!!!
过滤器
? Gateway作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作往往是通过网关提供的过滤器来实现。 ? Gateway自带的过滤器有几十个,常见自带过滤器有:
过滤器名称 | 说明 |
---|
AddRequestHeader | 对匹配上的请求加上Header | AddRequestParameters | 对匹配上的请求路由添加参数 | AddResponseHeader | 对从网关返回的响应添加Header | StripPrefix | 对匹配上的请求路径去除前缀 |
详细的说明参考官网。我们可以通过不同的手段配置全局过滤器和局部过滤器。 ? 执行的生命周期也类似Spring MVC的拦截器,包括了"pre"和"post":
Spring Cloud Config分布式配置中心
基本概述
? 在我们开发的过程中,我们常常有这样的困扰,每次修改文件的配置就要重启本地服务器进行测试,这样随着项目越来越庞大,我们重启本地服务器所花费的时间也越来越多,大大影响了我们效率(还有我的心情)。 ? 这个时候,我们就可以将我们的配置文件集中管理至云端,例如GitHub或者是码云中的仓库。大致的架构如下图:
Spring Cloud Bus 服务总栈
? 当我们将配置文件上传到了云端后,本地IDE立即清爽许多😁。但是,我们发现在云端更改配置文件的内容后,依然需要通过重启本地服务器去读取新的配置文件(这有什么区别嘛😫)。 ? 这时候我们就需要Spring Cloud Bus来进行对项目的优化。 需要注意的是Spring Cloud Bus底层是基于RabbitMQ实现的!!!默认使用本地的消息队列服务,所以需要提前启动本地RabbitMQ服务(安装RabbitMQ以后才有)
基本概述
? Spring Cloud Bus是用轻量的消息代理将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。也就是消息总线可以为微服务做监控,也可以实现应用程序之间相互通信。 Spring Cloud Bus可选的消息代理有RabbitMQ和Kafka。 使用了Bus后的架构图: (越来越多了😁)
Spring Cloud的完整体系图
|