SpringCloud 笔记篇

1.springcloud 和 springboot 版本对应关系

Spring Cloud 和 boot 对应版本

更详细的技术选型(版本对应关系)

https://start.spring.io/actuator/info

Gitee项目传送门: spring-cloud-alibaba

一、服务注册中心

CAP理论

Consistency: 一致性

Availability: 可用性

Partition tolerance: 分区容错性

1.1 Euraka(AP)

  • 关键注解:

@EnableEurekaServer

@EnableEurekaClient(可省略不写)

  • 依赖
<!--服务端-->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<!--客户端-->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
  • 配置
# 1.服务端配置
server:
  port: 7001
eureka:
  instance:
    hostname: localhost
  client:
    register-with-eureka: false  #是否自我注册
    fetch-registry: false  #是否从注册中心获取注册的服务信息
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 
  server:
    enable-self-preservation: false  #禁止eureka自我保护

-------手动分割---------

# 2.客户端配置
eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      default:http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  instance:
    instance-id: payment8001  #instance重命名,默认为 PC名:APPNAME
    prefer-ip-address: true #访问路径可以显示IP地址
    lease-renewal-interval-in-seconds: 10   #客户端向服务端发送心跳的时间间隔,默认30s
    lease-expiration-duration-in-seconds: 10  #服务端在收到最后一次心跳后的等待时间上限,默认90s 后剔除服务

1.2 Zookeeper(CP)

  • 安装
wget wget http://mirrors.hust.edu.cn/apache/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz

tar -zxvf zookeeper-3.4.13.tar.gz

cd /usr/local/zookeeper

#启动
./zkServer.sh
  • 依赖
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.14</version>
        </dependency>
  • 配置
spring:
  application:
    name: cloud-payment-service
  cloud:
    zookeeper:
      connect-string: 192.168.101.102:2181

1.3 Consul(CP)

由Go语言开发,是一套开源的分布式服务发现和配置管理系统。

  • 安装
wget https://releases.hashicorp.com/consul/1.12.0/consul_1.12.0_linux_amd64.zip --no-check-certificate
unzip consul_1.12.0_linux_amd64.zip
./consul
./consul agent -dev -ui -node=consul-dev -client=192.168.x.x
  • 依赖
<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
  • 配置
spring:
  application:
    name: consul-provider-payment
  cloud:
    consul:
      host: localhost
      port: 8500
      discovery:
        service-name: ${spring.application.name}
        instance-id: ${spring.application.name}
        port: ${server.port}
        ip-address: ${spring.cloud.consul.discovery.instance-id}

1.4 Nacos

二、服务调用

2.1 Ribbon

  • 什么是Ribbon?

客户端负载均衡工具。

当我们启动 orderservice,第一次访问时,时间消耗会大很多,这是因为 Ribbon 懒加载的机制。

  • Ribbon核心组件IRule,有自带的负载均衡算法

Ribbon的自定义配置类,不能放在@ComponentScan所扫描的当前包以及子包下(也就是说要和使用@SpringBootApplication的类的父文件夹同级。),否则自定义的配置类就会被所有的Ribbon客户端共享,达不到特殊化定制的目的了。

  • 手写轮询算法(扩展)
/**
 * @author o_o
 * @date 2022-07-29
 */
@Component
public class LoadBalancerImpl implements LoadBalancer {

    private final AtomicInteger atomicInteger = new AtomicInteger(0);

    @Override
    public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
        int index = getAndIncrement() % serviceInstances.size();
        return serviceInstances.get(index);
    }

    //CAS
    private int getAndIncrement() {
        int current;
        int next;
        do {
            current = atomicInteger.get();
            next = current >= Integer.MAX_VALUE ? 0 : current + 1;
        } while (!atomicInteger.compareAndSet(current, next));
        System.out.println("********** next = " + next);
        return next;
    }
}

2.2 Openfeign

  • 什么是openfeign? 接口+注解

Feign是一个声明式webservice客户端,使用feign能让编写webservice客户端更加简单。Feign可以与Eureka和Ribbon组合使用支持负载均衡。

  • 依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • openfeign的使用 ,注解+接口
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")
public interface PaymentService {

    /**
     * feign 实现远程调用
     *
     * @return string
     */
    @GetMapping("/payment/feign")
    String feign();

}
  • openfeign超时控制
# 设置feign 客户端超时时间(openFeign默认支持ribbon)
ribbon:
  # 两端建立连接的时间
  ReadTimeout: 3000
  # 从服务器读取资源的时间
  ConnectTimeout: 5000
  • openfeign日志功能
logging:
  level:
    com.kk.feign.service.PaymentService: debug
  • 配置类
@Configuration
public class FeignConfig {

    /**
     * NONE: 默认的,不显示任何日志
     * BASIC:仅记录请求方法、URL、响应状态码以及执行时间
     * HEADERS:除了BASIC中定义的信息以外,还有请求和响应的头信息
     * FULL: 除了HEADERS中定义的信息之外,还有请求和响应的正文及元数据
     * @return level
     */
    @Bean
    Logger.Level feignLogger() {
        return Logger.Level.FULL;
    }
}

三、服务降级/熔断/限流

3.1 Hystrix

  • 依赖
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

什么是Hystrix ?能干嘛?

断路器。可以做服务降级、熔断、限流,以及接近实时的监控。

3.1.1服务降级 fallback

当服务不可用(异常或超时),不让客户端一直等待,并立即返回一个友好提示。

场景:程序异常、超时、服务熔断触发服务降级、线程池/信号量打满也会导致服务降级。

@EnableCircuitBreaker

  • 单个的服务降级

@HystrixCommand(fallbackMethod = "pocketBottom", commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000") })

  • 全局的服务降级

@HystrixCommand

@DefaultProperties(defaultFallback = "globalFallbackMethod")

  • 调用的服务挂了

先写一个feign接口的实现类

@FeignClient(value = "hystrix-payment-service", fallback = PaymentFallbackServiceImpl.class)

3.1.2服务熔断 break

  • 服务降级-->服务熔断-->恢复调用链路

当服务挂了,直接拒绝访问,触发服务降级返回友好提示。类似保险丝。

@HystrixCommand(fallbackMethod = "hystrixCircuitBreakerFallback", commandProperties = { //是否开启断路器 @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ENABLED, value = "true"), //请求次数 @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_REQUEST_VOLUME_THRESHOLD, value = "10"), //时间窗口期 @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_SLEEP_WINDOW_IN_MILLISECONDS, value = "10000"), //失败率到达多少跳闸 @HystrixProperty(name = HystrixPropertiesManager.CIRCUIT_BREAKER_ERROR_THRESHOLD_PERCENTAGE, value = "60"), })

3.1.3服务限流 flowlimit

秒杀高并发等操作,严禁全部请求打过来,大家排队一秒N个,有序进行。

四、服务网关

4.1 Spring Cloud Gateway

  • 什么是Gateway??

Gateway,API网关服务,是zuul 1.x的代替版。旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式的通信框架Netty。

  • 依赖
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
  • yml
server:
  port: 9527
spring:
  application:
    name: cloud-gateway
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedHeaders: "*"
            allowedMethods: "*"
            default-filters:
              - DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_FIRST

      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由

      routes:
        - id: pament_rout1            # 路由的唯一标识
#          uri: http://localhost  # 如果断言成功,将要转发去的地址
          uri: lb://CLOUD-CONSUMER-FEIGN-ORDER  # 如果断言成功,将要转发去的地址
          predicates:
            - Path=/order/**     # 断言,路径匹配的进行路由

        - id: pament_rout2
#          uri: http://localhost  # 如果断言成功,将要转发去的地址
          uri: lb://CLOUD-CONSUMER-FEIGN-ORDER  # 如果断言成功,将要转发去的地址          order: 0
          predicates:
            - Path=/feign/circuitBreak/**
#            - Before=2021-08-25T12:53:46.101+08:00[Asia/Shanghai] #匹配这个时间之前的请求
#            - After=2021-08-25T12:53:46.101+08:00[Asia/Shanghai]  #匹配这个时间之后的请求
#            - Between=2021-08-25T12:53:46.101+08:00[Asia/Shanghai],2021-09-25T12:53:46.101+08:00[Asia/Shanghai] #匹配这个两个时间的请求
#            - Cookie=name,wwzzqq
#            - Header=X-Request-Id,\d+  #请求头要有 X-Request-Id 属性并且值为整数的正则表达式
#            - Host=shangguigu.com
#            - Method=GET  #请求方式是 GET
#            - Query=username,\d+ #要有参数名 username 并且值还要是证书才能路由


eureka:
  instance:
    hostname: cloud-gateway-service
  client:
    service-url:
     defaultZone: http://eureka7001.com:7001/eureka
    register-with-eureka: true
    fetch-registry: true

五、服务配置中心

5.1 SpringCloud Config Center

  • 什么是配置中心?

SpringCloud Config Center 为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。

服务端配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>
server:
  port: 3344

spring:
  application:
    name: config-center
  cloud:
    config:
      server:
        git:
          uri: https://gitee.com/kk-dad/springcloud-config.git
          search-paths:
            - springcloud-config
      label: master

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
    register-with-eureka: true
    fetch-registry: true

客户端配置

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-client</artifactId>
</dependency>

application.yml 改为 bootstrap.yml,这是关键的一步不然启动会报错!!

server:
  port: 80

spring:
  application:
    name: cloud-consumer-feign-order-config-client
  cloud:
    config:
      label: master
      name: application
      profile: dev
      uri: http://localhost:3344


eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    #客户端向服务端发送心跳的时间间隔,默认30s
    lease-renewal-interval-in-seconds: 10
    #服务端在收到最后一次心跳后的等待时间上限,默认90s 后剔除服务
    lease-expiration-duration-in-seconds: 10

六、spring cloud bus 消息总线

  • 什么是消息总线?

在微服务架构体系中,通常会使用轻量级的消息代理来构建一个共用的消息主题,并让系统中所有微服务实例都连接上来。由于该主题中产生的消息会被所有实例监听和消费,所以会被称为消息总线。

  • 基本原理

config client 实例都监听MQ中的同一个topic(默认是springcloud bus)。当一个服务刷新数据的时候,他会把这个消息放入到topic中,这样其他监听同一个topic的服务就得到通知,然后更新自身的配置信息。

  • spring cloud bus?

springcloud bus是用来将分布式系统的节点与轻量级消息系统链接起来的框架,它整合了Java的事件处理机制和消息中间件的功能。springcloud bus 目前支持 RabbitMQ 和 Kafka。

Spring cloud Bus 配合 Spring cloud config center 可以实现配置的动态刷新。

  • 依赖
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.kk</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
  • 配置
server:
  port: 3355

spring:
  application:
    name: config-client3355
  cloud:
    config:
      label: master
      name: application
      profile: dev
      uri: http://localhost:3344
  rabbitmq:
    host: 172.24.108.226
    port: 5672
    username: cloud
    password: qaq123..


eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
    #客户端向服务端发送心跳的时间间隔,默认30s
    lease-renewal-interval-in-seconds: 10
    #服务端在收到最后一次心跳后的等待时间上限,默认90s 后剔除服务
    lease-expiration-duration-in-seconds: 10

management:
  endpoints:
    web:
      exposure:
        include: '*'

全局刷新 curl -X POST "http://localhost:8002/actuator/refresh"

七、spring cloud stream 消息驱动

技术兴起原因:为了解决系统中不同中间件的适配问题。采用适配绑定的方式,自动切换不同的MQ。

Spring Cloud Stream为一些消息中间件提供了个性化的自动配置,引用了发布、订阅、消费、分区的三个核心概念。官方版本目前仅仅支持RabbitMQ和Kafka。

MQ相关术语
Message:生产者/消费者之间靠消息媒介传递信息内容

MessageChannel:消息必须走特定的通道

消息通道的子接口SubscribableChannel,由MessageHandle消息处理器所订阅。

相关注解
Middleware:中间件,目前只支持RabbitMQ和Kafka
Binder:应用层和消息中间件之间的封装,实现了Kafka和RabbitMQ的Binder,通过Binder可以很方便的连接中间件,可以动态的改变消息类型,这些可以通过配置文件修改。
Input:表示输入通道,消息进入该通道传到应用程序。
Output:注解标识输出通道,发布的消息将通过该通道离开应用程序。
StreamListener:监听队列,用于消费者的队列的消息接收。
EnableBinding:将信道channel和exchange绑定在一起。

  • 依赖
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>    
 </dependencies>
  • 服务提供者配置
server:
  port: 9000

spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders:
       defaultRabbit:
         type: rabbit
      bindings: # 服务的整合处理
        out: # 这个名字是一个通道的名称
          destination: wzq-xchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”
  rabbitmq:
      host: localhost #rabbitmq服务启动所在机器的IP地址
      port: 5672
      username: cloud
      password: qaq123..

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    instance-id: ${spring.cloud.client.ip-address}:${server.port}  # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
  • 服务消费者配置
server:
  port: 9100

spring:
  application:
    name: cloud-stream-consumer
  cloud:
    stream:
      binders: # 在此处配置要绑定的rabbitmq的服务信息;
        defaultRabbit: # 表示定义的名称,用于于binding整合
          type: rabbit # 消息组件类型
          environment: # 设置rabbitmq的相关的环境配置
            spring:
              rabbitmq:
                host: 192.168.31.52
                port: 5672
                username: guest
                password: guest
      bindings: # 服务的整合处理
        input: # 这个名字是一个通道的名称
          destination: studyExchange # 表示要使用的Exchange名称定义
          content-type: application/json # 设置消息类型,本次为对象json,如果是文本则设置“text/plain”

eureka:
  client: # 客户端进行Eureka注册的配置
    service-url:
      defaultZone: http://localhost:7001/eureka
  instance:
    lease-renewal-interval-in-seconds: 2 # 设置心跳的时间间隔(默认是30秒)
    lease-expiration-duration-in-seconds: 5 # 如果现在超过了5秒的间隔(默认是90秒)
    instance-id:  ${spring.cloud.client.ip-address}:${server.port} # 在信息列表时显示主机名称
    prefer-ip-address: true     # 访问的路径变为IP地址
  • 常用注解

imagepng

7.1重复消费问题

默认情况下,每个消费者的分组名都是随机的。不同的组会引起重复消费的问题,例如:消息提供者只向消息队列中发送了一个消息,正常情况下,消费者A从队列中拿走之后,消费者B不能再获得相同的消息,但是由于AB是不同的组,所以A和B都会获取相同的消息,这就导致了资源被重复消费。

微服务应用放置到同一个group中,就能够保证消息只会被应用消费一次,不同的组是可以消费的,同一个组内会发生竞争关系,只有其中一个可以消费。

7.2消息持久化

两个消费者A和B,A设置了group属性值,B没有设置,这时消费者全部宕机,但是消息生产者一直响MQ中生产消息,这时候重启A和B会怎样?

B没有分组,所有再次启动后不会从MQ中取数据,A启动成功后可以正常消费MQ中的消息。

消费者设置group,可以保证消息队列中的消息持久化,group对于消费者来讲很重要,既能避免重复消费,又能在消费者重启后可以消费MQ中未消费的消息。

八、分布式链路追踪 Sleuth

微服务跟踪(sleuth)是一个工具, 它在整个分布式系统中能跟踪一个用户请求的过程(包括数据采集,数据传输,数据存储,数据分析,数据可视化),捕获这些跟踪数据,就能构建微服务的整个调用链的视图,这是调试和监控微服务的关键工具。
SpringCloudSleuth有4个特点

截屏20221204 205200png

  • pom
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.kk</groupId>
            <artifactId>cloud-api-commons</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-commons</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-zipkin</artifactId>
        </dependency>
  • yml
server:
  port: 8080

spring:
  application:
    name: hystrix-payment-service
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1   # 采样值介于0-1之间,1表示全部采集

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

  instance:
    prefer-ip-address: true
    instance-id: ${spring.cloud.client.ip-address}:${server.port}
posted @ 2022-11-21 00:19  little_lunatic  阅读(65)  评论(0)    收藏  举报