一文让你了解SpringCloud五大核心组件

Posted 林在闪闪发光

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文让你了解SpringCloud五大核心组件相关的知识,希望对你有一定的参考价值。

🏆今日学习目标:

🍀SpringCloud五大核心组件
创作者:林在闪闪发光
⏰预计时间:30分钟
🎉个人主页:林在闪闪发光的个人主页

 🍁林在闪闪发光的个人社区,欢迎你的加入: 林在闪闪发光的社区

 

SpringCloud五大组件:

1、注册中心组件(服务治理):Netflix Eureka;

2、负载均衡组件:Netflix Ribbon,各个微服务进行分摊,提高性能;

3、熔断器组件(断路器):Netflix Hystrix,Resilience4j ;保护系统,控制故障范围;

4、网关服务组件:Zuul,Spring Cloud Gateway;api网关,路由,负载均衡等多种作用;

5、配置中心:Spring Cloud Config,将配置文件组合起来,放在远程仓库,便于管理;

SpringCloud五大组件:

1、Netflix Eureka(注册中心组件)

  • Spring Cloud 提供了多种注册中心的支持,如:Eureka、Consul、ZooKeeper 等,Netflix Eureka 本身是一个基于 REST 的服务,包含两个组件:Eureka Server 和 Eureka Client;

作用:

  • Eureka Server 提供服务注册服务,各个节点启动后,会在 Eureka Server 中进行注册,这样 Eureka Server 的服务注册表将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到;
  • Eureka Server 之间通过复制的方式完成数据的同步,Eureka 还提供了客户端缓存机制,即使所有的 Eureka Server 都挂掉,客户端依然可以利用缓存中的信息消费其他服务的 API;
  • Eureka Client:生产者或消费者;
  • 在应用启动后,Eureka Client 将会向 Eureka Server 发送心跳,默认周期为 30 秒,如果 Eureka Server 在多个心跳周期内(默认 90 秒)没有接收到某个节点的心跳,Eureka Server 将会进入自我保护机制;

2、Netflix Ribbon(负载均衡组件)

  • 适用于 Spring Cloud 2020 之前的版本;
  • Ribbon 是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起,Ribbon 客户端组件提供一系列完善的配置项如连接超时,重试等,
  • 简单的说,就是在配置文件中列出 Load Balancer 后面所有的机器,Ribbon 会自动的帮助你基于某种规则(如简单轮询,随机连接等)去连接这些机器,我们也很容易使用 Ribbon 实现自定义的负载均衡算法;
  • 作用:Ribbon,主要提供客户侧的软件负载均衡算法。
  • 简介:Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。

负载均衡策略:

  • RoundRobinRule ---- 轮询、默认;
  • RandomRule ---- 随机;
  • RetryRule ---- 重试机制;
  • BestAvailableRule ---- 选择最小并发 server;
  • AvailabilityFilteringRule ---- 过滤高并发、失败 server;
  • WeightedResponseTimeRule ---- 根据响应时长比重选择中间值;
  • ZoneAvoidanceRule ---- 判断 server 性能;
  • 查看 com.netflix.loadbalancer.IRule 接口;

3、熔断器组件

1.Netflix Hystrix

简介:

  • 推荐 Spring Cloud 2020 之前版本使用
  • 雪崩效应:在微服务架构中,存在多个微服务,若其中一个微服务出现故障,就很容易因为依赖关系而引发故障蔓延,最终导致整个系统瘫痪,列举:电商系统中,存在用户、订单、库存、积分、评论等微服务,用户创建一个订单,请求库存系统出货,库存系统出现问题,导致订单服务挂起或失败,在高并发的情况下,被挂起的线程导致后续请求被阻塞,最终导致订单服务不可用;
  • 服务熔断:当 A 服务去调用 B 服务,如果迟迟没有收到 B 服务的响应,那么就终断当前的请求,而不是一直等待下去,此时还要去监控 B 服务,当 B 服务恢复正常使用时,A 服务再发起请求;
  • 服务降级:A 服务调用 B 服务,没有调用成功发生熔断,那么 A 服务拿一个默认值顶着,避免给我们的用户,响应一些错误的页面;
  • 请求缓存:对接口进行缓存,可以大大降低生产者的压力,适用更新频率低,但是访问又比较频繁的数据;
  • 请求合并:将客户端多个请求合并成一个请求,只发送一个 HTTP 请求,得到响应后再将请求结果分发给不同的请求,这样就可以提供传输效率;
  • Netflix Hystrix 实现了断路器、线程隔离等一系列保护功能,用于隔离访问远程系统、服务或者第三方库,防止联级失败,从而提升系统的可用性与容错性;

2. Resilience4j

简介:

  • 推荐 Spring Cloud 2020 之后版本使用;
  • Resilience4j 是 Spring Cloud G 版本推荐的容错方案,是一个轻量级的容错库,专为 Java 8 和函数式编程而设计,借鉴了 Hystrix 的设计,提供了断路器(CircuitBreaker)、并发调用隔离(Bulkhead)、限流(RateLimiter)、重试(Retry)、超时(Timeout) 等功能;
  • 断路器 CircuitBreaker
    • 断路器一般通过 3 个有限状态机来实现:CLOSED、OPEN、HALF_OPEN,此外,还有 2 个特殊的状态机:DISABLED 和 FORCED_OPEN,状态的存储更新必须是线程安全的,即只有一个线程能够在某个时间点更新状态;
  • 关闭 ----> 打开:当故障率等于或大于可配置的阈值时,CircuitBreaker 的状态将从“关闭”更改为“打开”。
  • 打开 ----> 半开:当 CircuitBreaker 打开时,它会拒绝带有 CallNotPermittedException 的调用,经过一段等待时间后,CircuitBreaker 状态从 OPEN 变为 HALF_OPEN,并允许可配置数量的服务调用是否仍然不可用或再次变为可用,用 CallNotPermittedException 拒绝其他调用,直到所有允许的调用完成,如果故障率或慢呼叫率等于或大于配置的阈值,则状态会变回 OPEN;
  • 半开 ----> 关闭:如果故障率和慢呼叫率低于阈值,则状态将变回“已关闭”;
  • DISABLED:始终拒绝调用;
  • FORCED_OPEN:始终允许调用;

  • 并发调用隔离 Bulkhead

  • 在系统设计中,需要预期故障的发生,将应用程序拆分成多个组件,通过资源隔离确保一个组件的故障不会影响其他的组件,就像轮船用隔板(Bulkhead)分成多个小隔间,每个隔间都被隔板密封,这样可以防止进洪水时整艘船沉没;
  • 两个服务 A 和服务 B,A 的某些 API 依赖 B,当服务 B 运行速度非常慢的时候,A 调用 B 的请求变多时,A 的性能会受到影响,服务 A 中那些不依赖于服务 B 的功能也无法处理,因此,需要隔离 A 中依赖 B 的请求,Resilience4j 提供了 SemaphoreBulkhead 和 FixedThreadPoolBulkhead 来实现 Bulkhead;
  • 限流 RateLimiter
    • 微服务在给定的时间内设置可以处置的最大请求数,控制吞吐量来帮助保护服务器免于过载;
    • 重试 Retry
      微服务体系中,多个服务互相依赖,当被依赖的服务出现问题而无法按预期响应时,就会级联到下游服务,导致不良的用户体验,通常我们会为每个微服务部署多个实例,如果其中一个实例有问题,无法响应我们的请求,我们则重试该请求,负载均衡器可以将请求发送到运行状况良好的节点并正确获得响应,通过重试,有更多机会获得正确的响应;
    • 超时 Timeout
      • 在微服务体系中,微服务相互依赖,可能因为网络的原因,导致消费者阻塞,在设计时需要设置超时来应对服务缓慢 、不可用性问题;

4.网关服务组件

1.Netflix Zuul

简介:

  • 推荐 Spring Cloud 2020 之前版本使用;
  • 未加网关的微服务架构
    • 通过上面的学习,分布式架构基本成型,内部服务集群 Service A 和 Service B,它们都会到注册中心注册和订阅服务,而 Open Service 集群专门对外提供接口,这样的实现是否合理?是否有更好的方法?

 

这种架构破坏了服务无状态特点:为了保证对外服务的安全性,我们需要实现对服务访问的权限控制,而 Open Service 的访问权限机制会贯穿并污染整个开放服务的业务逻辑,破坏了集群中 Rest Api 无状态的特点,从具体的开发来说,工作中除了要考虑实际业务逻辑之外,还要额外持续对接口的访问做权限处理;

  • 无法直接复用接口:当我们需要一个已有的集群内部接口,我们不得不在原有的接口上做校验逻辑,或者增加一个代理来做权限控制,无法直接复用原有的接口;

网关服务
将权限控制、日志收集从服务单元中抽离出去,最适合的地方是服务集群的最外端,我们需要一个功能更强大的负载均衡器,网关服务;
网关服务是微服务架构中不可或缺的一部分,它具备统一向外提供 Rest Api、服务路由、负载均衡、权限控制等功能,为微服务架构提供了门前保护,除了安全之外,还能让服务集群具备高可用性和测试性;

Zuul 是 NetFlix 开源的微服务网关,可以和 Eureka、Ribbon、Hystrix 等组件配合使用,其核心是一系列的过滤器;

  • 身份认证和安全:识别每个资源的验证要求,拒绝不符合要求的请求;
  • 审查与监控:在边缘位置追踪有意义的数据和统计结果,从而带来精确的生产视图;
  • 动态路由:动态地将请求路由到不同的后端服务集群;
  • 压力测试:逐渐增加指向集群的流量;
  • 负载分配:为每一种负载类型分配对应容量,并弃用超出限定值的请求;
  • 静态响应处理:在边缘位置直接建立部分响应,从而避免其转发到集群内部;
  • 多区域弹性:跨越 AWS Region 进行请求路由,实现 ELB(AWS Elastic Load Balancing ---- 负载均衡服务)使用的多样化,以及让系统的边缘更贴近系统的使用者;
  • 使用 Zuul 后的微服务架构

  • 客户端请求微服务时,先经过 Zuul,再调用微服务集群,这样对于校验、负载均衡等功能移到了 Zuul 中实现,而微服务只需关注自身的业务逻辑则可;

5、配置中心组件

Spring Cloud Config

简介:

  • 之前配置文件是否存在的问题?
    • 微服务各自拥有自己的配置文件,当配置修改之后,我们需要重启项目,如果数量庞大,维护成本增加,针对这个问题,我们采用 Spring Cloud Config 来做配置;
    • Spring Cloud Config 为分布式系统外部化配置提供了服务端和客户端的支持,它包含 Config Server 和 Config Client 两个部分,实现了 Spring Environment  和 PropertySource 抽象的映射,非常适合 Spring 应用程序;
    • Config Server 是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,支持 Git、SVN、本地文件存储,默认使用 Git;
    • Config Client 是 Config Server 的客户端,用于操作存储在 Config Server 中的配置内容,微服务在启动时会请求 Config Server 获取配置文件的内容,请求到后再启动容器;

 

1.Config Server

  • 创建仓库
    • 创建 Git 远程仓库,并将微服务所有配置文件上传到仓库中,配置文件命名规则
    • 环境配置:application-profile.properties;
    • 配置中心:application-profile.profiles;
  • 创建工程,选择 Eureka Discovery Client、Config Server 组件;
  • 导入pom,配置文件以及启动类配置
  • 启动测试

2.Config Client

  •  加入bootstrap支持,pom
  • 创建bootstrap.properties
  • 拆分application.properties,本地 application.properties 中的配置分成两个部分
  • 注册部分,Eureka 相关配置、引入的其余配置文件配置(比如 logback.xml),移植到 bootstrap.properties 配置文件中,注册微服务
  • 其余配置项,移植到远程配置仓库中对应的配置文件中;
  • 删除 application.properties 配置(我对之进行重命名备份);
  • 微服务启动,到注册中心中去注册,才能获取配置中心提供的功能,去读取git仓库中的配置文件
  • 注册中心配置,就需要从application.properties移到bootstrap.properties;

配置加载顺序:

  • 读本地 bootstrap.properties
  • 到注册中心注册服务
  • 连接 Config Server,加载远程配置 applicationTest-dev.properties
  • 加载本地 application.properties

SpringCloud的五大核心组件俊哥,侯哥

乐优项目SpringCloud笔记总结

ly-item 商品的的mapper模块,里面有datasource

ly-cart: 购物车模块

ly-registry: 注册中心服务端,其他的模块都是客户端

ly-api-gateway: 路由网关

ly-feign:远程调用

注册中心Eureka,ly-registry服务端

lyregistry这个Module作为服务端

服务端可以进行配置

server:
  port: 10086

spring:
  application:
    name: ly-registry

eureka:
  client:
    fetch-registry: false
    register-with-eureka: false
    service-url:
      defaultZone: http://localhost:${server.port}/eureka

  server:
    enable-self-preservation: false #关闭自我保护
    eviction-interval-timer-in-ms: 5000 #每隔5秒进行一次服务列表清理
package com.yunhe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class LyRegistry {
    public static void main(String[] args) {
        SpringApplication.run(LyRegistry.class,args);
    }
}


使用ly-user作为客户端进行相关的测试:

package com.yunhe;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients  //开启feign功能
public class LyUserApplication {
    public static void main(String[] args) {
        SpringApplication.run(LyUserApplication.class,args);
    }
}

加入相关的客户端实现的依赖:

 <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--feign实现远程调用 ly-item-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.persistence</groupId>
            <artifactId>persistence-api</artifactId>
            <version>1.0</version>
        </dependency>

客户端的配置

server:
  port: 10010

spring:
  application:
    name: item-service


  datasource:
    url: jdbc:mysql://localhost:3306/leyou?characterEncoding=UTF-8&useSSL=false
    username: root
    password: roothouzhicong

    hikari:
      maximum-pool-size: 30
      minimum-idle: 10

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    lease-renewal-interval-in-seconds: 5 #每隔6秒发送一次心跳
    lease-expiration-duration-in-seconds: 10 #10秒不发送就过期
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${spring.application.name}:${server.port}
    
 # 对Ribbon进行配置
item-service: #feign里面负载均衡配置
  ribbon:
    ConnectTimeout: 250 # Ribbon的连接超时时间
    ReadTimeout: 3000 # Ribbon的数据读取超时时间
    OkToRetryOnAllOperations: true # 是否对所有操作都进行重试
    MaxAutoRetriesNextServer: 1 # 切换实例的重试次数
    MaxAutoRetries: 1 # 对当前实例的重试次数

feign:
  hystrix:
    enabled: true # 开启Feign的熔断功能,默认为关闭
    

Feign实现远程调用

ly-user这个模块调用ly-item

  1. 在ly-user的pom.xml文件加入feign的依赖

  2. 在ly-user的LyApplication 启动类上加入**@EnableFeignClients**注解

  3. 在client客户端下面创建一个itemClient接口

  4. @RequestMapping("brand")
    

加上这个前端要用的请求的路径。

  1. 加入Service这个接口中的定义的相关的方法。
  2. 前面加上**@FeignClient(name=“item-service”)** (item-service是这个ly-item这个模块里面的spring.application.name=item-service)
  3. 由于还没有进行优化,我们可以先把pojo类全部复制粘贴过来
  4. 建立一个BrandController进行前端的测试输入这个测试类的请求就好

itemClient:

package com.yunhe.client;

import com.yunhe.pojo.Brand;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

//注意:类上面不要写@RequestMapping
@FeignClient(name = "item-service",fallback = ItemClientFallback.class)
public interface ItemClient {

    @GetMapping("brand")
    public List<Brand> listAll();


}
@RestController
public class UserController {

    @Autowired
    private ItemClient itemClient;

    @GetMapping
    public List<Brand> queryAllBrands(){
        return itemClient.listAll();
    }
}

Ribbon负载均衡

  1. 可以知道feignEureka,zuul中已经自带了ribbon和Hystrix,所以不用引入依赖.

Hystrix熔断器

feign里面自带熔断器,但是默认是关闭状态的,需要手动开启

使ly-user模块调用ly-item模块,需要feign和hystrix,进行hystrix步骤:

  1. yml文件加上:
feign:
	hystrix:
	enabled: true #开启熔断器
  1. 创建client包然后进行创建下面的类: //注意:类上面不要写@RequestMapping ,这里的@GetMapping(“brand”)和ly-item里面的controller测试的请求一样。
package com.yunhe.client;

import com.yunhe.pojo.Brand;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

//注意:类上面不要写@RequestMapping
@FeignClient(name = "item-service",fallback = ItemClientFallback.class)
public interface ItemClient {

    @GetMapping("brand")
    public List<Brand> listAll();


}

  1. 创建 ItemClientFallback实现类: ly-item的服务断了不会影响ItemClientFallback方法的执行
package com.yunhe.client;

import com.yunhe.client.ItemClient;
import com.yunhe.pojo.Brand;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Component
public class ItemClientFallback implements ItemClient {
    @Override
    @GetMapping("brand")
    public List<Brand> listAll() {
        System.out.println("服务断了,呜呜呜呜。。。");
        return null;
    }
}

zuul网关

  1. 创建一个单独的模块ly-api-gateway,所有的端口号会经过zuul处理。
  2. 当然其他的所有模块都是注册中心的客户端,需要加上**@EnableDiscoveryClient,在主配置文件上面**
  3. **引入网关的依赖,**也需要引入eureka客户端的依赖
<!--zuul网关-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>


        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
  1. 启动类上面 加上**@EnableZuulProxy** 网关代理注解

  2. 在ly-api-gateway的application.yml文件中配置网关,注意一下:routes 下面的 item-service是配置文件中的spring.application.name 的名字

zuul:
	prefix: /api #添加路由前缀
	retryable: true
	routes:
		item-service: /item/** #商品服务
		user-service: /user/** #用户微服务
		cart-service: /cart/** #购物车服务
  1. 网关的所有的配置文件信息
server:
  port: 10000

spring:
  application:
    name: api-gateway

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka
  instance:
    lease-renewal-interval-in-seconds: 5 #每隔6秒发送一次心跳
    lease-expiration-duration-in-seconds: 10 #10秒不发送就过期
    prefer-ip-address: true
    ip-address: 127.0.0.1
    instance-id: ${spring.application.name}:${server.port}
zuul:
  prefix: /api # 添加路由前缀
  retryable: true #当网关没有连接上来的时候是否可以重试
  routes:
    item-service: /item/**  #商品微服务 /item下的所有的请求
    user-service: /user/**  #用户微服务
    cart-service: /cart/** #购物车微服务

ribbon:
  ConnectTimeout: 60000 # 连接超时时间(ms)
  ReadTimeout: 60000 # 通信超时时间(ms)
  OkToRetryOnAllOperations: true # 是否对所有操作重试
  MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数
  MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMillisecond: 10000 # 熔断超时时长:10000ms
  1. 通过网关进行访问ly-item里面的增删改查的操作。

    http://localhost:10000/api/item/brand 和 不用网关访问的效果一样 http://localhost:10010/brand

  2. zuul自带hystrix和Ribbon功能,需要我们通过配置文件开启

  3. 网关可以进行过滤的配置

package com.yunhe.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.stereotype.Component;
//注意一下需要加上这个@Component组件 
@Component
public class LoginFilter extends ZuulFilter{
    /**
     * - pre:请求在被路由之前执行
     * - routing:在路由请求时调用
     * - post:在routing和errror过滤器之后调用
     * - error:处理请求时发生错误调用
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    //数字越小优先级越高
    @Override
    public int filterOrder() {
        return 1;
    }

    //是否进行过滤  true 过滤  false 不进行过滤
    @Override
    public boolean shouldFilter() {
        return true;
    }

    //run()   过滤的方法
    @Override
    public Object run() throws ZuulException {
        System.out.println("zuul filter执行了。。。。。");
        return null;
    }
}

以上是关于一文让你了解SpringCloud五大核心组件的主要内容,如果未能解决你的问题,请参考以下文章

SpringCloud五大核心组件

SpringCloud的五大核心组件俊哥,侯哥

「五大常用算法」一文图解分治算法和思想

五大常用算法一文搞懂分治算法

SpringCloud系列SpringCloud概述及微服务技术栈的使用

SpringCloud 五大组件基础介绍