服务熔断保护实践--Sentinal

news2024/11/25 23:49:09

目录

概述

环境说明

步骤

Sentinel服务端

Sentinel客户端

依赖

在客户端配置sentinel参数

测试

保护规则设置

设置资源名

设置默认的熔断规则

RestTemplate的流控规则

Feign的流控规则


概述

微服务有很多互相调用的服务,构成一系列的调用链路,如果调用链路中某个服务失效或者网络堵塞等问题,而有较多请求都需要调用有问题的服务时,这是就会造成多个服务的大面积失效,造成服务“雪崩”效应。

服务“雪崩”的根本原因在于服务之间的强依赖,为了预防服务“雪崩”这一问题,可以做好服务隔离、服务熔断降级、服务限流。

服务隔离:当某个服务故障时,不波及其他模块,不影响整体服务。

服务熔断:当下游服务因为请求压力过大造成响应慢或响应失败时,上游服务为了保护系统,暂时切断对下游服务的调用,直接返回一个降级的内容,从而保全整体系统。

服务限流:限制系统的输入和输出达到保护系统的目的,例如:限制请求速率,超出的请求不处理或者暂缓处理或降级处理。

本文介绍的服务熔断组件是Sentinel

Sentinel和Hystrix的对比

对比项目SentinelHystrix
隔离策略信号量隔离线程池隔离/信号量隔离
熔断策略基于响应时间或失败比例基于失败比例
实时指标实现滑动窗口信号量隔离
规则配置支持多种数据源支持多种数据源
扩展性多个扩展点插件形式
基于注解的支持支持支持
限流基于QPS,支持基于调用关系的限流支持
流量整形支持慢启动、匀速器模式不支持
系统负载保护支持不支持
控制台开箱即用,可配置规则、秒级监控、机器发现等不完善

本文的操作是在 服务熔断保护实践--Hystrix 的基础上进行。
 

环境说明

jdk1.8

maven3.6.3

mysql8

spring cloud2021.0.8

spring boot2.7.12

idea2022

步骤

Sentinel服务端

下载Sentinel服务jar包

cmd进入jar包所在目录

使用java -jar命令启动

D:\soft\sentinel>java -jar sentinel-dashboard-1.8.6.jar

浏览器访问localhost:8080

输入用户名/密码:sentinel/sentinel

进入到Sentinel控制台

Sentinel客户端
依赖

在父工程声明spring-cloud-alibaba依赖(注意:在dependencyManagement里声明)

		<dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2021.0.4.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>

在sentinel客户端的服务(order-service、order-service-feign_hystrix) 引入sentinel依赖

<!--引入sentinel-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

刷新依赖

在客户端配置sentinel参数

application.yml配置sentinel服务控制台信息(涉及到的客户端都加,这里在order-service服务、order-service-feign_hystrix服务里加)

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8080

测试

启动eureka、product、order-service、order-service-feign_hystrix服务

浏览器访问

http://localhost:9002/order/buy/1
http://localhost:9003/order/buy/1

查看sentinel控制台,首页下方看到两个服务

展开,访问子选项

浏览器多次访问服务,能看到实时监控如下

保护规则设置

在order-service服务中,新建一个Controller类,用于sentinel流控测试

由OrderController复制、修改得到Order1Controller

package org.example.order.controller;

import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.example.order.entity.Product;
import org.example.order.feign.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/order1")
public class Order1Controller {

    @Autowired
    private ProductFeignClient productFeignClient;

    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){
        return productFeignClient.findById(id);
    }
    
}

Order1Controller添加降级方法

	/**
     * 定义降级逻辑
     * 熔断执行的降级方法
     */
    public Product orderBlockHandler(Long id){
        Product product = new Product();
        product.setProductName("触发熔断的降级方法");
        return product;
    }

    /**
     * 定义降级逻辑
     * 抛出异常执行的降级方法
     */
    public Product orderExceptionHandler(Long id){
        Product product = new Product();
        product.setProductName("抛出异常执行的降级方法");
        return product;
    }

在请求的方法上方添加@SentinelResource注解

     /**
     * @SentinelResource
     *      blockHandler: 声明熔断时执行的降级方法(限流熔断降级)
     *      fallback: 抛出异常执行的降级方法(异常降级)
     */
    @SentinelResource(blockHandler = "orderBlockHandler", fallback = "orderExceptionHandler")
    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){
        return productFeignClient.findById(id);
    }

修改product服务的findById方法,注释掉模拟网络延迟的代码

启动eureka、product、order服务

多次访问order1接口方法

http://localhost:9002/order1/buy/1

浏览器访问Sentinel控制台

http://localhost:8080/#/dashboard/metric/service-order

看到实时监控数据如下

熟悉相关流控规则设置界面

点击如图+流控按钮添加流控规则,看到如下界面

点击+熔断按钮,看到如下界面

点击+热点按钮,看到如下界面

点击+授权按钮,看到如下界面

修改order-service服务Order1Controller类的findById方法,添加如下代码

		if(id != 1){
            throw new RuntimeException("异常的id,抛出异常");
        }

重启order-service服务

浏览器访问

http://localhost:9002/order1/buy/1

刷新sentinel控制台

点击添加熔断规则

访问:正常访问

http://localhost:9002/order1/buy/1

访问:异常访问

http://localhost:9002/order1/buy/2

触发异常降级方法,按住Ctrl + R组合键,将异常访问次数超过设置阈值1

5s(熔断时长)内,访问id为正常值1,也返回的是异常降级方法

5s(熔断时长)后,访问id为正常值1,能正常访问了

设置资源名

资源名称默认为包名+类名+方法名

如何自定义资源名称?方法如下:

修改接口方法@SentinelResource添加value= "findById"设置

    /**
     * @SentinelResource
     *      blockHandler: 声明熔断时调用的降级方法
     *      fallback: 抛出异常执行的降级方法
     *      value: 自定义资源名称,默认 包名+类名+方法名
     */
    @SentinelResource(value = "findById",blockHandler = "orderBlockHandler", fallback = "orderExceptionHandler")
    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){

重启order服务

发现资源名称变为了自定义的findById

同时发现一个问题:在重启order服务后也清空了熔断规则问题

可以设置默认的熔断规则来解决这个问题。

设置默认的熔断规则

在order-service服务里配置默认的熔断规则

修改application.yml,添加如下sentinel的datasource配置

spring:
  cloud:
    sentinel:
      datasource:
        ds:
          file:
            file: classpath:flowrule.json
            data-type: json
            rule-type: flow

在resources目录下添加flowrule.json文件

[
  {
    "resource": "orderFindById",
    "controlBehavior": 0,
    "count": 1,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]

一条限流规则主要由下面几个因素组成:

resource:资源名,即限流规则的作用对象 count: 限流阈值 grade: 限流阈值类型(QPS 或并发线程数) limitApp: 流控针对的调用来源,若为 default 则不区分调用来源 strategy: 调用关系限流策略 controlBehavior: 流量控制效果(直接拒绝、Warm Up、匀速排队)

这些值,可以参考RuleConstant.class,双击shift 搜索RuleConstant,找到RuleConstant.class

例如:

controlBehavior=0 代表为默认的流量控制 (直接拒绝或快速失败)

controlBehavior=1代码WARN UP(预热)

重启order服务

访问服务

查看Sentinel控制台,能看到默认的流控规则了。

设置默认的熔断规则总结:

通用的流控规则在方法上方添加注解@SentinelResource(value = "findById",blockHandler = "orderBlockHandler", fallback = "orderExceptionHandler"),同时编写对应的降级方法。

RestTemplate的流控规则

修改order服务

@LoadBalanced
@Bean
@SentinelRestTemplate(fallback = "handleFallback", fallbackClass = ExceptionUtil.class, blockHandler="handleBlock",blockHandlerClass=ExceptionUtil.class)
public RestTemplate restTemplate(){
    return new RestTemplate();
}

@SentinelRestTemplate说明

  • 异常降级

    • fallback:异常降级方法

    • fallbackClass:异常降级类

  • 限流降级

    • blockHandler:限流降级方法

    • blockHandlerClass:限流降级类

添加异常类

package org.example.order.exception;

import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import org.example.order.entity.Product;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;

public class ExceptionUtil {
    //限流熔断业务逻辑
    public static SentinelClientHttpResponse handleBlock(HttpRequest request, byte[] body,
                                                         ClientHttpRequestExecution execution, BlockException ex) {
        System.err.println("Oops: " + ex.getClass().getCanonicalName());
        Product product = new Product();
        product.setProductName("限流熔断降级");
        return new SentinelClientHttpResponse(JSON.toJSONString(product));
    }

    //异常熔断业务逻辑
    public static SentinelClientHttpResponse handleFallback(HttpRequest request, byte[] body,
                                                            ClientHttpRequestExecution execution, BlockException ex) {
        System.err.println("fallback: " + ex.getClass().getCanonicalName());
        Product product = new Product();
        product.setProductName("异常熔断降级");
        return new SentinelClientHttpResponse(JSON.toJSONString(product));
    }
}

查看sentinel配置,SentinelProperties.class

修改sentinel配置,使得SpringCloud应用启动时,直接与Sentinel建立心跳连接,访问sentinel 控制台就可以看到服务连接情况,不需要第一次访问应用的某个接口时,才连接sentinel。

spring.cloud.sentinel.eager = true

复制Order1Controller得到Order2Controller,修改代码后如下:

package org.example.order.controller;

import org.example.order.entity.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
@RequestMapping("/order2")
public class Order2Controller {
    @Autowired
    private RestTemplate restTemplate;
    
    @RequestMapping(value = "/buy/{id}", method = RequestMethod.GET)
    public Product findById(@PathVariable Long id){
        if(id != 1){
            throw new RuntimeException("异常的id,抛出异常");
        }
        return restTemplate.getForObject("http://service-product/product/1", Product.class);
    }
}

启动eureka、product、order服务

访问sentinel控制台,直接能看到服务

访问

添加流控规则

测试

访问1次,没有触发流控规则,能正常访问到数据

http://localhost:9002/order2/buy/1

多次访问,触发流控规则,调用了降级方法

控制台显示显示如下

确实是ExceptionUtil的信息

RestTemplate的流控规则总结:

  • RestTemplate的Bean上方添加注解@SentinelRestTemplate

  • 添加异常处理的类

Feign的流控规则

在order-service-feign_hystrix服务修改

在feign中开启sentinel熔断

feign:
  # 在feign中开启hystrix熔断
  #circuitbreaker:
  #  enabled: true
    # 在feign中开启sentinel熔断
  sentinel:
    enabled: true

配置FeignClient

和使用Hystrix的方式一致,需要配置FeignClient接口以及通过 fallback 指定熔断降级方法

启动eureka、product、order-service-feign_hystrix服务

测试

浏览器访问

查看sentinel控制台

添加流控规则

访问次数小于阈值,正常返回数据

多次访问超过阈值,触发了Feign熔断的降级方法

Feign的流控规则总结:

  • 添加依赖

  • 在feign中开启sentinel熔断支持

  • 配置FeignClient接口及实现类里定义熔断方法

完成!enjoy it!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1161193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LangChain介绍及代码实践

一、简介 LangChian 作为一个大语言模型开发框架&#xff0c;是 LLM 应用架构的重要一环。那什么是 LLM 应用架构呢&#xff1f;其实就是指基于语言模型的应用程序设计和开发的架构。 LangChian 可以将 LLM 模型、向量数据库、交互层 Prompt、外部知识、外部工具整合到一起&a…

如何看待将本增效?

如何看待将本增效&#xff1f; 么是降本增效&#xff1f;就是公司里&#xff0c;增进收益的动作要多做&#xff0c;无效的动作要少做&#xff0c;甚至不做。什么叫有效&#xff1f;回到公司的经营目标上去&#xff0c;企业的管理就是目标管理。降本&#xff0c;需要卓越运营&a…

NLP学习笔记:使用 Python 进行NLTK

一、说明 本文和接下来的几篇文章将介绍 Python NLTK 库。NLTK — 自然语言工具包 — NLTK 是一个强大的开源库&#xff0c;用于 NLP 的研究和开发。它内置了 50 多个文本语料库和词汇资源。它支持文本标记化、词性标记、词干提取、词形还原、命名实体提取、分割、分类、语义推…

【计算系统】5分钟了解超算,高性能计算,并行计算,分布式计算,网格计算,集群计算以及云计算的区别

5分钟了解超算&#xff0c;高性能计算&#xff0c;并行计算&#xff0c;分布式计算&#xff0c;网格计算&#xff0c;集群计算以及云计算的区别 1. 超算2. 高性能计算3. 并行计算4. 分布式计算5. 网格计算6. 集群计算7. 云计算小结相关资料 1. 超算 超级计算机&#xff08;Sup…

Android拖放startDragAndDrop拖拽onDrawShadow静态添加xml布局View,Kotlin(4)

Android拖放startDragAndDrop拖拽onDrawShadow静态添加xml布局View&#xff0c;Kotlin&#xff08;4&#xff09; import android.content.ClipData import android.graphics.Canvas import android.graphics.Point import android.os.Bundle import android.util.Log import a…

MATLAB 支持向量机(SVM)

MATLAB 支持向量机&#xff08;SVM&#xff09;详细解释&#xff08;含代码&#xff09; 基础线性可分最大间隔超平面 SVM分类基本代码和工具二分类线性非线性 多分类详细解释 基础 线性可分 简单来讲就是如何将两个数据用点、直线、平面分开。。。。。 二维空间中&#xff…

ios原生分享

什么是 ios 系统的原生分享呢&#xff0c;如下图所示 具体使用系统UIActivityViewController&#xff0c;完整代码如下&#xff1a; -(void)shareAny:(NSString *)text url:(NSString *)_url imagePath:(NSString *)_imagePath {NSLog("shareAny, text:%, url:%, imagePa…

Security ❀ DNS协议常见DOS攻击详解

文章目录 1. DNS协议基础概述2. DNS报文详解2.1. DNS Request 请求包2.2. DNS Reply 响应包 3. DNS Request Flood3.1. 攻击原理3.2. 防护方法3.2.1. TC源认证3.2.2. 被动防御3.2.3. CNAME防护模式3.2.4. *CANME类型解析过程** 4. DNS Reply Flood4.1. 攻击原理4.2. 防护方法 5…

【44.全排列Ⅱ】

目录 一、题目描述二、算法原理三、代码实现 一、题目描述 二、算法原理 三、代码实现 class Solution { public:vector<vector<int>> ret;vector<int> path;vector<bool> check;vector<vector<int>> permuteUnique(vector<int>&am…

C语言--温度转化(把华氏度转换为摄氏度)

一.问题描述: 有人用温度计测量出用华氏法表示的温度,今要求把它转换为以摄氏法表示的温度,转换公式如下: 这个代码是C语言的入门代码&#xff0c;难点在于5/9在程序中如何写出。在计算机中5/9等于1。 /符号&#xff1a;整除问题(整数/整数 结果是丢弃小数的整数) 5/2 2。那…

好看的个人导航页源码

这款导航页源码 非常合适个人使用 简洁漂亮 放点自己经常用到的网站 还支持别人自助添加快捷书签 源码获取&#xff1a;https://www.qqmu.com/930.html

UE5——网络——属性复制

当属性被注册进行复制后&#xff0c;您将无法再取消注册&#xff08;涉及到生存期这一话题&#xff09;。之所以会这样&#xff0c;是因为我们要预制尽可能多的信息&#xff0c;以便针对同一组属性将某一工作分担给多个连接。这样可以节省大量的计算时间。 virtual void GetLif…

java入坑之运行管理

一、概述 1.1Java开发和运行过程 编写阶段&#xff1a;采用各种编辑工具&#xff0c;编写.java文件编译阶段&#xff1a;采用javac.exe对java文件编译&#xff0c;产生.class文件运行阶段&#xff1a;采用java.exe加载.class文件运行 详细过程 1.2相关概念 javaOS管理 JavaOS是…

全新二开游戏支付通道/话费/电网、紫水晶带云端源码

源码修复可用&#xff0c;YY业务都可用 本店所售程序只供测试研究&#xff0c;不得使用于非法用途&#xff0c;不得违反国家法律&#xff0c;不得用于进行违法行为&#xff0c;否则后果自负&#xff01;购买以后用作他用附带的一切法律责任后果都由购买者承担于本店无任何关…

Linux开机、重启、关机和用户登录注销

1.【关机】 shutdown shutdown now 表示立即关机 shutdown -h now 表示立即关机 shutdown -h 1 表示1分钟后关机 halt 用来关闭正在运行的Linux操作系统 2.【重启】 shutdown -r now 表示立即重启 reboot 重启系统 sync …

蜜罐系统HFish的部署与功能实测

1. 引入 根据参考1对蜜罐的定义&#xff1a; 蜜罐&#xff08;Honeypot&#xff09;是一个计算机科学领域的术语&#xff0c;指用于检测或防御未经授权的行为或黑客攻击的陷阱。其名称来源于其工作原理类似于用来诱捕昆虫的蜜罐。蜜罐通常伪装成看似有利用价值的网路、资料、…

JVM修炼印记之初识

文章目录 JVM认识JVM的功能常见JVMHotSpot的发展历程 JVM认识 Java虚拟机&#xff08;Java Virtual Machine&#xff0c;JVM&#xff09;是一个用于执行Java字节码的虚拟计算机。它是Java语言的核心&#xff0c;可以在不同的操作系统和硬件平台上运行Java程序。 JVM负责将Java…

[架构之路-252/创业之路-83]:目标系统 - 纵向分层 - 企业信息化的呈现形态:常见企业信息化软件系统 - 企业应用信息系统集成

目录 第一章 什么是企业应用信息系统集成What 1.1 简介 1.2 架构 二、为什么需要企业应用信息系统集成Why 三、如何实现企业应用信息系统集成 3.1 步骤 3.2 企业应用集成的层次 3.3 业务流程重组 第一章 什么是企业应用信息系统集成What 1.1 简介 企业应用信息系统集…

力扣刷题 day62:11-1

1.反转字符串中的元音字母 给你一个字符串 s &#xff0c;仅反转字符串中的所有元音字母&#xff0c;并返回结果字符串。 元音字母包括 a、e、i、o、u&#xff0c;且可能以大小写两种形式出现不止一次。 方法一&#xff1a;双指针 #方法一&#xff1a;双指针 def reverseV…

国际多语言出海商城源码/返佣产品自动匹配拼单商城源码

源码介绍&#xff1a; 国际多语言出海商城返佣产品自动匹配订单拼单商城源码&#xff0c;8国多语言出海拼单商城。此网站是很多巴西客户定制的原型&#xff0c;已投放运营符合当地本地化。 多语言商城返利返佣投资理财派单自带余额宝&#xff0c;采取全新支付端口&#xff0c…