SpringCloud Netflix集成Sentinel限流

2024-05-06 20:32

本文主要是介绍SpringCloud Netflix集成Sentinel限流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、摘要

1.1、sentinel介绍

1.2、sentinel特征

二、学习目标

三、实施步骤

3.1、新建项目product-server。

        3.1.1、New->File->Project->Spring Initializr

        3.1.2、选择依赖的jar(product-server选择lombok、spring-boot-starter-web、spring-cloud-starter-netflix-eureka-client):

        3.1.3、知识拓展

3.2、同样的步骤,新建order-server服务模块;其中order-server需要依赖openFeign。

3.3、实现产品查询接口

3.4、order-server使用feign调用product-server查询接口.

3.5、启动product-server和order-server服务。

3.6、下载sentinel并启动。

3.7、下载jemeter压测,下载地址:Apache JMeter - Apache JMeter™

3.8、在sentinel面板设置限流策略

3.9、QPS限流——我们设置query/{id}接口qps为8个请求/秒。

3.10、并发线程数限流——设置成每秒5个请求。

四、sentinel限流原理

4.1、sentinel如何拦截feign接口

4.2、四种限流原理

计数器限流算法

滑动窗口限流算法

漏桶限流算法

令牌桶限流算法

五、参考文章


一、摘要

1.1、sentinel介绍

Sentinel是阿里开源的项目,提供了流量控制、熔断降级、系统负载保护等多个维度来保障服务之间的稳定性。官网:Home · alibaba/Sentinel Wiki · GitHub

2012年,Sentinel诞生于阿里巴巴,其主要目标是流量控制。2013-2017年,Sentinel迅速发展,并成为阿里巴巴所有微服务的基本组成部分。 它已在6000多个应用程序中使用,涵盖了几乎所有核心电子商务场景。2018年,Sentinel演变为一个开源项目。2020年,Sentinel Golang发布。

1.2、sentinel特征

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

完善的 SPI 扩展点:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel的生态圈

二、学习目标

2.1、完成springcloud netflix框架搭建

2.2、完成springCloud与Sentinel的集成

2.3、使用Jemeter测试限流功能

2.4、总结Sentinel限流原理

3.5、服务有:一个集群的eureka服务(部署两个)、一个产品服务product-server、一个订单服务order-server、还有sentinel服务。其中eureka服务部署请看Eureka Server集群服务搭建_DayDayUp的博客-CSDN博客。

3.6、各框架版本

框架版本注意
spring-boot2.5.5版本如果不兼容会出现意想不到的问题。
spring-cloud-starter-alibaba-sentinel2021.1
spring-cloud2020.0.4

三、实施步骤

3.1、新建项目product-server。

        3.1.1、New->File->Project->Spring Initializr

 输入项目名及选择配置。

        3.1.2、选择依赖的jar(product-server选择lombok、spring-boot-starter-web、spring-cloud-starter-netflix-eureka-client):

        3.1.3、知识拓展

  1. Developer tools->勾选Lombok, 作用:Lombok 提供了一些注解来帮助我们简化消除一些必须有但显得臃肿的 java 代码,如 gettingsetting、toString、equals等.
  2. Web->勾选Spring web,作用:Spring-boot-starter-web->提供servlet容器——tomcat、webmvc(restFul api)、spring核心jar、spring的bean装载jar、log日志jar等依赖(没有它,无法启动项目).
  3. Spring Cloud Discovery->勾选Eureka Discovery client: 注册中心eureka的客户端的依赖jar.
  4. Spring Cloud Routing->勾选OpenFeign,作用:Feign接口依赖的jar(feign自动依赖ribbon和hystrix相关jar).

3.2、同样的步骤,新建order-server服务模块;其中order-server需要依赖openFeign。

3.3、实现产品查询接口

        3.3.1、新建基本类请求对象ProductResponse和响应对象Response。

package com.example.product.response;import lombok.AllArgsConstructor;
import lombok.Data;import java.math.BigDecimal;@Data
@AllArgsConstructor
public class ProductResponse {private Integer id;private String name;private Integer num;private BigDecimal price;}
package com.example.product.response;import lombok.Getter;
import lombok.Setter;@Setter
@Getter
public class Response<T>{private Integer errorCode;private String errorMsg;private T data;public Response(Integer errorCode, String errorMsg, T data) {this.errorCode = errorCode;this.errorMsg = errorMsg;this.data = data;}public static <T> Response<T> success(T data){return new Response<>(null, null, data);}}

           3.3.2、product-server的application.yml配置。

spring:application:name: product-server
server:port: 8081servlet:context-path: /product
#配置注册eureka地址(带用户名和密码)
eureka:client:serviceUrl:defaultZone: http://eureka:eureka@localhost:8671/eureka,http://eureka:eureka@localhost:8672/eureka

        3.3.3、 product-server的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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.5</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>product-server</artifactId><version>0.0.1-SNAPSHOT</version><name>product-server</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-cloud.version>2020.0.4</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><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><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

        3.3.4、产品查询接口简单实现

package com.example.product.controller;import com.example.product.response.ProductResponse;
import com.example.product.response.Response;
import com.example.product.service.ProductService;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;@RestController
public class ProductController {@Resourceprivate ProductService productService;@RequestMapping(value = "/select/{id}")public Response<ProductResponse> selectById(@PathVariable Integer id){return Response.success(productService.queryById(id));}}
package com.example.product.service;import com.example.product.response.ProductResponse;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;@Service
public class ProductService {private static Map<Integer, ProductResponse> productHashMap = new HashMap<>();static {productHashMap.put(1, new ProductResponse(1, "冰箱", 5, new BigDecimal(20000)));productHashMap.put(2, new ProductResponse(2, "空调", 9, new BigDecimal(30000)));productHashMap.put(3, new ProductResponse(3, "洗衣机", 8, new BigDecimal(5000)));}public ProductResponse queryById(Integer id){return productHashMap.get(id);}
}

3.4、order-server使用feign调用product-server查询接口.

        3.4.1、新建基本类请求对象ProductResponse和响应对象Response(可以做成jar依赖order)。

package com.example.order.response;import lombok.AllArgsConstructor;
import lombok.Data;import java.math.BigDecimal;@Data
@AllArgsConstructor
public class ProductResponse{private Integer id;private String name;private Integer num;private BigDecimal price;}
package com.example.order.response;import lombok.Getter;
import lombok.Setter;@Setter
@Getter
public class Response<T>{private Integer errorCode;private String errorMsg;private T data;public Response(Integer errorCode, String errorMsg, T data) {this.errorCode = errorCode;this.errorMsg = errorMsg;this.data = data;}public static <T> Response<T> success(T data){return new Response<>(null, null, data);}}

        3.4.2、feign接口实现

package com.example.order.feign;import com.example.order.response.ProductResponse;
import com.example.order.response.Response;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;@FeignClient(name = "product-server", path = "/product", fallbackFactory = ProductMicroServerFallbackFactory.class)
public interface ProductMicroServer {@GetMapping(value = "/select/{id}")Response<ProductResponse> selectById(@PathVariable Integer id);
}
package com.example.order.feign;import com.example.order.response.ProductResponse;
import com.example.order.response.Response;
import org.springframework.stereotype.Service;import java.math.BigDecimal;@Service
public class ProductMicroServerFallback implements ProductMicroServer{@Overridepublic Response<ProductResponse> selectById(Integer id) {return Response.success(new ProductResponse(0, "棒棒糖(兜底商品)", 1, new BigDecimal(0.5)));}
}
package com.example.order.feign;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;import javax.annotation.Resource;@Slf4j
@Service
public class ProductMicroServerFallbackFactory implements FallbackFactory<ProductMicroServer> {@Resourceprivate ProductMicroServerFallback productMicroServerFallback;@Overridepublic ProductMicroServer create(Throwable cause) {log.error("ProductMicroServerFallback->selectById(Integer id) exception:", cause);return productMicroServerFallback;}
}

 启动类添加激活feign接口注解并指定扫描包。

package com.example.order;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;@EnableFeignClients(value = "com.example.order.feign")
@SpringBootApplication
public class OrderServerApplication {public static void main(String[] args) {SpringApplication.run(OrderServerApplication.class, args);}}

    3.4.3、application.yml和pom.xml配置

        application.yml添加sentinel配置及支持。

spring:application:name: order-servercloud:sentinel:transport:#指定控制台交流的端口,随意指定一个未使用的端口即可port: 8719#sentinel dashboard 地址dashboard: localhost:8080
server:port: 8082servlet:context-path: /order#Sentinel 对 Feign 的支持
feign:sentinel:enabled: true#配置注册eureka地址(带用户名和密码)
eureka:client:serviceUrl:defaultZone: http://eureka:eureka@localhost:8671/eureka

 pom.xml添加sentinel的jar依赖。

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.4</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>order-server</artifactId><version>0.0.1-SNAPSHOT</version><name>order-server</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-cloud.version>2020.0.4</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2021.1</version></dependency></dependencies><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><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><excludes><exclude><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></exclude></excludes></configuration></plugin></plugins></build></project>

3.5、启动product-server和order-server服务。

        3.5.1、启动后并查看是否注册到eureka。

         3.5.2、访问order-server查询接口,检测feign服务是调用成功:http://localhost:8082/order/query/1

 

3.6、下载sentinel并启动。

        3.6.1、下载地址:控制台 · alibaba/Sentinel Wiki · GitHub

        3.6.2、启动sentinel

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

启动日志:

 浏览器输入sentinel启动时指定端口号8080,http://localhost:8080, 如下(默认登录密码为sentinel)。

成功访问一次product查询商品接口后再次刷新sentinel面板,出现order-server表示集成生效。

3.7、下载jemeter压测,下载地址:Apache JMeter - Apache JMeter™

        3.7.1、运行bin\jemeter.bat文件启动jemeter(可以选择中文操作界面)。

         3.7.2、添加线程组测试。

        3.7.3、添加http请求。

        3.7.4、添加结果数查看。

         3.7.5、添加http接口配置

        3.7.6、设置线程并发数。

3.8、在sentinel面板设置限流策略

        3.8.1、在sentinel面板找到指定的接口并设置限流策略。

3.9、QPS限流——我们设置query/{id}接口qps为8个请求/秒。

 启动jemeter压测。  

 启动后查看结果数,发现sentinel的qps限流生效。

 查看sentinel的限流数据及监控。

3.10、并发线程数限流——设置成每秒5个请求。

sentinel并发线程数限流设置。

 jemeter压测线程数设置成每秒300个线程(我电脑是4核)。

 压测结果:

 

四、sentinel限流原理

4.1、sentinel如何拦截feign接口

sentinel跟 hystrix 一样实现自定义的java.lang.reflect.InvocationHandler 接口 SentinelInvocationHandler 用来处理方法的调用。

4.2、四种限流原理

  • 计数器限流算法

        计数器是限流中最简单的,规定为:在指定周期内累加访问次数,当访问次数达到设定的阈值时,出发限流策略,当进入下一个时间周期时会将访问次数清零。

        优点:实现简单
        临界问题:如图所示,当在8-10秒和10-12秒内分别并发500,虽然没有超过阈值,但如果算8-12秒,则并发数高达1000,已经超过了原先定义的10秒内不超过500的并发量。

  • 滑动窗口限流算法

        为了避免计数器中的临界问题,让限制更加平滑,将固定窗口中分割出多个小时间窗口,分别在每个小的时间窗口中记录访问次数,然后根据时间将窗口往前滑动并删除过期的小时间窗口。

        优点:实现相对简单,且没有计数器算法的临界问题
        缺点:无法应对短时间高并发(突刺现象)

  • 漏桶限流算法

        漏桶限流算法的核心就是, 不管上面的水流速度有多块, 漏桶水滴的流出速度始终保持不变

        实际应用:消息中间件采用的就是漏桶限流的思想

        主要作用:

  1. 控制数据注入网络的速度
  2. 平滑网络上的突发流量(类似于电容整流)

        不足:无法应对突发的并发流量,因为流出速率一直都是恒定的

  • 令牌桶限流算法

        令牌桶是网络流量整形(Traffic Shaping)速率限制(Rate Limiting)中最常使用的一种算法。速度恒定、令牌桶大小固定,如果令牌桶被填满,则会丢弃生成的令牌,如果桶内没有令牌则出现限流策略。

        优点:可以像漏桶那样匀速,也可以像计数器那样突发处理。

五、参考文章

1、控制台 · alibaba/Sentinel Wiki · GitHub

2、常用的四种限流算法图解_July的博客-CSDN博客

这篇关于SpringCloud Netflix集成Sentinel限流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/965301

相关文章

springboot健康检查监控全过程

《springboot健康检查监控全过程》文章介绍了SpringBoot如何使用Actuator和Micrometer进行健康检查和监控,通过配置和自定义健康指示器,开发者可以实时监控应用组件的状态,... 目录1. 引言重要性2. 配置Spring Boot ActuatorSpring Boot Act

使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)

《使用Java解析JSON数据并提取特定字段的实现步骤(以提取mailNo为例)》在现代软件开发中,处理JSON数据是一项非常常见的任务,无论是从API接口获取数据,还是将数据存储为JSON格式,解析... 目录1. 背景介绍1.1 jsON简介1.2 实际案例2. 准备工作2.1 环境搭建2.1.1 添加

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

java如何分布式锁实现和选型

《java如何分布式锁实现和选型》文章介绍了分布式锁的重要性以及在分布式系统中常见的问题和需求,它详细阐述了如何使用分布式锁来确保数据的一致性和系统的高可用性,文章还提供了基于数据库、Redis和Zo... 目录引言:分布式锁的重要性与分布式系统中的常见问题和需求分布式锁的重要性分布式系统中常见的问题和需求

SpringBoot基于MyBatis-Plus实现Lambda Query查询的示例代码

《SpringBoot基于MyBatis-Plus实现LambdaQuery查询的示例代码》MyBatis-Plus是MyBatis的增强工具,简化了数据库操作,并提高了开发效率,它提供了多种查询方... 目录引言基础环境配置依赖配置(Maven)application.yml 配置表结构设计demo_st

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单

《Springboot的ThreadPoolTaskScheduler线程池轻松搞定15分钟不操作自动取消订单》:本文主要介绍Springboot的ThreadPoolTaskScheduler线... 目录ThreadPoolTaskScheduler线程池实现15分钟不操作自动取消订单概要1,创建订单后

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

SpringCloud集成AlloyDB的示例代码

《SpringCloud集成AlloyDB的示例代码》AlloyDB是GoogleCloud提供的一种高度可扩展、强性能的关系型数据库服务,它兼容PostgreSQL,并提供了更快的查询性能... 目录1.AlloyDBjavascript是什么?AlloyDB 的工作原理2.搭建测试环境3.代码工程1.

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python