我是靠谱客的博主 迷路鞋子,最近开发中收集的这篇文章主要介绍Spring Cloud 系列之 Alibaba Sentinel 服务哨兵,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

前文中我们提到 Netflix 中多项开源产品已进入维护阶段,不再开发新的版本,就目前来看是没有什么问题的。但是从长远角度出发,我们还是需要考虑是否有可替代产品使用。比如本文中要介绍的 Alibaba Sentinel 就是一款高性能且轻量级的流量控制、熔断降级可替换方案。

  Sentinel 官网:https://github.com/alibaba/Sentinel

  

Hystrix 目前状态

  

  官网提示:https://github.com/Netflix/Hystrix

Hystrix is no longer in active development, and is currently in maintenance mode.

Hystrix 不再主动开发,当前处于维护模式。

  

1|0Sentinel 是什么

  

  随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

  

Sentinel 具有以下特征:

  • 丰富的应用场景Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring CloudDubbogRPC 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel
  • 完善的 SPI 扩展点Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

  

Sentinel 主要特征

  

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/sentinel-features-overview-en.png

  

Sentinel 开源生态

  

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/sentinel-opensource-eco-landscape-en.png

  

  Sentinel 目前已经针对 Servlet、Dubbo、Spring Boot/Spring Cloud、gRPC 等进行了适配,用户只需引入相应依赖并进行简单配置即可非常方便地享受 Sentinel 的高可用流量防护能力。Sentinel 还为 Service Mesh 提供了集群流量防护的能力。未来 Sentinel 还会对更多常用框架进行适配。

  

Sentinel 分为两个部分:

  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。
  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。

  

2|0Sentinel 的历史

  

  • 2012 年,Sentinel 诞生,主要功能为入口流量控制。
  • 2013-2017 年,Sentinel 在阿里巴巴集团内部迅速发展,成为基础技术模块,覆盖了所有的核心场景。Sentinel 也因此积累了大量的流量归整场景以及生产实践。
  • 2018 年,Sentinel 开源,并持续演进。

  

3|0Sentinel vs Hystrix

  

3|1Hystrix

  

  官网:https://github.com/Netflix/Hystrix

Hystrix is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.

  Hystrix 的关注点在于隔离和熔断为主的容错机制,超时或被熔断的调用将会快速失败,并可以提供 fallback 机制。

  

3|2Sentinel

  

  官网:https://github.com/alibaba/Sentinel

   Sentinel 的关注点在于:

  • 多样化的流量控制
  • 熔断降级
  • 系统负载保护
  • 实时监控和控制台

  

Hystrix 迁移 Sentinel 方案

  

  Sentinel 提供了从 Hystrix 迁移到 Sentinel 的方案,官网:https://github.com/alibaba/Sentinel/wiki/Guideline:-从-Hystrix-迁移到-Sentinel

  

3|3总结

  

Sentinel

Hystrix

隔离策略

信号量隔离(并发线程数限流)

线程池隔离/信号量隔离

熔断降级策略

基于响应时间、异常比率、异常数

基于异常比率

实时指标实现

滑动窗口(LeapArray)

滑动窗口(基于 RxJava)

规则配置

支持多种数据源

支持多种数据源

扩展性

多个扩展点

插件的形式

基于注解的支持

支持

支持

调用链路信息

支持同步调用

不支持

限流

基于 QPS / 并发数,支持基于调用关系的限流

有限支持

流量整形

支持慢启动、匀速器模式

不支持

系统负载保护

支持

不支持

控制台

开箱即用,可配置规则、查看秒级监控、机器发现等

较为简单

常见框架的适配

Servlet、Spring Cloud、Dubbo、gRPC 等

Servlet、Spring Cloud Netflix

  

4|0Sentinel 核心

  

Sentinel 的使用可以分为两个部分:

  • 核心库(Java 客户端):不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持(见 主流框架适配)。
  • 控制台(Dashboard):控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。

  

5|0Sentinel 控制台

  

  Sentinel 提供一个轻量级的开源控制台,它提供机器发现以及健康情况管理、监控(单机和集群),规则管理和推送的功能。

  官网文档:https://github.com/alibaba/Sentinel/wiki/控制台

  

5|1获取控制台

  

  您可以从 release 页面 下载最新版本的控制台 jar 包。

  您也可以从最新版本的源码自行构建 Sentinel 控制台:

  • 下载 控制台 工程
  • 使用以下命令将代码打包成一个 fat jar: mvn clean package

  

5|2启动控制台

  

  启动命令如下,本文使用的是目前最新 1.7.1 版本:

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.1.jar

注意:启动 Sentinel 控制台需要 JDK 版本为 1.8 及以上版本。

  其中 -Dserver.port=8080 用于指定 Sentinel 控制台端口为 8080

  从 Sentinel 1.6.0 起,Sentinel 控制台引入基本的登录功能,默认用户名和密码都是 sentinel。可以参考 鉴权模块文档 配置用户名和密码。

注:若您的应用为 Spring Boot Spring Cloud 应用,您可以通过 Spring 配置文件来指定配置,详情请参考 Spring Cloud Alibaba Sentinel 文档

  

  为了方便启动,可以编写一个启动脚本 run.bat

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.7.1.jar

pause

  

5|3访问

  

  访问:http://localhost:8080/

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131171829583.png

  

  输入默认用户名和密码 sentinel 点击登录。至此控制台就安装完成了。

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131172136071.png

  

6|0环境准备

  

  sentinel-demo 聚合工程。SpringBoot 2.2.4.RELEASESpring Cloud Hoxton.SR1

  • eureka-server:注册中心
  • eureka-server02:注册中心
  • product-service:商品服务,提供了 /product/{id} 接口
  • order-service-rest:订单服务,基于 Ribbon 通过 RestTemplate 调用商品服务
  • order-server-feign:订单服务,基于 Feign 通过声明式服务调用商品服务

  

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131180149055.png

  

7|0客户端接入控制台

  

  点击链接观看:客户端接入控制台视频(获取更多请关注公众号「哈喽沃德先生」)

  

  控制台启动后,客户端需要按照以下步骤接入到控制台:

  • 添加依赖
  • 定义资源
  • 定义规则

  

  先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。

  

  由于我们的项目是 Spring Cloud 项目所以借助官方文档来进行学习。

  Spring 官网文档:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html

  Github 文档:https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel

  

7|1添加依赖

  

  父工程需要添加如下依赖:

<dependencyManagement>

    <dependencies>

        <dependency>

            <groupId>com.alibaba.cloud</groupId>

            <artifactId>spring-cloud-alibaba-dependencies</artifactId>

            <version>2.1.0.RELEASE</version>

            <type>pom</type>

            <scope>import</scope>

        </dependency>

    </dependencies>

</dependencyManagement>

  子工程需要添加如下依赖:

<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>

</dependency>

  

配置文件

  

  客户端需要启动 Transport 模块来与 Sentinel 控制台进行通信。

  order-service-rest 的 application.yml

spring:

  cloud:

    sentinel:

      transport:

        port: 8719

        dashboard: localhost:8080

  这里的 spring.cloud.sentinel.transport.port 端口配置会在应用对应的机器上启动一个 Http Server,该 Server 会与 Sentinel 控制台做交互。比如 Sentinel 控制台添加了一个限流规则,会把规则数据 push 给这个 Http Server 接收,Http Server 再将规则注册到 Sentinel 中。

  

初始化客户端

  

  确保客户端有访问量,Sentinel 会在客户端首次调用的时候进行初始化,开始向控制台发送心跳包。

  简单的理解就是:访问一次客户端,Sentinel 即可完成客户端初始化操作,并持续向控制台发送心跳包。

  

访问

  

  首先确保 Sentinel 是启动状态,然后依次启动 eureka-server,eureka-server02,product-service,order-service-rest。

  多次访问:http://localhost:9090/order/1 然后查看控制台实时监控结果如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200214154631720.png

  

7|2定义资源

  

  点击链接观看:定义资源视频(获取更多请关注公众号「哈喽沃德先生」)

  

  资源 是 Sentinel 中的核心概念之一。我们说的资源,可以是任何东西,服务,服务里的方法,甚至是一段代码。最常用的资源是我们代码中的 Java 方法。Sentinel 提供了 @SentinelResource 注解用于定义资源,并提供了 AspectJ 的扩展用于自动定义资源、处理 BlockException 等。

  官网文档:https://github.com/alibaba/Sentinel/wiki/如何使用#定义资源

  

注解支持

  

  官网文档:https://github.com/alibaba/Sentinel/wiki/注解支持

package com.example.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;

import com.alibaba.csp.sentinel.slots.block.BlockException;

import com.example.pojo.Product;

import com.example.service.ProductService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

/**

 * 商品管理

 */

@Service

public class ProductServiceImpl implements ProductService {

    @Autowired

    private RestTemplate restTemplate;

    /**

     * 根据主键查询商品

     *

     * @param id

     * @return

     */

    @SentinelResource(value = "selectProductById",

            blockHandler = "selectProductByIdBlockHandler", fallback = "selectProductByIdFallback")

    @Override

    public Product selectProductById(Integer id) {

        return restTemplate.getForObject("http://product-service/product/" + id, Product.class);

    }

    // 服务流量控制处理,参数最后多一个 BlockException,其余与原函数一致。

    public Product selectProductByIdBlockHandler(Integer id, BlockException ex) {

        // Do some log here.

        ex.printStackTrace();

        return new Product(id, "服务流量控制处理-托底数据", 1, 2666D);

    }

    // 服务熔断降级处理,函数签名与原函数一致或加一个 Throwable 类型的参数

    public Product selectProductByIdFallback(Integer id, Throwable throwable) {

        System.out.println("product-service 服务的 selectProductById 方法出现异常,异常信息如下:"

                + throwable);

        return new Product(id, "服务熔断降级处理-托底数据", 1, 2666D);

    }

}

注意:注解方式埋点不支持 private 方法。

  

@SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。 @SentinelResource 注解包含以下属性:

  • value:资源名称,必需项(不能为空)
  • entryTypeentry 类型,可选项(默认为 EntryType.OUT
  • blockHandler / blockHandlerClassblockHandler对应处理 BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是 public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为 BlockExceptionblockHandler 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • fallbackfallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要和原函数一致,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • defaultFallbacksince 1.6.0):默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑(即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了 fallback defaultFallback,则只有 fallback 会生效。defaultFallback 函数签名要求:
    • 返回值类型必须与原函数返回值类型一致;
    • 方法参数列表需要为空,或者可以额外多一个 Throwable 类型的参数用于接收对应的异常。
    • defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 对象,注意对应的函数必需为 static 函数,否则无法解析。
  • exceptionsToIgnoresince 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

注:1.6.0 之前的版本 fallback 函数只针对降级异常(DegradeException)进行处理,不能针对业务异常进行处理

  特别地,若 blockHandler 和 fallback 都进行了配置,则被限流降级而抛出 BlockException 时只会进入 blockHandler 处理逻辑。若未配置 blockHandlerfallback 和 defaultFallback,则被限流降级时会将 BlockException 直接抛出(若方法本身未定义 throws BlockException 则会被 JVM 包装一层 UndeclaredThrowableException)。

  从 1.4.0 版本开始,注解方式定义资源支持自动统计业务异常,无需手动调用 Tracer.trace(ex) 来记录业务异常。Sentinel 1.4.0 以前的版本需要自行调用 Tracer.trace(ex) 来记录业务异常。

  

7|3定义规则

  

  Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。同时 Sentinel 也提供相关 API,供您来定制自己的规则策略。

  Sentinel 支持以下几种规则:流量控制规则熔断降级规则系统保护规则来源访问控制规则 和 热点参数规则

  官网文档:https://github.com/alibaba/Sentinel/wiki/如何使用#规则的种类

  

流量控制规则

  

  点击链接观看:流量控制规则视频(获取更多请关注公众号「哈喽沃德先生」)

  

  选择 簇点链路 找到定义好的资源 selectProductById 并点击对应的规则按钮进行设置。

  

  比如我们设置一个流量控制规则,定义资源访问的 QPS 为 1(每秒能处理查询数目)。

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200214155300979.png

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131213800426.png

  

测试

  

  快速刷新页面多次访问:http://localhost:9090/order/1 结果如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200214155837546.png

  

熔断降级规则

  

模拟服务出错

  

  修改 order-service-rest 项目中的核心代码,模拟服务出错。

package com.example.service.impl;

import com.alibaba.csp.sentinel.annotation.SentinelResource;

import com.alibaba.csp.sentinel.slots.block.BlockException;

import com.example.pojo.Product;

import com.example.service.ProductService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

/**

 * 商品管理

 */

@Service

public class ProductServiceImpl implements ProductService {

    @Autowired

    private RestTemplate restTemplate;

    /**

     * 根据主键查询商品

     *

     * @param id

     * @return

     */

    @SentinelResource(value = "selectProductById",

            blockHandler = "selectProductByIdBlockHandler", fallback = "selectProductByIdFallback")

    @Override

    public Product selectProductById(Integer id) {

        // 模拟查询主键为 1 的商品信息会导致异常

        if (1 == id)

            throw new RuntimeException("查询主键为 1 的商品信息导致异常");

        return restTemplate.getForObject("http://product-service/product/" + id, Product.class);

    }

    // 服务流量控制处理,参数最后多一个 BlockException,其余与原函数一致。

    public Product selectProductByIdBlockHandler(Integer id, BlockException ex) {

        // Do some log here.

        ex.printStackTrace();

        return new Product(id, "服务流量控制处理-托底数据", 1, 2666D);

    }

    // 服务熔断降级处理,函数签名与原函数一致或加一个 Throwable 类型的参数

    public Product selectProductByIdFallback(Integer id, Throwable throwable) {

        System.out.println("product-service 服务的 selectProductById 方法出现异常,异常信息如下:"

                + throwable);

        return new Product(id, "服务熔断降级处理-托底数据", 1, 2666D);

    }

}

  

  熔断降级规则支持相应时间、异常比例、异常数三种方式。

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131214554221.png

  

测试

  

  访问:http://localhost:9090/order/1 结果如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200214160237861.png

  

动态规则扩展

  

  官网文档:

  • https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel#动态数据源支持
  • https://github.com/alibaba/Sentinel/wiki/动态规则扩展#示例

  

  SentinelProperties 内部提供了 TreeMap 类型的 datasource 属性用于配置数据源信息。支持:

  • 文件配置规则
  • Nacos 配置规则
  • ZooKeeper 配置规则
  • Apollo 配置规则
  • Redis 配置规则

  

文件配置规则

  

  Sentinel 支持通过本地文件加载规则配置,使用方式如下(限流规则作为演示):

spring:

  cloud:

    sentinel:

      datasource:

        ds1:

          file:

            file: classpath:flowRule.json

            data-type: json

            rule-type: flow

  

  flowRule.json 对应 com.alibaba.csp.sentinel.slots.block.RuleConstant 各属性。

[

  {

    "resource": "selectProductList",

    "count": 1,

    "grade": 1,

    "limitApp": "default",

    "strategy": 0,

    "controlBehavior": 0

  }

]

  

  重要属性:

Field

说明

默认值

resource

资源名,资源名是限流规则的作用对象

count

限流阈值

grade

限流阈值类型,QPS 模式(1)或并发线程数模式(0)

QPS 模式

limitApp

流控针对的调用来源

default,代表不区分调用来源

strategy

调用关系限流策略:直接、链路、关联

根据资源本身(直接)

controlBehavior

流控效果(直接拒绝 / 排队等待 / 慢启动模式),不支持按调用关系限流

直接拒绝

clusterMode

是否集群限流

  

  访问客户端以后,刷新控制台,查看流控规则如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131221321055.png

  

8|0RestTemplate 支持

  

  Spring Cloud Alibaba Sentinel 支持对 RestTemplate 调用的服务进行服务保护。需要在构造 RestTemplate Bean 时添加 @SentinelRestTemplate 注解。

  

8|1启动类

  

  OrderServiceRestApplication.java

package com.example;

import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;

import com.example.exception.ExceptionUtil;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.client.loadbalancer.LoadBalanced;

import org.springframework.context.annotation.Bean;

import org.springframework.web.client.RestTemplate;

@SpringBootApplication

public class OrderServiceRestApplication {

    @Bean

    @LoadBalanced

    @SentinelRestTemplate(blockHandler = "handleException", blockHandlerClass = ExceptionUtil.class,

            fallback = "fallback", fallbackClass = ExceptionUtil.class)

    public RestTemplate restTemplate() {

        return new RestTemplate();

    }

    public static void main(String[] args) {

        SpringApplication.run(OrderServiceRestApplication.class, args);

    }

}

  

8|2服务熔断处理类

  

  ExceptionUtil.java 必须使用静态方法。

package com.example.exception;

import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;

import com.alibaba.csp.sentinel.slots.block.BlockException;

import com.alibaba.fastjson.JSON;

import com.example.pojo.Product;

import org.springframework.http.HttpRequest;

import org.springframework.http.client.ClientHttpRequestExecution;

import org.springframework.http.client.ClientHttpResponse;

public class ExceptionUtil {

    // 服务流量控制处理

    public static ClientHttpResponse handleException(HttpRequest request,

                                                     byte[] body,

                                                     ClientHttpRequestExecution execution,

                                                     BlockException exception) {

        exception.printStackTrace();

        return new SentinelClientHttpResponse(

                JSON.toJSONString(new Product(1, "服务流量控制处理-托底数据", 1, 2666D)));

    }

    // 服务熔断降级处理

    public static ClientHttpResponse fallback(HttpRequest request,

                                                    byte[] body,

                                                    ClientHttpRequestExecution execution,

                                                    BlockException exception) {

        exception.printStackTrace();

        return new SentinelClientHttpResponse(

                JSON.toJSONString(new Product(1, "服务熔断降级处理-托底数据", 1, 2666D)));

    }

}

  

8|3访问

  

  控制台设置流量控制规则,定义资源访问的 QPS 为 1(每秒能处理查询数目)。

  快速刷新页面多次访问:http://localhost:9090/order/1 结果如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200214155837546.png

  

9|0OpenFeign 支持

  

  其实不管是 Hystrix 还是 Sentinel 对于 Feign 的支持,核心代码基本上是一致的,只需要修改依赖和配置文件即可。

  

9|1添加依赖

  

<!-- spring cloud openfeign 依赖 -->

<dependency>

    <groupId>org.springframework.cloud</groupId>

    <artifactId>spring-cloud-starter-openfeign</artifactId>

</dependency>

<!-- spring cloud alibaba sentinel 依赖 -->

<dependency>

    <groupId>com.alibaba.cloud</groupId>

    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>

</dependency>

  

9|2开启 Sentinel

  

server:

  port: 9091 # 端口

spring:

  application:

    name: order-service-feign # 应用名称

  cloud:

    sentinel:

      transport:

        port: 8719

        dashboard: localhost:8080

# 配置 Eureka Server 注册中心

eureka:

  instance:

    prefer-ip-address: true       # 是否使用 ip 地址注册

    instance-id: ${spring.cloud.client.ip-address}:${server.port} # ip:port

  client:

    service-url:                  # 设置服务注册中心地址

      defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/

# feign 开启 sentinel 支持

feign:

  sentinel:

    enabled: true

  

9|3熔断降级

  

  ProductServiceFallback.java

package com.example.fallback;

import com.example.pojo.Product;

import com.example.service.ProductService;

import feign.hystrix.FallbackFactory;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.stereotype.Component;

/**

 * 服务熔断降级处理可以捕获异常

 */

@Component

public class ProductServiceFallbackFactory implements FallbackFactory<ProductService> {

    // 获取日志,在需要捕获异常的方法中进行处理

    Logger logger = LoggerFactory.getLogger(ProductServiceFallbackFactory.class);

    @Override

    public ProductService create(Throwable throwable) {

        return new ProductService() {

            @Override

            public Product selectProductById(Integer id) {

                logger.error("product-service 服务的 selectProductById 方法出现异常,异常信息如下:"

                        + throwable);

                return new Product(id, "托底数据", 1, 2666D);

            }

        };

    }

}

  

9|4消费服务

  

  ProductService.java

package com.example.service;

import com.example.fallback.ProductServiceFallbackFactory;

import com.example.pojo.Product;

import org.springframework.cloud.openfeign.FeignClient;

import org.springframework.web.bind.annotation.GetMapping;

import org.springframework.web.bind.annotation.PathVariable;

// 声明需要调用的服务

@FeignClient(value = "product-service", fallbackFactory = ProductServiceFallbackFactory.class)

public interface ProductService {

    /**

     * 根据主键查询商品

     *

     * @param id

     * @return

     */

    @GetMapping("/product/{id}")

    Product selectProductById(@PathVariable("id") Integer id);

}

  

  OrderServiceImpl.java

package com.example.service.impl;

import com.example.pojo.Order;

import com.example.service.OrderService;

import com.example.service.ProductService;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import java.util.Arrays;

@Service

public class OrderServiceImpl implements OrderService {

    @Autowired

    private ProductService productService;

    /**

     * 根据主键查询订单

     *

     * @param id

     * @return

     */

    @Override

    public Order selectOrderById(Integer id) {

        return new Order(id, "order-001", "中国", 2666D,

                Arrays.asList(productService.selectProductById(1)));

    }

}

  

9|5控制层

  

package com.example.controller;

import com.example.pojo.Order;

import com.example.service.OrderService;

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;

@RestController

@RequestMapping("/order")

public class OrderController {

    @Autowired

    private OrderService orderService;

    /**

     * 根据主键查询订单

     *

     * @param id

     * @return

     */

    @GetMapping("/{id}")

    public Order selectOrderById(@PathVariable("id") Integer id) {

        return orderService.selectOrderById(id);

    }

}

  

9|6启动类

  

package com.example;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.cloud.openfeign.EnableFeignClients;

// 开启 FeignClients 注解

@EnableFeignClients

@SpringBootApplication

public class OrderServiceFeignApplication {

    public static void main(String[] args) {

        SpringApplication.run(OrderServiceFeignApplication.class, args);

    }

}

  

9|7测试

  

  控制台信息如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131233524521.png

  

  添加流量控制规则,定义资源访问的 QPS 为 1(每秒能处理查询数目)。

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200131233925164.png

  

  快速刷新页面多次访问:http://localhost:9091/order/1 结果如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200214161610742.png

  

  或者关闭服务提供者,访问:http://localhost:9091/order/1 结果如下:

https://mrhelloworld.com/resources/articles/spring/spring-cloud/sentinel/image-20200214161610742.png

  至此 Sentinel 服务哨兵知识点就讲解结束了。

https://mrhelloworld.com/resources/articles/articles_bottom/end02.gif

  本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议

  大家可以通过 分类 查看更多关于 Spring Cloud 的文章。

最后

以上就是迷路鞋子为你收集整理的Spring Cloud 系列之 Alibaba Sentinel 服务哨兵的全部内容,希望文章能够帮你解决Spring Cloud 系列之 Alibaba Sentinel 服务哨兵所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(31)

评论列表共有 0 条评论

立即
投稿
返回
顶部