IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> 网关限流及高可用_springCloud_6 -> 正文阅读

[大数据]网关限流及高可用_springCloud_6

一.基于漏桶算法的内置filter的限流

1.1 准备工作:

1.1.1 本地解压一个redis安装包,启动并监控

先打开服务:redis-server.exe,再打开客户端窗口:redis-cli.exe,打开客户端后输入: monitor命令进行监控
如下图所示:

在这里插入图片描述

1.1.2 工程中导入依赖:

在工程中引入redis相应的依赖:基于reactive的redis依赖
       <!--监控依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!--redis的依赖-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>

1.2 修改网关中的yml文件

server:
  port: 8080 #端口
spring:
  application:
    name: api-gateway-server #服务名称
  redis:
    host: localhost
    pool: 6379
    database: 0
  cloud: #配置SpringCloudGateway的路由
    gateway:
      routes:
      - id: product-service
        uri: lb://service-product
        predicates:
        - Path=/product-service/**
        filters:
        - name: RequestRateLimiter
          args:
            # 使用SpEL从容器中获取对象
            key-resolver: '#{@pathKeyResolver}'  #pathKeyResolver与配置类中的方法名一致
            # 令牌桶每秒填充平均速率
            redis-rate-limiter.replenishRate: 1
            # 令牌桶的上限
            redis-rate-limiter.burstCapacity: 3
        - RewritePath=/product-service/(?<segment>.*), /$\{segment}
      #RequestRateLimiter:使用限流过滤器,是sppringcloud gateway提供的
      #参数 replenishRate:向令牌桶内填充的速率
      #     burstCapacity:令牌桶的容量
#eureka注册中心
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/
  instance:
    prefer-ip-address: true #使用ip地址注册

1.3 配置redis中key的解析器KeyResolve

package cn.itcast.gateway;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 限流规则配置类-存在多个KeyResolver会抛出异常
 * 1.基于路径的限流规则 :abc
 * 2.基于请求ip的限流规则 127.0.0.1
 * 3.基于参数的
 */
@Configuration
public class KeyResolverConfiguration {

    /**
     * 编写基于请求路径的限流规则
     * 方法名称与yml配置文件中的key-resolver属性的@后面的名称一致
     */
    //@Bean
    public KeyResolver pathKeyResolver(){
        return new KeyResolver() {
            /**
             *
             * ServerWebExchange 上下文参数
             *
             */
            public Mono<String> resolve(ServerWebExchange exchange) {
                return  Mono.just(exchange.getRequest().getPath().toString());

            }
        };
    }

    /**
     * 基于lambad表达式的形式基于参数的限流
     *  格式 abc?access-token=1
     */
    @Bean
    public KeyResolver userKeyResolver(){
        return exchange -> Mono.just(
            //基于请求参数的限流
            exchange.getRequest().getQueryParams().getFirst("access-token")
            //基于ip地址的限流
            //  exchange.getRequest().getHeaders().getFirst("X-Forwarded-For")
        );
    }
}

二.基于Sentinel的限流

1.引入依赖:

<dependency>
      <groupId>com.alibaba.csp</groupId>
      <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
      <version>1.6.3</version>
</dependency>

2.修改yml配置文件

注释基于filter的限流规则yml配置

server:
  port: 8080 #端口
spring:
  application:
    name: api-gateway-server #服务名称
  redis:
    host: localhost
    pool: 6379
    database: 0
  cloud: #配置SpringCloudGateway的路由
    gateway:
      routes:
      - id: product-service
        uri: lb://service-product
        predicates:
        - Path=/product-service/**
        filters:
#        - name: RequestRateLimiter
#          args:
#            # 使用SpEL从容器中获取对象
#            #key-resolver: '#{@pathKeyResolver}'  #pathKeyResolver与配置类中的方法名一致
#            key-resolver: '#{@userKeyResolver}'  #pathKeyResolver与配置类中的方法名一致
#            # 令牌桶每秒填充平均速率
#            redis-rate-limiter.replenishRate: 1
#            # 令牌桶的上限
#            redis-rate-limiter.burstCapacity: 3
        - RewritePath=/product-service/(?<segment>.*), /$\{segment}
      #RequestRateLimiter:使用限流过滤器,是sppringcloud gateway提供的
      #参数 replenishRate:向令牌桶内填充的速率
      #     burstCapacity:令牌桶的容量
#eureka注册中心
eureka:
  client:
    service-url:
      defaultZone: http://localhost:9000/eureka/
  instance:
    prefer-ip-address: true #使用ip地址注册

3.创建配置类GatewayConfiguration

3.1 配置类增加限流规则方法

/**
 * 配置初始化的限流参数
 * 用于指定资源的限流规则
 * 		1.资源名称(yml文件中的路由id)
 * 		2.配置统计时间- setIntervalSec
 * 		3.配置限流阀值
 */
@PostConstruct
public void initGatewayRules() {
	Set<GatewayFlowRule> rules = new HashSet<>();
	rules.add(new GatewayFlowRule("product-service")
			.setCount(1)
			.setIntervalSec(1)
	);

	GatewayRuleManager.loadRules(rules);
}

3.2 修改限流后提示语不明确的配置方法

未增加配置前提示:
	Blocked by Sentinel: ParamFlowException

增加明确方法:

/**
* 自定义一个限流处理器,解决限流后提示信息"Blocked by Sentinel: ParamFlowException"不明确的问题
 */
@PostConstruct
public void initBlockHandlers() {
	BlockRequestHandler blockRequestHandler= new BlockRequestHandler() {
		@Override
		public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
			HashMap<Object, Object> map = new HashMap<>();
			map.put("code","200");
			map.put("message","不好意思,限流了");
			return ServerResponse.status(HttpStatus.OK)
					.contentType(MediaType.APPLICATION_JSON_UTF8)
					.body(BodyInserters.fromObject(map));

		}
	};
	GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}

4.自定义分组限流

添加方法:

/**
	 * 自定义API限流分组
	 * 		1.定义分组
	 * 		2.对小组配置限流规则
	 */
	@PostConstruct
	private void initCustomizedApis() {
		Set<ApiDefinition> definitions = new HashSet<>();
		ApiDefinition api1 = new ApiDefinition("product_api")
				.setPredicateItems(new HashSet<ApiPredicateItem>() {{
					add(new ApiPathPredicateItem().setPattern("/product-service/product/**").		//以/product-service/product/开头的所有url
							setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
				}});
		ApiDefinition api2 = new ApiDefinition("order_api")
				.setPredicateItems(new HashSet<ApiPredicateItem>() {{
					add(new ApiPathPredicateItem().setPattern("/order-service/order"));	//完全匹配/order-service/order的URL
				}});
		definitions.add(api1);
		definitions.add(api2);
		GatewayApiDefinitionManager.loadApiDefinitions(definitions);
	}

修改限流规则方法:

/**
	 * 配置初始化的限流参数
	 * 用于指定资源的限流规则
	 * 		1.资源名称(yml文件中的路由id)
	 * 		2.配置统计时间- setIntervalSec
	 * 		3.配置限流阀值
	 */
	@PostConstruct
	public void initGatewayRules() {
		Set<GatewayFlowRule> rules = new HashSet<>();
		//路由限流
		/*rules.add(new GatewayFlowRule("product-service")
				.setCount(1)
				.setIntervalSec(1)
		);*/

		//自定义API限流分组
		rules.add(new GatewayFlowRule("product_api")
				.setCount(1)
				.setIntervalSec(1));



		GatewayRuleManager.loadRules(rules);
	}

5.限流规则配置类完整代码

package cn.itcast.gateway;

import com.alibaba.csp.sentinel.adapter.gateway.common.SentinelGatewayConstants;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiDefinition;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPathPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.ApiPredicateItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.api.GatewayApiDefinitionManager;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayParamFlowItem;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Configuration
public class GatewayConfiguration {

	private final List<ViewResolver> viewResolvers;

	private final ServerCodecConfigurer serverCodecConfigurer;

	public GatewayConfiguration(ObjectProvider<List<ViewResolver>> viewResolversProvider,
	                            ServerCodecConfigurer serverCodecConfigurer) {
		this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
		this.serverCodecConfigurer = serverCodecConfigurer;
	}

	/**
	 * 配置限流的异常处理器:SentinelGatewayBlockExceptionHandler
	 */
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
		return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
	}

	/**
	 * 配置限流过滤器
	 */
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE)
	public GlobalFilter sentinelGatewayFilter() {
		return new SentinelGatewayFilter();
	}

	/**
	 * 配置初始化的限流参数
	 * 用于指定资源的限流规则
	 * 		1.资源名称(yml文件中的路由id)
	 * 		2.配置统计时间- setIntervalSec
	 * 		3.配置限流阀值
	 */
	@PostConstruct
	public void initGatewayRules() {
		Set<GatewayFlowRule> rules = new HashSet<>();
		//路由限流
		/*rules.add(new GatewayFlowRule("product-service")
				.setCount(1)
				.setIntervalSec(1)
		);*/

		//自定义API限流分组
		rules.add(new GatewayFlowRule("product_api")
				.setCount(1)
				.setIntervalSec(1));



		GatewayRuleManager.loadRules(rules);
	}

	/**
	 * 自定义一个限流处理器,解决限流后提示信息"Blocked by Sentinel: ParamFlowException"不明确的问题
	 */
	@PostConstruct
	public void initBlockHandlers() {
		BlockRequestHandler blockRequestHandler= new BlockRequestHandler() {
			@Override
			public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
				HashMap<Object, Object> map = new HashMap<>();
				map.put("code","200");
				map.put("message","不好意思,限流了");
				return ServerResponse.status(HttpStatus.OK)
						.contentType(MediaType.APPLICATION_JSON_UTF8)
						.body(BodyInserters.fromObject(map));

			}
		};
		GatewayCallbackManager.setBlockHandler(blockRequestHandler);
	}

	/**
	 * 自定义API限流分组
	 * 		1.定义分组
	 * 		2.对小组配置限流规则
	 */
	@PostConstruct
	private void initCustomizedApis() {
		Set<ApiDefinition> definitions = new HashSet<>();
		ApiDefinition api1 = new ApiDefinition("product_api")
				.setPredicateItems(new HashSet<ApiPredicateItem>() {{
					add(new ApiPathPredicateItem().setPattern("/product-service/product/**").		//以/product-service/product/开头的所有url
							setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
				}});
		ApiDefinition api2 = new ApiDefinition("order_api")
				.setPredicateItems(new HashSet<ApiPredicateItem>() {{
					add(new ApiPathPredicateItem().setPattern("/order-service/order"));	//完全匹配/order-service/order的URL
				}});
		definitions.add(api1);
		definitions.add(api2);
		GatewayApiDefinitionManager.loadApiDefinitions(definitions);
	}
}

三.详情可下载学习文档:

学习文档下载

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-09-09 11:50:45  更:2021-09-09 11:51:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 20:26:14-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码