0


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.ymlserver: port: 8000
  • 创建启动类@SpringBootApplicationpublic 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层@Servicepublic class GoodsService { @Autowired private GoodsDao goodsDao; public Goods findById(int id) { Goods goods = goodsDao.findById(id); return goods; }}
  • dao层@Repositorypublic class GoodsDao { public Goods findById(int id) { return new Goods(id, "手机", 2000, 1000); }}
  • 测试 访问:http://localhost:8000/goods/findById/1![在这里插入图片描述](https://img-blog.csdnimg.cn/2e1518bbb44a45b9962e30a95c461cf3.png)

3. 消费者 eureka-consumer

  • 创建 eureka-consumer子模块在这里插入图片描述
  • 引入依赖 <dependencies> <!--spring boot web--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
  • application.ymlserver: port: 9000
  • 创建启动类@SpringBootApplicationpublic 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![在这里插入图片描述](https://img-blog.csdnimg.cn/84c6176675da4036aba23c287f025403.png)

二、使用 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-provider

eureka-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@EnableEurekaServerpublic class EurekaApplication { public static void main(String[] args) { SpringApplication.run(EurekaApplication.class,args); }}
  • application.ymlserver: 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/![在这里插入图片描述](https://img-blog.csdnimg.cn/6483b04ead19473286d82ece0a3b6634.png)

三、 改造 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.ymlserver: port: 8001eureka: 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.ymlserver: port: 9000eureka: 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: 是否启用仪表盘

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

eureka-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/![在这里插入图片描述](https://img-blog.csdnimg.cn/1c0b4fcf66be4c7da86d4c274fe98a0b.png)
  • zoo.cfg# The number of milliseconds of each ticktickTime=2000# The number of ticks that the initial # synchronization phase can takeinitLimit=10# The number of ticks that can pass between # sending a request and getting an acknowledgementsyncLimit=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 connectclientPort=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.ymlserver: port: 8004spring: 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.ymlserver: port: 8005spring: 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![在这里插入图片描述](https://img-blog.csdnimg.cn/326b59669fc5498d802f47fd13d60f86.png)

第七章 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.ymlserver: port: 8006spring: application: name: consul-provider cloud: consul: host: 127.0.0.1 port: 8500 discovery: service-name: ${spring.application.name}
  • 启动类@SpringBootApplication@EnableDiscoveryClientpublic 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.ymlserver: port: 8007spring: application: name: consul-consumer cloud: consul: host: 127.0.0.1 port: 8500 discovery: service-name: ${spring.application.name}
  • 启动类@SpringBootApplication@EnableDiscoveryClientpublic 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个providercontroller在这里插入图片描述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 返回想要的规则即可@Configurationpublic class MyRule { @Bean public IRule rule(){ return new RandomRule(); }}
  • 启动类@RibbonClient(name ="EUREKA-PROVIDER",configuration = MyRule.class)
  • 测试

总结:

  • irule的具体实现类,看到他带的几个策略的写法。
  • 仿照策略的写法,自己写策略。
  • 调用不同的其他微服务时,可以采用不同的策略。

2. 配置

consumer工程

  • application.ymlEUREKA-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@Configurationpublic 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 调用接口实现类,复写方法,即 降级方法@Componentpublic 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![在这里插入图片描述](https://img-blog.csdnimg.cn/38c95e80542d45d7836f8c576193f9ad.png) 由于多次访问失败,会出现降级,打开断路器,拒绝了其他所有的请求。
  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.ymlspring: application: name: hystrix-monitorserver: port: 8769turbine: combine-host-port: true # 配置需要监控的服务名称列表 app-config: EUREKA-PROVIDER,EUREKA-CONSUMER cluster-name-expression: "'default'" aggregator: cluster-config: default #instanceUrlSuffix: /actuator/hystrix.streameureka: 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@EnableEurekaClientpublic class ApiGatewayApp { public static void main(String[] args) { SpringApplication.run(ApiGatewayApp.class,args); }}
  • 编写配置文件server: port: 80spring: 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>
  • ymleureka: 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


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


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


本文转载自: https://blog.csdn.net/m0_52691962/article/details/128236093
版权归原作者 Java技术一点通 所有, 如有侵权,请联系我们删除。

“SpringCloud 学习笔记”的评论:

还没有评论