SpringCloud 学习笔记

❤ 作者主页:Java技术一点通的博客
❀ 个人介绍:大家好,我是Java技术一点通!( ̄▽ ̄)~*
🍊 记得关注、点赞、收藏、评论⭐️⭐️⭐️
📣 认真学习,共同进步!!!🎉🎉

第一章 SpringCloud简介

一、 软件架构演进

  • 单体架构
    在这里插入图片描述
     

  • 垂直架构
    在这里插入图片描述
     

  • 分布式架构
    在这里插入图片描述
     

  • SOA架构
    在这里插入图片描述
     

  • 微服务架构
    在这里插入图片描述

 


二、微服务架构

1. 微服务理念

(1) "微服务”一词源 于 Martin Fowler的名为 Microservices的博文,可以在他的官方博客上找到http://martinfowler.com/articles/microservices.html

(2) 微服务是系统架构上的一种设计风格,它的主旨是将一个原本独立的系统拆分成多个小型服务,这些小型服务都在各自独立的进程中运行,服务之间一般通过 HTTP 的 RESTfuL API 进行通信协作。

restfull 风格: 数据的增删改查,使用http的不同方式。数据传输用json。

  • 查询 GET ip:port/user/1

  • 新增 POST ip:port/user json{username:itlils,age:18}

  • 修改 PUT ip:port/user/1 json{username:itlils,age:19}

  • 删除 DELETE ip:port/user/1

(3) 由于有了轻量级的通信协作基础,所以这些微服务可以使用不同的语言来编写。大厂,各种语言混用。
cloud官网: https://spring.io/
在这里插入图片描述
 
在这里插入图片描述
 

2. 现在大型互联网公司,都在使用微服务架构

  • 京东的促销节架构:
    在这里插入图片描述
     
  • 阿里的架构:
    在这里插入图片描述
     
  • 京东物流的架构:
    在这里插入图片描述
     

3. springcloud组件

在这里插入图片描述
在这里插入图片描述
 


第二章 走进springcloud

一、了解springcloud

  1. Spring Cloud 是一系列框架的有序集合。

  2. Spring Cloud 并没有重复制造轮子,它只是将目前各家公司开发的比较成熟、经得起实际考验的服务框架组合起来。

    netflix eureka 1.1,alibaba 2.2

  3. 通过 Spring Boot 风格进行再封装,屏蔽掉了复杂的配置和实现原理,最终给开发者留出了一套简单易懂、易部署和易维护的分布式系统开发工具包。

  4. 它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务发现注册、配置中心、消息总线、负载均衡、 断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署。

  5. Spring Cloud项目官方网址:https://spring.io/projects/spring-cloud

  6. Spring Cloud 版本命名方式采用了伦敦地铁站的名称,同时根据字母表的顺序来对应版本时间顺序,比如:最早的Release版本:Angel,第二个Release版本:Brixton,然后是Camden、Dalston、Edgware,Finchley,Greenwich,Hoxton。

    目前最新的是2021.0.1版本。

在这里插入图片描述
 


二、 cloud与boot版本对应关系

在这里插入图片描述
 


三、 cloud与dubbo对比

在这里插入图片描述
 
相同点: Spring Cloud 与 Dubbo 都是实现微服务有效的工具。

不同点:

  • Dubbo 只是实现了服务治理,而 Spring Cloud 子项目分别覆盖了微服务架构下的众多部件。

  • Dubbo 使用 RPC 通讯协议,Spring Cloud 使用 RESTful 完成通信,Dubbo 效率略高于 Spring Cloud。

小结:

  • 微服务就是将项目的各个模块拆分为可独立运行、部署、测试的架构设计风格。

  • Spring 公司将其他公司中微服务架构常用的组件整合起来,并使用 SpringBoot 简化其开发、配置。称为 Spring Cloud。

  • Spring Cloud 与 Dubbo都是实现微服务有效的工具。Dubbo 性能更好,而 Spring Cloud 功能更全面。Dubbo 已经融入到spingcloudAlibaba这一套。


第三章 停更/升级/替换

在这里插入图片描述


第四章 微服务架构编码构建

在这里插入图片描述
 

一、 搭建 Provider 和 Consumer 服务

1. 父工程 spring-cloud-parent

  • 创建spring-cloud-parent父工程
    在这里插入图片描述
     

  • 使用utf-8编码:
    在这里插入图片描述
     

  • maven设置:
    在这里插入图片描述
     

  • pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>spring-cloud-parent</artifactId>
        <version>1.0.0</version>
    
        <!--spring boot 环境 -->
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.2.11.RELEASE</version>
            <relativePath/>
        </parent>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        </properties>
    
    </project>
    

2. 提供者 eureka-provider

  • 创建 eureka-provider子模块
    在这里插入图片描述

  • 引入依赖

     <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
    
  • application.yml

    server:
      port: 8000
    
  • 创建启动类

    @SpringBootApplication
    public class ProviderApplication {
        public static void main(String[] args) {
            SpringApplication.run(ProviderApplication.class,args);
        }
    }
    
  • 实体类

    public class Goods implements Serializable {
        
        private int id;//商品id
        private String title;//商品名
        private double price;//价格
        private int count;//库存
    
        public Goods() {
        }
    
        public Goods(int id, String title, double price, int count) {
            this.id = id;
            this.title = title;
            this.price = price;
            this.count = count;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public int getCount() {
            return count;
        }
    
        public void setCount(int count) {
            this.count = count;
        }
    
        @Override
        public String toString() {
            return "Goods{" +
                    "id=" + id +
                    ", title='" + title + '\'' +
                    ", price=" + price +
                    ", count=" + count +
                    '}';
        }
    }
    
  • controller层

    @RestController
    @RequestMapping("goods")
    public class GoodsController {
    
        @Autowired
        private GoodsService goodsService;
    
        @GetMapping("findById/{id}")
        public Goods findById(@PathVariable("id") int id) {
            Goods goods = goodsService.findById(id);
            return goods;
        }
    }
    
  • service层

    @Service
    public class GoodsService {
    
        @Autowired
        private GoodsDao goodsDao;
    
        public Goods findById(int id) {
            Goods goods = goodsDao.findById(id);
            return  goods;
        }
    }
    
  • dao层

    @Repository
    public class GoodsDao {
        public Goods findById(int id) {
            return new Goods(id, "手机", 2000, 1000);
        }
    }
    
  • 测试
    访问:http://localhost:8000/goods/findById/1

    在这里插入图片描述
     


3. 消费者 eureka-consumer

  • 创建 eureka-consumer子模块
    在这里插入图片描述

  • 引入依赖

     <dependencies>
    
            <!--spring boot web-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
        </dependencies>
    
  • application.yml

    server:
      port: 9000
    
  • 创建启动类

    @SpringBootApplication
    public class ConsumerApplication{
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class,args);
        }
    }
    
  • 实体类

    public class Goods implements Serializable {
        
        private int id;//商品id
        private String title;//商品名
        private double price;//价格
        private int count;//库存
    
        public Goods() {
        }
    
        public Goods(int id, String title, double price, int count) {
            this.id = id;
            this.title = title;
            this.price = price;
            this.count = count;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
        public int getCount() {
            return count;
        }
    
        public void setCount(int count) {
            this.count = count;
        }
    
        @Override
        public String toString() {
            return "Goods{" +
                    "id=" + id +
                    ", title='" + title + '\'' +
                    ", price=" + price +
                    ", count=" + count +
                    '}';
        }
    }
    
  • controller层

    @RestController
    @RequestMapping("/order")
    public class OrderController {
    
        @GetMapping("/add/{id}")
        public Goods add(@PathVariable("id") Integer id) {
            //业务逻辑
    
            //1查询商品
    
            //2减库存
    
            //3支付
    
            //4物流
            return new Goods();
        }
    }
    
  • 测试
    访问:http://localhost:9000/order/add/2

    在这里插入图片描述
     


二、使用 RestTemplate 完成远程调用

  • Spring提供的一种简单便捷的模板类,用于在 java 代码里访问 restful 服务。
  • 其功能与 HttpClient 类似,但是 RestTemplate 实现更优雅,使用更方便。

eureka-consumer 模块中添加 RestTemplate 类:

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

OrderController

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("/add/{id}")
    public Goods add(@PathVariable("id") Integer id) {
        /*
            远程调用eureka—provider服务中的findById接口:使用RestTemplate
            1. 定义Bean  restTemplate
            2. 注入Bean
            3. 调用方法
         */

        String url = "http://localhost:8000/goods/findById/"+id;

        Goods goods = restTemplate.getForObject(url, Goods.class);

        return goods;
    }
}

测试:
启动 eureka-providereureka-consumer 两个服务,访问:http://localhost:9000/order/add/8
在这里插入图片描述


第五章 Eureka服务注册与发现

一、Eureka

概念:

  • Eureka 是 Netflix 公司开源的一个服务注册与发现的组件 。

  • Eureka 和其他 Netflix 公司的服务组件(例如负载均衡、熔断器、网关等) 一起,被 Spring Cloud 社区整合为Spring-Cloud-Netflix 模块。

  • Eureka 包含两个组件:Eureka Server (注册中心) 和 Eureka Client (服务提供者、服务消费者)。

操作:
在这里插入图片描述
nbgsp;


二、 搭建 Eureka Server 服务

(1)创建 eureka-server 模块

(2) 引入 SpringCloud 和 euraka-server 相关依赖

(3)完成 Eureka Server 相关配置

(4)启动该模块


父工程pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring-cloud-parent</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <modules>
        <module>eureka-provider</module>
        <module>eureka-consumer</module>
        <module>eureka-server</module>
    </modules>

    <!--spring boot 环境 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <!--spring cloud 版本-->
        <spring-cloud.version>Hoxton.SR10</spring-cloud.version>
    </properties>

    <!--引入Spring Cloud 依赖-->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

</project>

eureka-server工程

  • 引入依赖

       <dependencies>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <!-- eureka-server -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            </dependency>
        </dependencies>
    
  • 创建启动类

    @SpringBootApplication
    // 启用EurekaServer
    @EnableEurekaServer
    public class EurekaApplication {
    
       public static void main(String[] args) {
           SpringApplication.run(EurekaApplication.class,args);
       }
    }
    
  • application.yml

    server:
      port: 8761
    
    # eureka 配置
    # eureka 一共有4部分 配置
    # 1. dashboard:eureka的web控制台配置
    # 2. server:eureka的服务端配置
    # 3. client:eureka的客户端配置
    # 4. instance:eureka的实例配置
    
    eureka:
      instance:
        hostname: localhost # 主机名
      client:
        service-url:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
    
        register-with-eureka: false # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要
        fetch-registry: false # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要
    
    
  • 测试
    启动项目后,访问:http://localhost:8761/
    在这里插入图片描述
     


三、 改造 Provider 和 Consumer 称为 Eureka Client

(1)引 eureka-client 相关依赖

(2)完成 eureka client 相关配置

(3)启动 测试


eureka-provider 工程

  • 引入依赖

    		<!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
  • 启动类上添加注解

    @EnableEurekaClient
    
  • application.yml

    server:
      port: 8001
    
    
    eureka:
      instance:
        hostname: localhost # 主机名
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
    spring:
      application:
        name: eureka-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
    

eureka-comsumer 工程

  • 引入依赖

    		<!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
  • 启动类上添加注解

    @EnableEurekaClient
    
  • application.yml

    server:
      port: 9000
    
    eureka:
      instance:
        hostname: localhost # 主机名
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
    spring:
      application:
        name: eureka-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
    

    在这里插入图片描述


四、 通过Eureka调用

Consumer 模块

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired

    private RestTemplate restTemplate;

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/add/{id}")
    public Goods add(@PathVariable("id") Integer id) {

        //服务发现
        List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");
        if(instances==null||instances.size()<=0){
            return null;
        }
        //通过某个策略拿到一个实例
        ServiceInstance serviceInstance = instances.get(0);
        String host = serviceInstance.getHost();
        int port = serviceInstance.getPort();
        System.out.println(host);
        System.out.println(port);

        String url="http://"+host+":"+port+"/goods/findById/"+id;
        Goods goods = restTemplate.getForObject(url, Goods.class);

        return goods;

    }
}

在这里插入图片描述


五、 Euraka配置详解

Eureka包含四个部分的配置:

  • instance:当前Eureka Instance实例信息配置
  • client:Eureka Client客户端特性配置
  • server:Eureka Server注册中心特性配置
  • dashboard:Eureka Server注册中心仪表盘配置

1、实例信息配置

eureka:
    instance:
        hostname: localhost # 主机名
        prefer-ip-address: # 是否将自己的ip注册到eureka中,默认false 注册 主机名
        ip-address: # 设置当前实例ip
        instance-id: # 修改instance-id显示
        lease-renewal-interval-in-seconds: 30 # 每一次eureka client 向 eureka server发送心跳的时间间隔
        lease-expiration-duration-in-seconds: 90 # 如果90秒内eureka server没有收到eureka client的心跳包,则剔除该服务

Eureka Instance的配置信息全部保存在org.springframework.cloud.netflix.eureka.EurekaInstanceConfigBean配置类里,实际上它是com.netflix.appinfo.EurekaInstanceConfig的实现类,替代了netflix的com.netflix.appinfo.CloudInstanceConfig的默认实现。
Eureka Instance的配置信息全部以eureka.instance.xxx的格式配置。

配置列表:

appname = unknown
应用名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。

appGroupName = null
应用组名

instanceEnabledOnit = false
实例注册到Eureka上是,是否立刻开启通讯。有时候应用在准备好服务之前需要一些预处理。

nonSecurePort = 80
非安全的端口

securePort = 443
安全端口

nonSecurePortEnabled = true
是否开启非安全端口通讯

securePortEnabled = false
是否开启安全端口通讯

leaseRenewalIntervalInSeconds = 30
实例续约间隔时间

leaseExpirationDurationInSeconds = 90
实例超时时间,表示最大leaseExpirationDurationInSeconds秒后没有续约,Server就认为他不可用了,随之就会将其剔除。

virtualHostName = unknown
虚拟主机名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。

instanceId
注册到eureka上的唯一实例ID,不能与相同appname的其他实例重复。

secureVirtualHostName = unknown
安全虚拟主机名,首先获取spring.application.name的值,如果取值为空,则取默认unknown。

metadataMap = new HashMap();
实例元数据,可以供其他实例使用。比如spring-boot-admin在监控时,获取实例的上下文和端口。

dataCenterInfo = new MyDataCenterInfo(DataCenterInfo.Name.MyOwn);
实例部署的数据中心。如AWS、MyOwn。

ipAddress=null
实例的IP地址

statusPageUrlPath = "/actuator/info"
实例状态页相对url

statusPageUrl = null
实例状态页绝对URL

homePageUrlPath = "/"
实例主页相对URL

homePageUrl = null
实例主页绝对URL

healthCheckUrlUrlPath = "/actuator/health"
实例健康检查相对URL

healthCheckUrl = null
实例健康检查绝对URL

secureHealthCheckUrl = null
实例安全的健康检查绝对URL

namespace = "eureka"
配置属性的命名空间(Spring Cloud中被忽略)

hostname = null
主机名,不配置的时候讲根据操作系统的主机名来获取

preferIpAddress = false
是否优先使用IP地址作为主机名的标识

2、客户端特性配置

eureka:
    client:
        service-url:
       		 # eureka服务端地址,将来客户端使用该地址和eureka进行通信
        	defaultZone: 
        register-with-eureka: # 是否将自己的路径 注册到eureka上。
        fetch-registry: # 是否需要从eureka中抓取数据。

Eureka Client客户端特性配置是对作为Eureka客户端的特性配置,包括Eureka注册中心,本身也是一个Eureka Client。
Eureka Client特性配置全部在org.springframework.cloud.netflix.eureka.EurekaClientConfigBean中,实际上它是com.netflix.discovery.EurekaClientConfig的实现类,替代了netxflix的默认实现。
Eureka Client客户端特性配置全部以eureka.client.xxx的格式配置。

配置列表:

enabled=true
是否启用Eureka client。

registryFetchIntervalSeconds=30
定时从Eureka Server拉取服务注册信息的间隔时间

instanceInfoReplicationIntervalSeconds=30
定时将实例信息(如果变化了)复制到Eureka Server的间隔时间。(InstanceInfoReplicator线程)

initialInstanceInfoReplicationIntervalSeconds=40
首次将实例信息复制到Eureka Server的延迟时间。(InstanceInfoReplicator线程)

eurekaServiceUrlPollIntervalSeconds=300
拉取Eureka Server地址的间隔时间(Eureka Server有可能增减)

proxyPort=null
Eureka Server的代理端口

proxyHost=null
Eureka Server的代理主机名

proxyUserName=null
Eureka Server的代理用户名

proxyPassword=null
Eureka Server的代理密码

eurekaServerReadTimeoutSeconds=8
从Eureka Server读取信息的超时时间

eurekaServerConnectTimeoutSeconds=5
连接Eureka Server的超时时间

backupRegistryImpl=null
Eureka Client第一次启动时获取服务注册信息的调用的回溯实现。Eureka Client启动时首次会检查有没有BackupRegistry的实现类,如果有实现类,则优先从这个实现类里获取服务注册信息。

eurekaServerTotalConnections=200
Eureka client连接Eureka Server的链接总数

eurekaServerTotalConnectionsPerHost=50
Eureka client连接单台Eureka Server的链接总数

eurekaServerURLContext=null
当Eureka server的列表在DNS中时,Eureka Server的上下文路径。如http://xxxx/eureka。

eurekaServerPort=null
当Eureka server的列表在DNS中时,Eureka Server的端口。

eurekaServerDNSName=null
当Eureka server的列表在DNS中时,且要通过DNSName获取Eureka Server列表时,DNS名字。

region="us-east-1"
实例所属区域。

eurekaConnectionIdleTimeoutSeconds = 30
Eureka Client和Eureka Server之间的Http连接的空闲超时时间。

heartbeatExecutorThreadPoolSize=2
心跳(续约)执行器线程池大小。

heartbeatExecutorExponentialBackOffBound=10
心跳执行器在续约过程中超时后的再次执行续约的最大延迟倍数。默认最大延迟时间=10 * eureka.instance.leaseRenewalIntervalInSeconds

cacheRefreshExecutorThreadPoolSize=2
cacheRefreshExecutord的线程池大小(获取注册信息)

cacheRefreshExecutorExponentialBackOffBound=10
cacheRefreshExecutord的再次执行的最大延迟倍数。默认最大延迟时间=10 *eureka.client.registryFetchIntervalSeconds

serviceUrl= new HashMap();serviceUrl.put(DEFAULT_ZONE, DEFAULT_URL);
Eureka Server的分区地址。默认添加了一个defualtZone。也就是最常用的配置eureka.client.service-url.defaultZone=xxx

registerWithEureka=true
是否注册到Eureka Server。

preferSameZoneEureka=true
是否使用相同Zone下的Eureka server。

logDeltaDiff=false
是否记录Eureka Server和Eureka Client之间注册信息的差异

disableDelta=false
是否开启增量同步注册信息。

fetchRemoteRegionsRegistry=null
获取注册服务的远程地区,以逗号隔开。

availabilityZones=new HashMap()
可用分区列表。用逗号隔开。

filterOnlyUpInstances = true
是否只拉取UP状态的实例。

fetchRegistry=true
是否拉取注册信息。

shouldUnregisterOnShutdown = true
是否在停止服务的时候向Eureka Server发起Cancel指令。

shouldEnforceRegistrationAtInit = false
是否在初始化过程中注册服务。

3、注册中心端配置

eureka:
    server: #是否开启自我保护机制,默认true
        enable-self-preservation: 
        eviction-interval-timer-in-ms: 120 2月#清理间隔(单位毫秒,默认是60*1000)
	instance:
        lease-renewal-interval-in-seconds: 30 # 每一次eureka client 向 eureka server发送心跳的时间间隔
        lease-expiration-duration-in-seconds: 90 # 如果90秒内eureka server没有收到eureka client的心跳包,则剔除该服务        

Eureka Server注册中心端的配置是对注册中心的特性配置。Eureka Server的配置全部在org.springframework.cloud.netflix.eureka.server.EurekaServerConfigBean里,实际上它是com.netflix.eureka.EurekaServerConfig的实现类,替代了netflix的默认实现。
Eureka Server的配置全部以eureka.server.xxx的格式进行配置。

配置列表:

enableSelfPreservation=true
是否开启自我保护

renewalPercentThreshold = 0.85
自我保护续约百分比阀值因子。如果实际续约数小于续约数阀值,则开启自我保护

renewalThresholdUpdateIntervalMs = 15 * 60 * 1000
续约数阀值更新频率。

peerEurekaNodesUpdateIntervalMs = 10 * 60 * 1000
Eureka Server节点更新频率。

enableReplicatedRequestCompression = false
是否启用复制请求压缩。

waitTimeInMsWhenSyncEmpty=5 * 60 * 1000
当从其他节点同步实例信息为空时等待的时间。

peerNodeConnectTimeoutMs=200
节点间连接的超时时间。

peerNodeReadTimeoutMs=200
节点间读取信息的超时时间。

peerNodeTotalConnections=1000
节点间连接总数。

peerNodeTotalConnectionsPerHost = 500;
单个节点间连接总数。

peerNodeConnectionIdleTimeoutSeconds = 30;
节点间连接空闲超时时间。

retentionTimeInMSInDeltaQueue = 3 * MINUTES;
增量队列的缓存时间。

deltaRetentionTimerIntervalInMs = 30 * 1000;
清理增量队列中过期的频率。

evictionIntervalTimerInMs = 60 * 1000;
剔除任务频率。

responseCacheAutoExpirationInSeconds = 180;
注册列表缓存超时时间(当注册列表没有变化时)

responseCacheUpdateIntervalMs = 30 * 1000;
注册列表缓存更新频率。

useReadOnlyResponseCache = true;
是否开启注册列表的二级缓存。

disableDelta=false。
是否为client提供增量信息。

maxThreadsForStatusReplication = 1;
状态同步的最大线程数。

maxElementsInStatusReplicationPool = 10000;
状态同步队列的最大容量。

syncWhenTimestampDiffers = true;
当时间差异时是否同步。

registrySyncRetries = 0;
注册信息同步重试次数。

registrySyncRetryWaitMs = 30 * 1000;
注册信息同步重试期间的时间间隔。

maxElementsInPeerReplicationPool = 10000;
节点间同步事件的最大容量。

minThreadsForPeerReplication = 5;
节点间同步的最小线程数。

maxThreadsForPeerReplication = 20;
节点间同步的最大线程数。

maxTimeForReplication = 30000;
节点间同步的最大时间,单位为毫秒。

disableDeltaForRemoteRegions = false;
是否启用远程区域增量。

remoteRegionConnectTimeoutMs = 1000;
远程区域连接超时时间。

remoteRegionReadTimeoutMs = 1000;
远程区域读取超时时间。

remoteRegionTotalConnections = 1000;
远程区域最大连接数

remoteRegionTotalConnectionsPerHost = 500;
远程区域单机连接数

remoteRegionConnectionIdleTimeoutSeconds = 30;
远程区域连接空闲超时时间。

remoteRegionRegistryFetchInterval = 30;
远程区域注册信息拉取频率。

remoteRegionFetchThreadPoolSize = 20;
远程区域注册信息线程数。

4、仪表盘配置

eureka:
    dashboard:
        enabled: true # 是否启用eureka web控制台
        path: / # 设置eureka web控制台默认访问路径

注册中心仪表盘的配置主要是控制注册中心的可视化展示。以eureka.dashboard.xxx的格式配置。

  • path="/" : 仪表盘访问路径

  • enabled=true: 是否启用仪表盘


  • 改造 provider

    server:
      port: 8000
    
    
    eureka:
      instance:
        hostname: localhost # 主机名
        prefer-ip-address: true # 将当前实例的ip注册到eureka server 中。默认是false 注册主机名
        ip-address: 127.0.0.1 # 设置当前实例的ip
        instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} # 设置web控制台显示的 实例id
        lease-renewal-interval-in-seconds: 3 # 每隔3 秒发一次心跳包
        lease-expiration-duration-in-seconds: 9 # 如果9秒没有发心跳包,服务器呀,你把我干掉吧~
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
    spring:
      application:
        name: eureka-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
    
  • 改造consumer

    server:
      port: 9000
    
    
    eureka:
      instance:
        hostname: localhost # 主机名
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
    spring:
      application:
        name: eureka-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径
    
  • 改造server

    server:
      port: 8761
    
    # eureka 配置
    # eureka 一共有4部分 配置
    # 1. dashboard:eureka的web控制台配置
    # 2. server:eureka的服务端配置
    # 3. client:eureka的客户端配置
    # 4. instance:eureka的实例配置
    
    
    eureka:
      instance:
        hostname: localhost # 主机名
      client:
        service-url:
          defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
        register-with-eureka: false # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要
        fetch-registry: false # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要
      server:
        enable-self-preservation: false # 关闭自我保护机制
        eviction-interval-timer-in-ms: 3000 # 检查服务的时间间隔
    

六、高可用

在这里插入图片描述
 
(1) 准备两个Eureka Server

(2) 分别进行配置,相互注册

(3) Eureka Client 分别注册到这两个 Eureka Server中


创建eureka-server1

server:
  port: 8761


eureka:
  instance:
    hostname: eureka-server1 # 主机名
  client:
    service-url:
      defaultZone: http://eureka-server2:8762/eureka
    register-with-eureka: true # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要
    fetch-registry: true # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要


spring:
  application:
    name: eureka-server-ha

创建eureka-server2

server:
  port: 8762


eureka:
  instance:
    hostname: eureka-server2 # 主机名
  client:
    service-url:
      defaultZone: http://eureka-server1:8761/eureka

    register-with-eureka: true # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要
    fetch-registry: true # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要
spring:
  application:
    name: eureka-server-ha

修改:C:\Windows\System32\drivers\etc\hosts

在hosts文件中添加:127.0.0.1 eureka-server1 127.0.0.1 eureka-server2

在这里插入图片描述
 

测试:
启动 eureka-servere1eureka-server2
在这里插入图片描述
 
在这里插入图片描述
 


eureka-provider

server:
  port: 8000


eureka:
  instance:
    hostname: localhost # 主机名
    prefer-ip-address: true # 将当前实例的ip注册到eureka server 中。默认是false 注册主机名
    ip-address: 127.0.0.1 # 设置当前实例的ip
    instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port} # 设置web控制台显示的 实例id
    lease-renewal-interval-in-seconds: 3 # 每隔3 秒发一次心跳包
    lease-expiration-duration-in-seconds: 9 # 如果9秒没有发心跳包,服务器呀,你把我干掉吧~
  client:
    service-url:
      defaultZone: http://eureka-server1:8761/eureka,http://eureka-server2:8762/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
  application:
    name: eureka-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径

eureka-consumer

server:
  port: 9000


eureka:
  instance:
    hostname: localhost # 主机名
  client:
    service-url:
      defaultZone:  http://eureka-server1:8761/eureka,http://eureka-server2:8762/eureka  # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
  application:
    name: eureka-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径

测试: 访问 http://localhost:9000/order/add/2
在这里插入图片描述

高可用测试:停掉一个eureka,依然可以访问consumer。

eureka不更新了,所以淘汰了。


第六章 Zookeeper服务注册与发现

在这里插入图片描述

有的老项目以前是dubbo,升级到微服务,使用zookeeper做注册中心。

zookeeper是一个分布式协调工具,可以实现注册中心功能。

实质: 注册中心换成zk。

1. 安装zookeeper

  • 下载:https://zookeeper.apache.org/
    在这里插入图片描述

  • zoo.cfg

    # The number of milliseconds of each tick
    tickTime=2000
    # The number of ticks that the initial 
    # synchronization phase can take
    initLimit=10
    # The number of ticks that can pass between 
    # sending a request and getting an acknowledgement
    syncLimit=5
    # the directory where the snapshot is stored.
    # do not use /tmp for storage, /tmp here is just 
    # example sakes.
    dataDir=D:/zookeeper-3.4.13/data
    # the port at which the clients will connect
    clientPort=2181
    # the maximum number of client connections.
    # increase this if you need to handle more clients
    #maxClientCnxns=60
    #
    # Be sure to read the maintenance section of the 
    # administrator guide before turning on autopurge.
    #
    # http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
    #
    # The number of snapshots to retain in dataDir
    #autopurge.snapRetainCount=3
    # Purge task interval in hours
    # Set to "0" to disable auto purge feature
    #autopurge.purgeInterval=1
    
  • 启动 bin目录下

    zkServer.cmd
    

    在这里插入图片描述
     

2. zookeeper-provider

  • 引入依赖

    <dependencies>
        <!--springcloud 整合 zookeeper 组件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <!--zk发现-->
            <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.9</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
    </dependencies>
    
    
  • application.yml

    server:
      port: 8004
    
    spring:
      application:
        name: zookeeper-provider
      cloud:
        zookeeper:
          connect-string: 127.0.0.1:2181 # zk地址
    
  • 启动类

    @SpringBootApplication
    @EnableDiscoveryClient //开启发现客户端
    public class ProviderApplication {
        public static void main(String[] args) {
            SpringApplication.run(ProviderApplication.class,args);
        }
    }
    
  • 复制eureka-provider模块中业务逻辑的代码
    在这里插入图片描述
     

3. zookeeper-consumer

  • 引入依赖

    <dependencies>
        <!--springcloud 整合 zookeeper 组件-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <!--zk发现-->
            <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.9</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
    </dependencies>
    
    
  • application.yml

    server:
      port: 8005
    
    spring:
      application:
        name: zookeeper-consumer
      cloud:
        zookeeper:
          connect-string: 127.0.0.1:2181 # zk地址
    
  • 启动类

    @SpringBootApplication
    @EnableDiscoveryClient //开启发现客户端
    public class ConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class,args);
        }
    }
    
  • 复制eureka-consumer模块中业务逻辑的代码
    在这里插入图片描述

  • 修改controller层

    List<ServiceInstance> instances = discoveryClient.getInstances("zookeeper-provider");
    
  • 测试
    访问:http://localhost:8005/order/add/2
    在这里插入图片描述


第七章 Consul服务注册与发现

一、Consul是什么

  • Consul 是由 HashiCorp 基于 GoLanguage 语言开发的,支持多数据中心,分布式高可用的服务发布和注册服务软件。
  • 用于实现分布式系统的服务发现与配置。
  • 使用起来也较 为简单。具有天然可移植性(支持Linux、windows和Mac OS X);安装包仅包含一个可执行文件,方便部署 。
  • Consul官网:https://www.consul.io/
  • Consul中文文档:https://www.springcloud.cc/spring-cloud-consul.html

二、Consul怎么用

1. 安装Consul

启动:在安装包的目录下打开命令窗口输入:consul.exe agent -dev
在这里插入图片描述

在这里插入图片描述
 

2. 搭建 consul-provider

  • 引入依赖

    	<dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
        </dependencies>
    
  • application.yml

    server:
      port: 8006
    
    spring:
      application:
        name: consul-provider
      cloud:
        consul:
          host: 127.0.0.1
          port: 8500
          discovery:
            service-name: ${spring.application.name}
    
  • 启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class ProviderApplication {
        public static void main(String[] args) {
            SpringApplication.run(ProviderApplication.class,args);
        }
    }
    
  • 复制相关的业务逻辑代码
    在这里插入图片描述

  • 启动
    在这里插入图片描述


3. 搭建 consul-consumer

  • 引入依赖

    	<dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
        </dependencies>
    
  • application.yml

    server:
      port: 8007
    
    spring:
      application:
        name: consul-consumer
      cloud:
        consul:
          host: 127.0.0.1
          port: 8500
          discovery:
            service-name: ${spring.application.name}
    
  • 启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class ConsumerApplication {
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class,args);
        }
    }
    
  • 复制相关的业务逻辑代码
    在这里插入图片描述

  • 启动
    在这里插入图片描述

最终测试调用成功即可:http://localhost:8007/order/add/9
在这里插入图片描述


三、 三个注册中心的异同

组件语言cap健康检查暴露接口cloud集成
eurekajavaap支持http已经集成
zookeeperjavacp支持tcp已经集成
consulgocp支持http已经集成

cap:

  • consustency 强一致性

  • avalibility 可用性

  • partition tolerance 分区容忍性


第八章 Ribbon负载均衡服务调用

一、Ribbon是什么

Netflix公司推出的http和TCP的客户端负载均衡工具。

ribbon:

  • 简化远程调用代码

  • 内置很多负载均衡算法

1. 服务端负载均衡

负载均衡算法在服务端,服务端维护服务列表。
在这里插入图片描述

2. 客户端负载均衡

  • 负载均衡算法在客户端

  • 客户端维护服务列表
    在这里插入图片描述


二、如何使用

  1. 引入依赖

      <!--Ribbon的依赖-->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
     </dependency>
    

    新版的eureka依赖里面集成了Ribbon依赖,所以可以不引用。
    在这里插入图片描述
     

  2. 声明restTemplate时@LoadBalanced
    在这里插入图片描述
     

  3. restTemplate请求远程服务时,ip端口替换为服务名

    String url="http://EUREKA-PROVIDER/goods/findById/"+id;
    Goods goods = restTemplate.getForObject(url, Goods.class);
    

测试:

  1. 启动2个provider

    controller
    在这里插入图片描述

    idea设置 能启动两份 provider:
    在这里插入图片描述
    在这里插入图片描述

  2. 多次访问consumer
    在这里插入图片描述
    在这里插入图片描述

多次刷新,发现:ribbon客户端,默认使用轮询算法,经行负载均衡调用。


三、ribbon 负载均衡策略

内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。注意:可以通过修改配置loadbalancer.<clientName>.connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上线,可以由客户端的<clientName>.<clientName>.ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。
BestAvailableRule忽略哪些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
Retry重试机制的选择逻辑

四、 设置ribbon 负载均衡策略

1. 代码

consumer工程

  • MyRule 返回想要的规则即可

    @Configuration
    public class MyRule {
        @Bean
        public IRule rule(){
            return new RandomRule();
        }
    }
    
  • 启动类

    @RibbonClient(name ="EUREKA-PROVIDER",configuration = MyRule.class)
    
  • 测试

总结:

  • irule的具体实现类,看到他带的几个策略的写法。

  • 仿照策略的写法,自己写策略。

  • 调用不同的其他微服务时,可以采用不同的策略。

2. 配置

consumer工程

  • application.yml
    EUREKA-PROVIDER: #远程服务名
      ribbon:
        NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #策略
    

作用:方便运维修改,重启。随时切换策略。


第九章、OpenFeign服务接口调用

一、概述

二、快速入门

  • 在消费端引入 open-feign 依赖

     	   <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
    
  • 编写Feign调用接口

    @FeignClient("eureka-provider")
    public interface GoodsFeign {
        @GetMapping("/goods/findById/{id}")
        public Goods findById(@PathVariable("id") Integer id);
    }
    
  • 在启动类 添加 @EnableFeignClients 注解,开启Feign功能

    @EnableFeignClients
    
  • 测试调用

    @RestController
    @RequestMapping("/order")
    public class OrderController {
        
        @Autowired
        GoodsFeign goodsFeign;
    
        @GetMapping("/add/{id}")
        public Goods add(@PathVariable("id") Integer id) {
            
            //feign调用
            Goods goods = goodsFeign.findById(id);
            return goods;
        }
    }
    
  • 测试


三、其他设置

1. 超时设置

  • Feign 底层依赖于 Ribbon 实现负载均衡和远程调用。

  • Ribbon默认1秒超时。

  • 超时配置: application.yml中

    # 设置Ribbon的超时时间
    ribbon:
      ConnectTimeout: 1000 # 连接超时时间 默认1s
      ReadTimeout: 3000 # 逻辑处理的超时时间 默认1s
    
  • 测试

  1. 连接超时,provider都停掉
    在这里插入图片描述
  2. 逻辑处理的超时时间
    provider
    @GetMapping("findById/{id}")
        public Goods findById(@PathVariable("id") int id) {
            Goods goods = goodsService.findById(id);
            goods.setTitle(goods.getTitle()+"|端口号:"+port);
    
            //模拟业务逻辑比较繁忙
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            return goods;
        }
    

在这里插入图片描述


2. 日志记录

  • Feign 只能记录 debug 级别的日志信息

  • 设置日志级别

    # 设置当前的日志级别 debug,feign只支持记录debug级别的日志
    logging:
      level:
        com.itcoder: debug
    
  • 定义Feign日志级别Bean

    @Configuration
    public class FeignLogConfig {
        /*
            1.NONE,不记录
            2.BASIC,记录基本的请求行,响应状态码数据
            3.HEADERS,记录基本的请求行,响应状态码数据,记录响应头信息
            4.FULL;记录完成的请求 响应数据
         */
        @Bean
        public Logger.Level level(){
            return Logger.Level.FULL;
        }
    }
    
  • 启用该Bean
    GoodsFeign

    @FeignClient(value = "eureka-provider",configuration = FeignLogConfig.class)
    

在这里插入图片描述
 


第十章 Hystrix断路器

一、概述

重点: 能让服务的调用方,够快的知道被调方挂了!不至于说让用户在等待。

Hystix 是 Netflix 开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败(雪崩)

雪崩: 一个服务失败,导致整条链路的服务都失败的情形。

Hystix 主要功能

  • 隔离
  • 降级
  • 熔断
  • 限流
    在这里插入图片描述
     

隔离

  1. 线程池隔离
    没有hystrix,a重试100次,才知道c挂了!
    在这里插入图片描述

    使用了hystrix,更细分线程池,只需要重试40次,让a更快的知道c挂了
    在这里插入图片描述
     

  2. 信号量隔离
    没有hystrix,a一个带着认证信息的线程,重试100次,才知道c挂了!
    在这里插入图片描述
    使用了hystrix,更细分线程池,一个带着认证信息的线程,只需要重试40次,让a更快的知道c挂了
    在这里插入图片描述


降级
服务提供方降级(异常,超时)
在这里插入图片描述
 
消费方降级
在这里插入图片描述
熔断
限流
是有限流,但是,项目一般不用。nginx或者网关限流。


二、服务降级

服务提供方

  • 在服务提供方,引入 hystrix 依赖

    	<!-- hystrix -->
             <dependency>
                 <groupId>org.springframework.cloud</groupId>
                 <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
             </dependency>
    
  • 方法

    /** 定义降级方法   返回特殊对象
         *  1方法的返回值要和原方法一致
         *  2方法参数和原方法一样
         */
        public Goods findById_fallback(Integer id){
            Goods goods=new Goods();
            goods.setGoodId(-1);
            goods.setTitle("provider提供方降级!");
            goods.setPrice(-9.9);
            goods.setStock(-10);
    
            return goods;
        }
    
  • 使用 @HystrixCommand 注解配置降级方法

    @GetMapping("/findById/{id}")
        @HystrixCommand(fallbackMethod = "findById_fallback",commandProperties = {
                //设置Hystrix的超时时间,默认1s
                @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
        })
        public Goods findById(@PathVariable("id") Integer id){
            Goods goods = goodsService.findById(id);
            goods.setTitle(goods.getTitle()+"|端口号:"+port);
    
            //模拟出异常
    //        int a=1/0;
    
            //模拟业务逻辑比较繁忙
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return goods;
        }
    
  • 在启动类上开启Hystrix功能:

    @EnableCircuitBreaker
    
  • 测试:http://localhost:9000/order/add/10

  1. 出错,服务方降级了
    2.3000超时,服务方降级了
  2. 3000超时,服务方降级了
    在这里插入图片描述
     

服务消费方

  • feign 组件已经集成了 hystrix 组件

  • 定义feign 调用接口实现类,复写方法,即 降级方法

    @Component
    public class GoodsFeignCallback implements GoodsFeign{
        @Override
        public Goods findById(Integer id) {
            Goods goods=new Goods();
            goods.setGoodId(-2);
            goods.setTitle("调用方降级了!");
            goods.setPrice(-5.5);
            goods.setStock(-5);
            return goods;
        }
    }
    
  • 在 @FeignClient 注解中使用 fallback 属性设置降级处理类

    @FeignClient(value = "EUREKA-PROVIDER",configuration = FeignLogConfig.class,fallback = GoodsFeignCallback.class)
    public interface GoodsFeign {
        @GetMapping("/goods/findById/{id}")
        public Goods findById(@PathVariable("id") Integer id);
    }
    
  • 配置开启

    # 开启feign对hystrix的支持
    feign:
      hystrix:
        enabled: true
    
  • 测试:停掉provider
    在这里插入图片描述


三、熔断

在这里插入图片描述
测试:
provider

@RestController
@RequestMapping("/goods")
public class GoodsController {
    @Autowired
    GoodsService goodsService;
    @Value("${server.port}")
    int port;

    @GetMapping("/findById/{id}")
    @HystrixCommand(fallbackMethod = "findById_fallback",commandProperties = {
            //设置Hystrix的超时时间,默认1s
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public Goods findById(@PathVariable("id") Integer id){
        Goods goods = goodsService.findById(id);
        goods.setTitle(goods.getTitle()+"|端口号:"+port);

        if(id==1){
            //模拟出异常
            int a=1/0;
        }

        //模拟出异常
//        int a=1/0;

        //模拟业务逻辑比较繁忙
//        try {
//            Thread.sleep(5000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        return goods;
    }

    /** 定义降级方法   返回特殊对象
     *  1方法的返回值要和原方法一致
     *  2方法参数和原方法一样
     */
    public Goods findById_fallback(Integer id){
        Goods goods=new Goods();
        goods.setGoodId(-1);
        goods.setTitle("provider提供方降级!");
        goods.setPrice(-9.9);
        goods.setStock(-10);

        return goods;
    }
}

访问两个接口

  1. http://localhost:9000/order/add/10

在这里插入图片描述

  1. 多次访问 http://localhost:9000/order/add/1
    在这里插入图片描述
    由于多次访问失败,会出现降级,打开断路器,拒绝了其他所有的请求。

  2. 导致10也不能访问了
    在这里插入图片描述

  3. 再过一会儿,半开状态
    在这里插入图片描述

Hystrix 熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值(5秒失败20次),会打开断路器,拒绝所有请求,直到服务恢复正常为止。

circuitBreaker.sleepWindowInMilliseconds:监控时间
circuitBreaker.requestVolumeThreshold:失败次数
circuitBreaker.errorThresholdPercentage:失败率

提供者controller中:

 @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
            //设置Hystrix的超时时间,默认1s
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
            //监控时间 默认5000 毫秒
            @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"),
            //失败次数。默认20次
            @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"),
            //失败率 默认50%
            @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50")

    })

四、熔断监控

在这里插入图片描述
Hystrix 提供了 Hystrix-dashboard 功能,用于实时监控微服务运行状态。

但是Hystrix-dashboard只能监控一个微服务。

Netflix 还提供了 Turbine ,进行聚合监控。
在这里插入图片描述
 

Turbine聚合监控

1. 搭建监控模板

  • 创建监控模块
    创建hystrix-monitor模块,使用Turbine聚合监控多个Hystrix dashboard功能。

  • 引入Turbine聚合监控起步依赖

    <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
    
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
  • 修改application.yml

    spring:
      application:
        name: hystrix-monitor
    server:
      port: 8769
    turbine:
      combine-host-port: true
      # 配置需要监控的服务名称列表
      app-config: EUREKA-PROVIDER,EUREKA-CONSUMER
      cluster-name-expression: "'default'"
      aggregator:
        cluster-config: default
      #instanceUrlSuffix: /actuator/hystrix.stream
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
    hystrix:
      dashboard:
        proxy-stream-allow-list: "*"
    
    
  • 创建启动类

    @SpringBootApplication
    @EnableEurekaClient
    @EnableTurbine //开启Turbine 很聚合监控功能
    @EnableHystrixDashboard //开启Hystrix仪表盘监控功能
    public class HystrixMonitorApp {
        public static void main(String[] args) {
            SpringApplication.run(HystrixMonitorApp.class,args);
        }
    }
    

2. 修改被监控模块

需要分别修改 hystrix-provider 和 hystrix-consumer 模块:

  • 导入依赖

    	<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</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-starter-netflix-hystrix-dashboard</artifactId>
            </dependency>
    
  • 配置Bean
    此处为了方便,将其配置在启动类中。

    @Bean
        public ServletRegistrationBean getServlet() {
            HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
            ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
            registrationBean.setLoadOnStartup(1);
            registrationBean.addUrlMappings("/actuator/hystrix.stream");
            registrationBean.setName("HystrixMetricsStreamServlet");
            return registrationBean;
        }
    
  • 启动类上添加注解

    @EnableHystrixDashboard // 开启Hystrix仪表盘监控功能
    

3. 测试

启动服务:

  • eureka-server

  • hystrix-provider

  • hystrix-consumer

  • hystrix-monitor

访问:
在浏览器访问http://localhost:8769/hystrix/ 进入Hystrix Dashboard界面
在这里插入图片描述

  • 实心圆:它有颜色和大小之分,分别代表实例的监控程度和流量大小。如上图所示,它的健康度从绿色、黄色、橙色、红色递减。通过该实心圆的展示,我们就可以在大量的实例中快速的发现故障实例和高压力实例。
  • 曲线:用来记录 2 分钟内流量的相对变化,我们可以通过它来观察到流量的上升和下降趋势。

第十一章、zuul路由网关

zuul核心人员走了两个,zuul2的研发过久,spring公司等不及,自己研发的Gateway网关。
https://github.com/Netflix/zuul/wiki


第十二章 Gateway新一代网关

功能: 路由+过滤。

一、 概述

官方文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/

不使用网关存在的问题:

  • 客户端需要记录不同微服务地址,增加客户端的复杂性
  • 每个后台微服务都需要认证
  • http 发请求,涉及到跨域
  • 后台新增微服务,不能动态知道地址

在这里插入图片描述

 
使用了网关的话:

  • 网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。

  • 在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。

  • 网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、缓存、负载均衡、流量管控、路由转发等。

  • 在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul/zuul2 、Spring Cl。
    在这里插入图片描述


二、快速入门

  • 搭建网关模块 api-gateway-server

  • 引入依赖

    <dependencies>
            <!--引入gateway 网关-->
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
    
            <!-- eureka-client -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            </dependency>
        </dependencies>
    
  • 创建启动类

    @SpringBootApplication
    @EnableEurekaClient
    public class ApiGatewayApp {
    
        public static void main(String[] args) {
            SpringApplication.run(ApiGatewayApp.class,args);
        }
    
    }
    
  • 编写配置文件

    server:
      port: 80
    
    spring:
      application:
        name: api-gateway-server
    
      cloud:
        # 网关配置
        gateway:
          # 路由配置:转发规则
          routes: #集合。
            # id: 唯一标识。默认是一个UUID
            # uri: 转发路径
            # predicates: 条件,用于请求网关路径的匹配规则
            # filters:配置局部过滤器的
    
            - id: eureka-provider
              # 静态路由
              # uri: http://localhost:8001/
              # 动态路由
              uri: lb://GATEWAY-PROVIDER
              predicates:
                - Path=/goods/**
              filters:
                - AddRequestParameter=username,zhangsan
    
            - id: eureka-consumer
              # uri: http://localhost:9000
              uri: lb://GATEWAY-CONSUMER
              predicates:
                - Path=/order/**
              # 微服务名称配置
          discovery:
            locator:
              enabled: true # 设置为true 请求路径前可以添加微服务名称
              lower-case-service-id: true # 允许为小写
    
    
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka
    
  • 测试
    在这里插入图片描述
    在这里插入图片描述


三、 静态路由

uri: http://localhost:8000/

四、动态路由

在这里插入图片描述

1. 引入eureka-client配置

  • pom

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

    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka
    

2. 修改uri属性:uri: lb://服务名称

uri: lb://eureka-provider

3. 测试

访问:http://localhost/goods/findById/2
在这里插入图片描述


五、微服务名称配置

application.yml

spring:
  cloud:
    # 网关配置
    gateway:   
    # 微服务名称配置
      discovery:
        locator:
          enabled: true # 设置为true 请求路径前可以添加微服务名称
          lower-case-service-id: true # 允许为小写

测试:http://localhost/eureka-provider/goods/findById/2
在这里插入图片描述


六、过滤器

(1)两个维度:

  • 内置过滤器 自定义过滤器

  • 局部过滤器 全局过滤器

(2)过滤器种类:

  • 内置局部过滤器

  • 内置全局过滤器

  • 自定义局部过滤器

  • 自定义全局过滤器
    在这里插入图片描述

  • Gateway 支持过滤器功能,对请求或响应进行拦截,完成一些通用操作。

  • Gateway 提供两种过滤器方式:“pre”和“post”

    pre 过滤器,在转发之前执行,可以做参数校验、权限校验、流量监控、日志输出、协议转换等。
    post 过滤器,在响应之前执行,可以做响应内容、响应头的修改,日志的输出,流量监控等。
    
  • Gateway 还提供了两种类型过滤器

    GatewayFilter:局部过滤器,针对单个路由
    GlobalFilter :全局过滤器,针对所有路由
    

内置过滤器 局部过滤器:

- id: gateway-provider
     #uri: http://localhost:8001/
     uri: lb://GATEWAY-PROVIDER
     predicates:
     - Path=/goods/**
        filters:
            - AddResponseHeader=foo, bar

在这里插入图片描述

内置过滤器 全局过滤器: route同级

  default-filters:
        - AddResponseHeader=yld,itlils

在这里插入图片描述
在这里插入图片描述
官方文档:
https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.1.0.RELEASE/single/spring-cloud-gateway.html#_gatewayfilter_factories


自定义过滤器
使用很少,可以不掌握自定义过滤器的写法。


创作不易,如果有帮助到你,请给文章点个赞和收藏,让更多的人看到!!!
关注博主不迷路,内容持续更新中。

  • 44
    点赞
  • 119
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Java技术一点通

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值