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

相关文章

Spring LDAP目录服务的使用示例

《SpringLDAP目录服务的使用示例》本文主要介绍了SpringLDAP目录服务的使用示例... 目录引言一、Spring LDAP基础二、LdapTemplate详解三、LDAP对象映射四、基本LDAP操作4.1 查询操作4.2 添加操作4.3 修改操作4.4 删除操作五、认证与授权六、高级特性与最佳

Spring Shell 命令行实现交互式Shell应用开发

《SpringShell命令行实现交互式Shell应用开发》本文主要介绍了SpringShell命令行实现交互式Shell应用开发,能够帮助开发者快速构建功能丰富的命令行应用程序,具有一定的参考价... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定义S

SpringSecurity JWT基于令牌的无状态认证实现

《SpringSecurityJWT基于令牌的无状态认证实现》SpringSecurity中实现基于JWT的无状态认证是一种常见的做法,本文就来介绍一下SpringSecurityJWT基于令牌的无... 目录引言一、JWT基本原理与结构二、Spring Security JWT依赖配置三、JWT令牌生成与

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

如何配置Spring Boot中的Jackson序列化

《如何配置SpringBoot中的Jackson序列化》在开发基于SpringBoot的应用程序时,Jackson是默认的JSON序列化和反序列化工具,本文将详细介绍如何在SpringBoot中配置... 目录配置Spring Boot中的Jackson序列化1. 为什么需要自定义Jackson配置?2.

Java中使用Hutool进行AES加密解密的方法举例

《Java中使用Hutool进行AES加密解密的方法举例》AES是一种对称加密,所谓对称加密就是加密与解密使用的秘钥是一个,下面:本文主要介绍Java中使用Hutool进行AES加密解密的相关资料... 目录前言一、Hutool简介与引入1.1 Hutool简介1.2 引入Hutool二、AES加密解密基础

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

SpringBoot实现微信小程序支付功能

《SpringBoot实现微信小程序支付功能》小程序支付功能已成为众多应用的核心需求之一,本文主要介绍了SpringBoot实现微信小程序支付功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作... 目录一、引言二、准备工作(一)微信支付商户平台配置(二)Spring Boot项目搭建(三)配置文件

解决SpringBoot启动报错:Failed to load property source from location 'classpath:/application.yml'

《解决SpringBoot启动报错:Failedtoloadpropertysourcefromlocationclasspath:/application.yml问题》这篇文章主要介绍... 目录在启动SpringBoot项目时报如下错误原因可能是1.yml中语法错误2.yml文件格式是GBK总结在启动S

Spring中配置ContextLoaderListener方式

《Spring中配置ContextLoaderListener方式》:本文主要介绍Spring中配置ContextLoaderListener方式,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录Spring中配置ContextLoaderLishttp://www.chinasem.cntene