2022年8月

统一配置中心:config


Config组件简介

spring cloud config 为微服务架构中的微服务提供集中化的外部支持,配置服务器为各个不同微服务应用的所有环节提供了一个中心化的外部配置

config(配置)又称为 统一配置中心顾名思义,就是将配置统一管理,配置统一管理的好处是在日后大规模集群部署服务应用时相同的服务配置一致,日后再修改配置只需要统一修改全部同步,不需要一个一个服务手动维护。

spring cloud config 分为服务端客户端两部分。

服务端也称为 分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密,解密信息等访问接口。

客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理。并且可用通过git客户端工具来方便的管理和访问配置内容。

imge

spring cloud config 分布式配置中心能干嘛?

  • 集中式管理配置文件

  • 不同环境,不同配置,动态化的配置更新,分环境部署,比如 /dev /test /prod /beta /release

  • 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息

  • 当配置发生变动时,服务不需要重启,即可感知到配置的变化,并应用新的配置

  • 将配置信息以REST接口的形式暴露

环境搭建

由于spring cloud config 默认使用git来存储配置文件 (也有其他方式,比如自持SVN 和本地文件),但是最推荐的还是git ,而且使用的是 http / https 访问的形式。

1、在码云上新建仓库

image

2、选择HTTPS连接,点击复制

image

3、新建一个config-server模块springcloud-config-server-3344

image

4、添加相关依赖

<dependencies>
    <!--config server统一配置中心-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency></dependencies>

5、编写application.yaml配置文件

server:
  port: 3344spring:
  application:
    name: springcloud-config-server
  # 连接码云远程仓库
  cloud:
    config:
      server:
        git:
          # 注意是https的而不是ssh
          uri: https://gitee.com/luoxiao1104/springcloud-config.git
          # 通过 config-server可以连接到git,访问其中的资源以及配置~
          default-label: master

6、编写主启动类

package com.study.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.config.server.EnableConfigServer;@SpringBootApplication@EnableConfigServerpublic class ConfigServerApplication_3344 {    public static void main(String[] args) {
        SpringApplication.run(ConfigServerApplication_3344.class,args);
    }
}

7、启动主启动类测试是否成功

image

Config客户端开发-远程连接

config client :微服务

1、新建一个config客户端模块springcloud-config-client-3355

image

2、导入相关依赖

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

3、编写application.yaml配置文件

server:
  port: 3355spring:
  application:
    name: springcloud-config-client#Eureka配置,服务注册到哪里eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-cofig-client-3355  #修改Eureka默认描述信息#自定义一个属性name: zhangsan

4、编写启动类

package com.study.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplication@EnableEurekaClientpublic class ConfigClientApplication_3355 {    public static void main(String[] args) {
        SpringApplication.run(ConfigClientApplication_3355.class,args);
    }
}

5、编写conroller测试

package com.study.springcloud.controller;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Value;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class DemoController {    private static final Logger log = LoggerFactory.getLogger(DemoController.class);    @Value("${name}")
    private String name;    @RequestMapping("/demo")
    public String demo(){
        log.info("demo ok!!!");        return "demo ok,name:"+name;
    }
}

访问 http://localhost:3355/demo
image

在项目中,配置里面的属性(如name属性)可能会根据环境(开发环境,测试环境)不同,值也是不一样的。所以我们在springboot中可以配置多套环境

1、新建开发环境application-dev.yaml

name: zhangsan-dev

2、新建测试环境application-test.yaml

name: lisi-test

3、在修改主配置文件application.yaml
image
4、重新访问 http://localhost:3355/demo
image

把配置文件上传到远端仓库

6、在Gitee上新建文件

image
application.yaml配置文件
image
application-dev.yaml配置文件
image
application-test.yaml配置文件
image
3个文件
image

7、删除项目中的所有yaml配置文件

8、启动config服务springcloud-config-client-3344

9、访问localhost:3344/configclient-dev.yaml 获取配置环境,缓存到本地

image
查看控制台输出缓存的地址
image

10、在config客户端=springcloud-config-client-3355创建bootstrap.yaml配置文件

#config server地址spring:
  cloud:
    config:
      discovery:
        #根据集群注册中心服务器id获取config sever,不要写死,建议在集群获取
        service-id: SPRINGCLOUD-CONFIG-SERVER
        #开启当前configclient 根据服务id去注册中心获取
        enabled: true
        #获取配置文件 1、分支 2、文件名 3、环境
      label: master
      name: configclient
      profile: dev#配置注册中心#Eureka配置,服务注册到哪里eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: springcloud-cofig-client-3355  #修改Eureka默认描述信息

11、启动测试

1、启动eureka集群springcloud-eureka-7001
2、启动config服务端springcloud-config-server-3344
3、启动config客户端springcloud-config-client-3355
image
4、更改bootstrap.yaml配置,重启3355
image
image

注意

config客户端配置如果使用application.yaml命名,会访问远程连接 http://localhost:8888 ,
application.yaml命名是用于已开发完成的项目

Config手动配置刷新

当远程git仓库中配置发生变化时,不需要重启微服务就可以直接读取远端修改之后的配置信息,这种就叫做手动配置刷新

1、在controller中添加@RefreshScope注解

image

2、在bootstrap.yaml配置文件中添加 端点暴露,重启。

image

3、修改远程配置文件

image

4、打开控制台输入curl -X POST http://localhost:3355/actuator/refresh

image
image

配置完之后以后每次在远端修改配置文件只需要走第4步就可以了


路由网关组件:Gateway


Gateway组件简介

Gateway提供了一个在springmvc之上构建API网关的库。springcloudgateway旨在提供一种简单而有效的方法来路由到api,并为api提供横切关注点,比如:安全性、监控/度量和弹性。

1.特性

  • 基于springboot2.x 和 spring webFlux 和 Reactor 构建 响应式异步非阻塞IO模型

  • 动态路由

  • 请求过滤

网关 gateway = 断言predicate + 过滤(后置filler)

  • 断言:当请求到达网关时,网关前置处理

  • 过滤:当请求满足断言的所有条件之后,会向后端服务转发,在向后端服务转发之前会经过一些过滤

Gateway组件使用

1、新建一个子模块springcloud-Gateway-7979

image

2、导入相关依赖

 <dependencies>
        <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-actuator</artifactId>
        </dependency>
        <!--引入Gateway网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
    </dependencies>

3、编写主启动类

package com.study.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublic class GatewayApplication_7979 {    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication_7979.class,args);
    }
}

4、编写application.yaml配置文件

server:
  port: 7979spring:
  application:
    name: springcloud-Gateway-7979
  #Gateway配置
  cloud:
    gateway:
      routes:
        - id: dept8001                # 指定路由唯一标识
          uri: http://localhost:8001/ # 指定路由服务的地址
          predicates:
            # 指定路由规则,及访问当前端口localhost:7979/dept/get/的时候会转发到localhost:8001/dept/get/下所有路径
            - Path=/dept/get/**

        - id: dept8002                # 指定路由唯一标识
          uri: http://localhost:8002/ # 指定路由服务的地址
          predicates:
            # 指定路由规则,及访问当前端口localhost:7979/dept/list的时候会转发到localhost:8002/dept/list
            - Path=/dept/listeureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: Gateway7979.com
    prefer-ip-address: true

5、启动测试

1、启动eureka注册中心集群springcloud-eureka-7001
2、启动服务提供者springcloud-provider-dept-8001springcloud-provider-dept-8002
3、启动Gateway路由网关springcloud-Gateway-7979
image

image

配置路由服务负载均衡

1、编写application.yaml

image

路由predicate(断言,验证)

网关 gateway = 断言predicate + 过滤(后置filler)

  • 断言:当请求到达网关时,网关前置处理

  • 过滤:当请求满足断言的所有条件之后,会向后端服务转发,在向后端服务转发之前会经过一些过滤

image

路由Filter以及自定义filter

一、使用内置的Filter

image

二、自定义全局Filter

自定义全局filter:所有请求都要经过全局filter之后再转发到后端服务

新建一个全局配置类实现GlobalFilter, Ordered接口

package com.study.springcloud.filters;import org.springframework.cloud.gateway.filter.GatewayFilterChain;import org.springframework.cloud.gateway.filter.GlobalFilter;import org.springframework.context.annotation.Configuration;import org.springframework.core.Ordered;import org.springframework.http.server.reactive.ServerHttpRequest;import org.springframework.http.server.reactive.ServerHttpResponse;import org.springframework.web.server.ServerWebExchange;import reactor.core.publisher.Mono;/**
 * 自定义网关全局filter
 */@Configurationpublic class CustomerGlobalFilter  implements GlobalFilter, Ordered {    //类似javaweb doFilter
    //exchange : 交换   request response   封装了 request response
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        //httprequest对象
        ServerHttpRequest request = exchange.getRequest();        //httpresponse对象
        ServerHttpResponse response = exchange.getResponse();
        System.out.println("经过全局Filter处理.......");
        Mono<Void> filter = chain.filter(exchange);//放心filter继续向后执行
        System.out.println("响应回来Filter处理......");        return filter;
    }    //order 排序  int数字:当又多个filter的时候,用来指定filter执行顺序  默认顺序按照自然数字进行排序 , -1 在所有filter执行之前执行
    @Override
    public int getOrder() {        return -1;
    }
}

通过网关提供web路径查看路由详细规则

1、applicaiton.yaml添加以下配置

management:
  endpoints:
    web:
      exposure:
        include: "*"

2、访问http://localhost:7979/actuator/gateway/routes 路径

image


路由网关组件:zuul


网关简介

  • 网关统一服务入口,可方便实现对平台众多服务接口进行管控,对访问服务的身份认证、防报文重放与防数据篡改、功能调用的业务鉴权、响应数据的脱敏、流量与并发控制,甚至基于API调用的计量或者计费等等。

  • 网关 = 路由转发 + 过滤器

路由转发:接收一切外界请求,转发到后端的微服务上去;在服务网关中可以完成一系列的横切功能,例如权限校验、限流以及监控等,这些都可以通过过滤器完成

网关的作用:

  • 网关统一所有微服务入口

  • 网关可用实现请求路径转发以及请求过程负载均衡

  • 访问服务的身份认证、防报文重放与数据篡改、功能调用的业务鉴权、响应数据的脱敏、流量与并发控制,甚至基于API调用的计量或者计费等等

zuul组件简介

zuul是从设备和网站到Netflix流媒体应用程序后端的所有请求的前门。作为一个边缘服务应用程序,zuul被构建为支持动态路由监视弹性安全性

Zuul包含了对请求的路由(用来跳转的)和过滤两个最主要功能:

其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础。Zuul和Eureka进行整合,将Zuul自身注册为Eureka服务治理下的应用,同时从Eureka中获得其他服务的消息,也即以后的访问微服务都是通过Zuul跳转后获得。

springcloud提供网关组件

  • netfilx zuul1.x(效率) zuul2.x

  • springcloud gateway 组件(Flux 异步非阻塞IO模型) 推荐使用

zuul组件设置路由网关

1、新建一个子模块springcloud-zuul-9527

image

2、添加相关依赖

<dependencies>
        <!--zuul依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <!--Hystrix依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--引入hystrix dashboard 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.study</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

3、编写application.yaml配置文件

server:
  port: 9527#微服务名称spring:
  application:
    name: springcloud-zuul-9527#集群eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
  instance:
    instance-id: zuul9527.com
    prefer-ip-address: true #显示ipinfo:
  app.name: # 项目名称
  company.name: 转身刹那的潇洒

4、修改电脑配置,添加一个网址

image

5、编写主启动类

package com.study.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@SpringBootApplication@EnableZuulProxy //开启zuul代理public class ZuulApplication_9527 {    public static void main(String[] args) {
        SpringApplication.run(ZuulApplication_9527.class,args);
    }
}

6、启动测试

1、启动eureka注册中心集群7001springcloud-eureka-7001
2、启动服务提供者springcloud-provider-dept-hystrix-8001
3、启动路由网关springcloud-zuul-9527

image

image

使用zuul路由
image

7、在application.yaml配置文件里添加以下设置zuul路由网关

#zuul路由配置zuul:
  routes:
    mydept.serverId: springcloud-provider-dept # eureka注册中心的服务提供方路由名称
    # 将eureka注册中心的服务提供方路由名称 改为自定义路由名称。
    mydept.path: /mydept/** # http://www.lxstudy.com:9527/springcloud-provider-dept/dept/get/1和http://www.lxstudy.com:9527/mydept/get/1两个都能访问
    #ignored-services: springcloud-provider-dept #不能在使用http://www.lxstudy.com:9527/springcloud-provider-dept/这个路径访问
    ignored-services: "*"
    prefix: /study # 设置公共的前缀


Hystrix组件:服务降级和 Dashboard 流监控


服务降级

服务降级是指 当服务器压力剧增的情况下,根据实际业务情况及流量,对一些服务和页面有策略的不处理,或换种简单的方式处理,从而释放服务器资源以保证核心业务正常运作或高效运作。说白了,就是尽可能的把系统资源让给优先级高的服务

资源有限,而请求是无限的。如果在并发高峰期,不做服务降级处理,一方面肯定会影响整体服务的性能,严重的话可能会导致宕机某些重要的服务不可用。所以,一般在高峰期,为了保证核心功能服务的可用性,都要对某些服务降级处理。比如当双11活动时,把交易无关的服务统统降级,如查看蚂蚁深林,查看历史订单等等。

服务降级主要用于什么场景呢?当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。

降级的方式可以根据业务来,可以延迟服务,比如延迟给用户增加积分,只是放到一个缓存中,等服务平稳之后再执行 ;或者在粒度范围内关闭服务,比如关闭相关文章的推荐。

关闭微服务系统中某些边缘服务 保证系统核心服务正常运行

使用服务降级

1、在springcloud-api中添加一个服务降级类FallbackFactory

package com.study.springcloud.service;import com.study.springcloud.pojo.Dept;import feign.hystrix.FallbackFactory;import org.springframework.stereotype.Component;import java.util.List;@Componentpublic class DeptClientServiceFallbackFactory implements FallbackFactory {    @Override
    public Object create(Throwable throwable) {        return new DeptClientService() {            @Override
            public Dept queryById(Long id) {                return new Dept()
                        .setDeptno(id)
                        .setDname("这个id=>"+id+"没有对应的信息,客户端提供降级的信息,这个服务已经被关闭")
                        .setDb_source("没有数据");
            }            @Override
            public List<Dept> queryAll() {                return null;
            }            @Override
            public boolean addDept(Dept dept) {                return false;
            }
        };
    }
}

2、在DeptClientService中指定降级配置类DeptClientServiceFallBackFactory

image

3、在消费者springcloud-consumer-dept-openfeign中配置appllication.yaml配置熔断降级

server:
  port: 80#开启降级openfeign.hystrixfeign:
  hystrix:
    enabled: true#EurekaClient配置eureka:
  client:
    register-with-eureka: false #不像eureka中注册自己
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/

4、运行测试

1、启动eureka集群注册中心springcloud-eureka-7001springcloud-eureka-7002
2、启动服务提供者springcloud-provider-dept-8001
3、启动消费者springcloud-consumer-dept-openfeign
image
4、关闭服务提供者springcloud-provider-dept-8001
image

服务熔断和降级的区别

  • 服务熔断—>服务端:某个服务超时或异常,引起熔断~,类似于保险丝(自我熔断)

  • 服务降级—>客户端:从整体网站请求负载考虑,当某个服务熔断或者关闭之后,服务将不再被调用,此时在客户端,我们可以准备一个 FallBackFactory ,返回一个默认的值(缺省值)。会导致整体的服务下降,但是好歹能用,比直接挂掉强。

  • 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)

  • 实现方式不太一样,服务降级具有代码侵入性(由控制器完成/或自动降级),熔断一般称为自我熔断。

Dashboard 流监控

Hystrix Dashboard的一个主要优点是它收集了关于每个HystrixCommand的一组度量。Hystrix仪表板以高效的方式显示每个断路器的运行状况

1、新建消费者模块springcloud-sonsumer-hystrix-dashboard

image

2、添加相关依赖

 <dependencies>
        <!--Hystrix依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--引入hystrix dashboard 依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
        <dependency>
            <groupId>org.study</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

3、编写application.yaml配置文件

server:
  port: 9001hystrix:
  dashboard:
    proxy-stream-allow-list: localhost

4、编写主启动类,添加dashboard监控注解

package com.study.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;@SpringBootApplication@EnableHystrixDashboard//开启dashboard监控public class DeptConsumerDashboard_9001 {    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashboard_9001.class,args);
    }
}

5、检查服务提供者是否都添加监控信息依赖

image

6、启动测试

image

7、给要被监控的服务提供者(springcloud-provider-dept-hystrix-8001模块)下的主启动类添加hystrix依赖和监控

添加hystrix依赖

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

添加监控

package com.study.springcloud;import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletRegistrationBean;import org.springframework.cloud.client.discovery.EnableDiscoveryClient;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;import org.springframework.context.annotation.Bean;//启动类@SpringBootApplication@EnableEurekaClient//在服务启动后自动注册到Eureka中!@EnableDiscoveryClient //服务发现public class DeptProvider_8001 {    public static void main(String[] args) {
        SpringApplication.run(DeptProvider_8001.class,args);
    }    //添加一个Servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());        //访问该页面就是监控页面
        servletRegistrationBean.addUrlMappings("/actuator/hystrix.stream");        return servletRegistrationBean;
    }
}

9、启动eureka集群springclou-eureka-7001,再启动服务提供者springcloud-provider-dept-hystrix-8001

1、
image
2、
image
3、
image
4、
image
5、
image
6、
image

imge


Hystrix组件:服务熔断


服务雪崩

多个微服务之间调用的时候,假设微服务A调用微服务B和微服务C,微服务B和微服务C又调用其他的微服务,这就是所谓的“扇出”,如果扇出的链路上某个微服务的调用响应时间过长,或者不可用,对微服务A的调用就会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。

imge

对于高流量的应用来说,单一的后端依赖可能会导致所有服务器上的所有资源都在几十秒内饱和。比失败更糟糕的是,这些应用程序还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联故障,这些都表示需要对故障和延迟进行隔离和管理,以达到单个依赖关系的失败而不影响整个应用程序或系统运行

Hystrix简介

Hystrix是一个应用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多依赖不可避免的会调用失败,比如超时,异常等,Hystrix 能够保证在一个依赖出问题的情况下,不会导致整个体系服务失败,避免级联故障,以提高分布式系统的弹性。

“断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控 (类似熔断保险丝) ,向调用方返回一个服务预期的,可处理的备选响应 (FallBack) ,而不是长时间的等待或者抛出调用方法无法处理的异常,这样就可以保证了服务调用方的线程不会被长时间,不必要的占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

imge

hystrix 用来保护微服务系统 实现 服务降级 服务熔断

服务熔断

熔断机制是赌赢雪崩效应的一种微服务链路保护机制。

当扇出链路的某个微服务不可用或者响应时间太长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。检测到该节点微服务调用响应正常后恢复调用链路。在SpringCloud框架里熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到一定阀值缺省是5秒内20次调用失败,就会启动熔断机制。熔断机制的注解是:@HystrixCommand

服务熔断解决如下问题:

  • 当所依赖的对象不稳定时,能够起到快速失败的目的;

  • 快速失败后,能够根据一定的算法动态试探所依赖对象是否恢复。

Hystrix实现服务熔断

1、新建一个服务提供者模块springcloud-provider-dept-hystrix-8001

2、添加依赖

 <dependencies>
        <!--我们需要拿到实体类,所以要配置api module-->
        <dependency>
            <groupId>org.study</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
        <!--springboot-test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <!--jetty-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <!--热部署-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.study</groupId>
            <artifactId>SpringCloud</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--Eureka-->
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </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-hystrix</artifactId>
        </dependency>
    </dependencies>

3、把springcloud-provider-dept-8001里所有文件都复制到项目

image

4、重命名主启动了类

image

5、修改DeptController

package com.study.springcloud.controller;import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;import com.study.springcloud.pojo.Dept;import com.study.springcloud.service.DeptService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;//提供Restful服务!@RestController@RequestMapping("/dept")public class DeptController {    @Autowired
    private DeptService deptService;    @GetMapping("/get/{id}")
    //熔断,假设调用这个方法出现错误或者异常导致失败了,就调用里面设置的备选方法
    @HystrixCommand(fallbackMethod = "hystrixGet")
    public Dept get(@PathVariable("id") Long id){        Dept dept = deptService.queryById(id);        if(dept==null){            throw new RuntimeException("id=>"+id+"不存在该用户,或者信息无法找到");
        }        return dept;
    }    //备选方法
    public Dept hystrixGet(@PathVariable("id") Long id){        return new Dept().setDeptno(id).setDname("id=>"+id+"没有对应信息,null~~@Hystrix").setDb_source("no this database in MySql");
    }
}

6、在主启动类添加熔断注解@EnableHystrix

image

7、修改applicaiton.yaml

image

8、启动测试

image