一、远程调用服务的模式

1、RPC:同技术栈,基于语言的API

2、HTTP:平台、语言无关性,基于应用来定义

二、Spring Cloud-Eureka

1、涉及到的组件(一部分)

  • Eureka:注册中心

  • Zuul:服务网关(不再维护,可以使用spring-gateway来代替)

  • Ribbon:负载均衡

  • Feign:服务调用

  • Hystrix:熔断器

在这里插入图片描述

springcloud和springboot版本存在一一对应关系:

Release TrainBoot Version
Hoxton2.2.x
Greenwich2.1.x
Finchley2.0.x
Edgware1.5.x
Dalston1.5.x

Spring提供了一个RestTemplate模板工具类,对基于HTTP的客户端进行了封装,并且实现了对象与json的序列化和反序列化,非常方便。RestTemplate并没有限定HTTP的客户端类型,而是进行了抽象,目前常用的3种都有支持:

  • HTTPClient <= apache
  • OkHTTP
  • JDK原生的URLConnection(默认的)
//Bean注解默认生成的对象名为方法名
@Bean
public RestTemplate restTemplate(){
    return new RestTemplate();
}

也可以使用HTTPClient和OkHTTP,需要引入相应的依赖,并将HTTPClient和OkHTTP作为参数传入new RestTemplate()构造方法中。

服务提供者(json) => 服务调用者(object) => 用户(json)

1、Eureka

就是服务注册中心(可以是一个集群),对外暴露自己的地址

在这里插入图片描述

在这里插入图片描述

负载均衡算法:随机或轮询

Eureka架构中的三个核心角色:

  • 服务注册中心

    Eureka的服务端应用,提供服务注册和发现功能,就是刚刚我们建立的eureka-server

  • 服务提供者

    提供服务的应用,可以是Spring Boot应用,也可以是其它任意技术实现,只要对外提供的是REST风格服务即 可。本例中就是我们实现的user-service

  • 服务消费者

    消费应用从注册中心获取服务列表,从而得知每个服务方的信息,知道去哪里调用服务方。本例中就是我们 实现的consumer-demo

2、高可用的的Eureka Server

Eureka Server即服务的注册中心,在刚才的案例中,我们只有一个EurekaServer,事实上EurekaServer也可以是 一个集群,形成高可用的Eureka中心 。

Eureka Server是一个web应用,可以启动多个实例(配置不同端口)保证Eureka Server的高可用

服务同步

多个Eureka Server之间也会互相注册为服务,当服务提供者注册到Eureka Server集群中的某个节点时,该节点会 把服务的信息同步给集群中的每个节点,从而实现数据同步。因此,无论客户端访问到Eureka Server集群中的任 意一个节点,都可以获取到完整的服务列表信息。

而作为客户端,需要把信息注册到每个Eureka中

在这里插入图片描述

3、Eureka客户端和服务端配置
  • Eureka客户端工程

    • user-service 服务提供

      • 服务地址使用ip方式 —— 影响serviceInstance.getHost()
      • 续约
    • consumer-demo 服务消费

      • 获取服务地址的频率
  • Eureka服务端工程

    • eureka-server 失效剔除
    • 自我保护

二、Spring Cloud-Ribbon

在刚才的案例中,我们启动了一个user-service,然后通过DiscoveryClient来获取服务实例信息,然后获取ip和端口来访问。

但是实际环境中,我们往往会开启很多个user-service的集群。此时我们获取的服务列表中就会有多个,到底该访问哪一个呢?

一般这种情况下我们就需要编写负载均衡算法,在多个实例列表中进行选择。

不过Eureka中已经帮我们集成了负载均衡组件:Ribbon,简单修改代码即可使用。

什么是Ribbon:

在这里插入图片描述

三、Spring Cloud-Hystrix

1.服务器雪崩

Hystix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务,防止出现级联失败。

在这里插入图片描述

服务器支持的线程和并发数有限,请求一直阻塞,会导致服务器资源耗尽,从而导致所有其它服务都不可用,形成雪崩效应。

这就好比,一个汽车生产线,生产不同的汽车,需要使用不同的零件,如果某个零件因为种种原因无法使用,那么 就会造成整台车无法装配,陷入等待零件的状态,直到零件到位,才能继续组装。 此时如果有很多个车型都需要这个零件,那么整个工厂都将陷入等待的状态,导致所有生产都陷入瘫痪。一个零件的波及范围不断扩大。

Hystrix解决雪崩问题的手段,主要包括:

  • 线程隔离
  • 服务降级
2.线程隔离&服务降级

在这里插入图片描述

服务降级虽然会导致请求失败,但是不会导致阻塞,而且最多会影响这个依赖服务对应的线程池中的资源,对其它服务没有响应。

触发Hystrix服务降级的情况:

  • 线程池已满
  • 请求超时
3.服务降级

要注意;因为熔断的降级逻辑方法必须跟正常逻辑方法保证:相同的参数列表和返回值声明。

失败逻辑中返回User对象没有太大意义,一般会返回友好提示。所以把queryById的方法改造为返回String, 反正也是Json数据。这样失败逻辑中返回一个错误说明,会比较方便。

刚才把fallback写在了某个业务方法上,如果这样的方法很多,那岂不是要写很多。所以可以把Fallback配置加在 类上,实现默认fallback;

在之前的案例中,请求在超过1秒后都会返回错误信息,这是因为Hystrix的默认超时时长为1,我们可以通过配置 修改这个值;

4.服务熔断

熔断原理:

在服务熔断中,使用的熔断器,也叫断路器,其英文单词为:Circuit Breaker 熔断机制与家里使用的电路熔断原理类似;当如果电路发生短路的时候能立刻熔断电路,避免发生灾难。在分布式系统中应用服务熔断后;服务调用方可以自己进行判断哪些服务反应慢或存在大量超时,可以针对这些服务进行主动熔断,防止整个系统被拖垮。 Hystrix的服务熔断机制,可以实现弹性容错;当服务请求情况好转之后,可以自动重连。通过断路的方式,将后续请求直接拒绝,一段时间(默认5秒)之后允许部分请求通过,如果调用成功则回到断路器关闭状态,否则继续打开,拒绝请求的服务。

在这里插入图片描述

不过,默认的熔断触发要求较高,休眠时间窗较短,为了测试方便,我们可以通过配置修改熔断策略;

四、Spring Cloud-Feign

在前面的学习中,我们使用了Ribbon的负载均衡功能,大大简化了远程调用时的代码:

String baseUrl = "http://user-service/user/";
User user = this.restTemplate.getForObject(baseUrl + id, User.class)

如果就学到这里,你可能以后需要编写类似的大量重复代码,格式基本相同,无非参数不一样。有没有更优雅的方式,来对这些代码再次优化呢?

这就是我们接下来要学的Feign的功能了。

1.Feign

为什么叫伪装? Feign可以把Rest的请求进行隐藏,伪装成类似SpringMVC的Controller一样。你不用再自己拼接url,拼接参数等等操作,一切都交给Feign去做。

完全使用SpringMVC的注解来生成url

在 ConsumerApplication 启动类上,添加注解,开启Feign功能

Feign中已经自动集成了Ribbon负载均衡,因此不需要自己定义RestTemplate进行负载均衡的配置

2.feign-ribbon负载均衡

Fegin内置的ribbon默认设置了请求超时时长,默认是1000,我们可以通过手动配置来修改这个超时时长;

因为ribbon内部有重试机制,一旦超时,会自动重新发起请求。如果不希望重试,可以添加配置;

3.Feign默认也有对Hystrix的集成

只不过,默认情况下是关闭的,需要手动开启。

(1) 首先要定义一个类,实现刚才编写的UserFeignClient,作为fallback的处理类,继承UserClient。同样需要保证实现的queryById()方法返回值和参数与接口中保持一致。

(2) 然后在UserClient中,指定刚才编写的实现类

4.请求压缩

Spring Cloud Feign 支持对请求和响应进行GZIP压缩,以减少通信过程中的性能损耗。通过下面的参数即可开启请求与响应的压缩功能。

5.日志级别

前面讲过,通过 logging.level.lxs.xx=debug 来设置日志级别。然而这个对Fegin客户端而言不会产生效果。因为 @FeignClient 注解修改的客户端在被代理时,都会创建一个新的Fegin.Logger实例。我们需要额外指定这个日志的级别才可以。

这里指定的Level级别是FULL,Feign支持4种级别:

  • NONE:不记录任何日志信息,这是默认值。
  • BASIC:仅记录请求的方法,URL以及响应状态码和执行时间
  • HEADERS:在BASIC的基础上,额外记录了请求和响应的头信息
  • FULL:记录所有请求和响应的明细,包括头信息、请求体、元数据。

五、Spring Cloud-Gateway

1.Gateway网关
  • Spring Cloud Gateway是Spring官网基于Spring 5.0、 Spring Boot 2.0、Project Reactor等技术开发的网关服务。
  • Spring Cloud Gateway基于Filter链提供网关基本功能:安全、监控/埋点、限流等。
  • Spring Cloud Gateway为微服务架构提供简单、有效且统一的API路由管理方式。
  • Spring Cloud Gateway是替代Netflix Zuul的一套解决方案。

Spring Cloud Gateway组件的核心是一系列的过滤器,通过这些过滤器可以将客户端发送的请求转发(路由)到对应的微服务。 Spring Cloud Gateway是加在整个微服务最前沿的防火墙和代理器,隐藏微服务结点IP端口信息, 从而加强安全保护。Spring Cloud Gateway本身也是一个微服务,需要注册到Eureka服务注册中心。

网关的核心功能是:过滤和路由

在这里插入图片描述

gaetway的鉴权依靠assert

  • 路由(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将会对请求和响应进行修改处理。
2.面向服务的路由

在刚才的路由规则中,把路径对应的服务地址写死了!如果同一服务有多个实例的话,这样做显然不合理。 应该根据服务的名称,去Eureka注册中心查找服务对应的所有实例列表,然后进行动态路由!

3.路由前缀

客户端的请求地址与微服务的服务地址如果不一致的时候,可以通过配置路径过滤器实现路径前缀的添加和去除。

添加前缀:在gateway中可以通过配置路由的过滤器PrefixPath,实现映射路径中地址的添加;

去除前缀:在gateway中可以通过配置路由的过滤器StripPrefix,实现映射路径中地址的去除;

4.过滤器

Gateway作为网关的其中一个重要功能,就是实现请求的鉴权。而这个动作往往是通过网关提供的过滤器来实现的。前面的路由前缀章节中的功能也是使用过滤器实现的。

Gateway自带过滤器有几十个,常见自带过滤器有:

过滤器名称说明
AddRequestHeader对匹配上的请求加上Header
AddRequestParameters对匹配上的请求路由添加参数
AddResponseHeader对从网关返回的响应添加Header
StripPrefix对匹配上的请求路径去除前缀

可以配置局部默认过滤器(作用上算全局过滤),对所有路由都生效

全局过滤器:不需要在配置文件中配置,作用在所有的路由上;实现 GlobalFilter 接口即可。

执行生命周期:类似Spring MVC的拦截器有两个:“pre” 和 “post”。“pre”和 “post” 分别会在请求被执行前调用和被执行后调用。(Spring MVC多出一个调用后环节)

使用场景:

  • 请求鉴权:一般 GatewayFilterChain 执行filter方法前,如果发现没有访问权限,直接就返回空。

  • 异常处理:一般 GatewayFilterChain 执行filter方法后,记录异常并返回。

  • 服务调用时长统计: GatewayFilterChain 执行filter方法前后根据时间统计。在执行filter方法前后各自记录一个时间戳,时间戳的差值就是服务调用时长。

5.自定义过滤器

自定义过滤器分为自定义局部过滤器和自定义全局过滤器

6.自定义全局过滤器

直接在浏览器中无法模拟请求头携带token发送,需要用到postman辅助测试

7.负载均衡和熔断

Gateway中默认就已经集成了Ribbon负载均衡和Hystrix熔断机制。但是所有的超时策略都是走的默认,比如熔断超时时间只有1S,很容易就触发了。因此建议手动进行配置;

8.Gateway跨域配置

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.1.RELEASE/multi/multi__cors_configuration.html

9.Gateway的高可用

启动多个Gateway服务,自动注册到Eureka,形成集群。如果是服务内部访问,访问Gateway,自动负载均衡,没问题。

但是,Gateway更多是外部访问,PC端、移动端等。它们无法通过Eureka进行负载均衡,那么该怎么办? 此时, 可以使用其它的服务网关,来对Gateway进行代理。比如:Nginx

10.Gateway与Feign的区别
  • 对外接口:Gateway 作为整个应用的流量入口,接收所有的请求,如PC、移动端等,并且将不同的请求转发至不同的处理微服务模块,其作用可视为nginx;大部分情况下用作权限鉴定、服务端流量控制;
  • 微服务间的内部互访:Feign 则是将当前微服务的部分服务接口暴露出来,并且主要用于各个微服务之间的服务调用。

六、Spring Cloud-Config

1.分布式配置中心

在分布式系统中,由于服务数量非常多,配置文件分散在不同的微服务项目中,管理不方便。为了方便配置文件集中管理,需要分布式配置中心组件。在Spring Cloud中,提供了Spring Cloud Config,它支持配置文件放在配置服务的本地,也支持放在远程Git仓库(GitHub、码云)。

使用Spring Cloud Config配置中心后的架构如下图:

配置中心本质上也是一个微服务,同样需要注册到Eureka服务注册中心!

在这里插入图片描述


2.获取配置中心配置

bootstrap和application的区别

  • bootstrap.yml文件也是Spring Boot的默认配置文件,而且其加载的时间相比于application.yml更早。

  • application.yml和bootstrap.yml虽然都是Spring Boot的默认配置文件,但是定位却不相同。bootstrap.yml 可以理解成系统级别的一些参数配置,这些参数一般是不会变动的。application.yml 可以用来定义应用级别 的参数,如果搭配 spring cloud config 使用,application.yml 里面定义的文件可以实现动态替换。

  • 总结就是,bootstrap.yml文件相当于项目启动时的引导文件,内容相对固定。application.yml文件是微服务 的一些常规配置参数,变化比较频繁。

七、Spring Cloud Bus服务总线

1.仍然留存的问题

通过查看用户微服务控制台的输出结果可以发现,我们对于Git仓库中配置文件的修改并没有及时更新到用户微服务,只有重启用户微服务才能生效。

如果想在不重启微服务的情况下更新配置该如何实现呢? 可以使用Spring Cloud Bus来实现配置的自动更新。

需要注意的是Spring Cloud Bus底层是基于RabbitMQ实现的,默认使用本地的消息队列服务,所以需要提前启动本地RabbitMQ服务(安装RabbitMQ以后才有),如下:

2.Spring Cloud Bus

Spring Cloud Bus是用轻量的消息代理将分布式的节点连接起来,可以用于广播配置文件的更改或者服务的监控管理。也就是消息总线可以为微服务做监控,也可以实现应用程序之间相互通信。 Spring Cloud Bus可选的消息代理有RabbitMQ和Kafka。

使用了Bus之后 :

在这里插入图片描述

3.Spring Cloud 完整体系架构图

在这里插入图片描述

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐