栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringCloud之GateWay网关

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringCloud之GateWay网关

目录

1.  概念

2. 案例 

2.1 路由规则

2.2 动态路由

2.3 重写转发路径

2.4 默认的路由规则

2.5 过滤器

2.5.1 局部过滤器

2.5.2 全局过滤器

3. 统一鉴权

4. 网关限流

4.1 常见的限流算法

4.2 基于Filter的限流

4.3 基于Sentinel的限流


Spring Cloud Gateway 作为 Spring Cloud 生态系中的网关,目标是替代 Netflix ZUUL,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。它是基 于Nttey的响应式开发模式 

组件RPS(request per second)
Spring Cloud GatewayRequests/sec: 32213.38
Zuul 1.XRequests/sec: 20800.13

1.  概念

1. 路由(route) 路由是网关最基础的部分,路由信息由一个ID、一个目的URL、一组断言工厂和一 组Filter组成。如果断言为真,则说明请求URL和配置的路由匹配。

2. 断言(predicates) Java8中的断言函数,Spring Cloud Gateway中的断言函数输入类型是 Spring5.0框架中的ServerWebExchange。Spring Cloud Gateway中的断言函数允许开发者去定 义匹配来自Http Request中的任何信息,比如请求头和参数等。

3. 过滤器(filter) 一个标准的Spring webFilter,Spring Cloud Gateway中的Filter分为两种类型, 分别是Gateway Filter和Global Filter。过滤器Filter可以对请求和响应进行处理。

2. 案例 

(1) 创建工程导入依赖


    org.springframework.cloud
    spring-cloud-starter-gateway

注意   SpringCloud Gateway使用的web框架为webflux,和SpringMVC不兼容。引入的限流组件是 hystrix。redis底层不再使用jedis,而是lettuce。

(2) 配置启动类

@SpringBootApplication
public class GatewayServerApplication {
public static void main(String[] args) {
    SpringApplication.run(GatewayServerApplication.class, args);
    }
}

(3) 编写配置文件

server:
  port: 8080 #服务端口
spring:
  application:
    name: api-gateway #指定服务名
  cloud:
    gateway:
      routes:
        - id: product-service   #路由ID
        uri: http://192.168.1.1:9001  #目标服务地址
        predicates:
        - Path=/product-service
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if(StringUtils.isBlank(token)){
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    
    @Override
    public int getOrder() {
        return 1;
    }
}

4. 网关限流

4.1 常见的限流算法

(1) 计数器

计数器限流算法是最简单的一种限流实现方式。其本质是通过维护一个单位时间内的计数器,每次请求计数器加1,当单位时间内计数器累加到大于设定的阈值,则之后的请求都被拒绝,直到单位时间已经过去,再将计数器重置为零

 (2) 漏桶算法

漏桶算法可以很好地限制容量池的大小,从而防止流量暴增。漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。 在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量。

为了更好的控制流量,漏桶算法需要通过两个变量进行控制:一个是桶的大小,支持流量突发增多时可 以存多少的水(burst),另一个是水桶漏洞的大小(rate)。

 (3) 令牌桶算法

令牌桶算法是对漏桶算法的一种改进,桶算法能够限制请求调用的速率,而令牌桶算法能够在限制调用的平均速率的同时还允许一定程度的突发调用。在令牌桶算法中,存在一个桶,用来存放固定数量的令牌。算法中存在一种机制,以一定的速率往桶中放令牌。每次请求调用需要先获取令牌,只有拿到令牌,才有机会继续执行,否则选择选择等待可用的令牌、或者直接拒绝。放令牌这个动作是持续不断的进行,如果桶中令牌数达到上限,就丢弃令牌,所以就存在这种情况,桶中一直有大量的可用令牌,这时进来的请求就可以直接拿到令牌执行,比如设置qps为100,那么限流器初始化完成一秒后,桶中就已经有100个令牌了,这时服务还没完全启动好,等启动完成对外提供服务时,该限流器可以抵挡瞬时 的100个请求。所以,只有桶中没有令牌时,请求才会进行等待,最后相当于以一定的速率执行。

4.2 基于Filter的限流

 (1) 环境搭建


    org.springframework.cloud
    spring-cloud-starter-gateway


    org.springframework.boot
    spring-boot-starter-data-redis-reactive

(2)准备rediss设备 

(3) 修改application.yml配置文件

spring:
  application:
    name: api-gateway #指定服务名
  cloud:
    gateway:
      routes:
      - id: product-service
        uri: lb://service-product  #根据微服务名从注册中心拉取微服务请求路径
        predicates:
        - Path=/product-service
    @Bean
    public KeyResolver pathKeyResolver() {
        return new KeyResolver() {
            @Override
            public Mono resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getPath().toString());
            }
        };
    }
    
    //@Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(
                exchange.getRequest().getHeaders().getFirst("X-Forwarded-For")
        );
    }
    
    //@Bean
    public KeyResolver userKeyResolver() {
        return exchange -> Mono.just(
                exchange.getRequest().getQueryParams().getFirst("token")
        );
    }
}

4.3 基于Sentinel的限流

Sentinel 支持对 Spring Cloud Gateway、Zuul 等主流的 API Gateway 进行限流。

GatewayFlowRule :网关限流规则,针对 API Gateway 的场景定制的限流规则,可以针对不同 route 或自定义的 API 分组进行限流,支持针对请求中的参数、Header、来源 IP 等进行定制化的 限流。

ApiDefinition :用户自定义的 API 定义分组,可以看做是一些 URL 匹配的组合。比如我们可以 定义一个 API 叫 my_api ,请求 path 模式为 /foo @Configuration public class GatewayConfiguration { private final List viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public GatewayConfiguration(ObjectProvider> viewResolversProvider, ServerCodecConfigurer serverCodecConfigurer) { this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList); this.serverCodecConfigurer = serverCodecConfigurer; } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() { return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer); } @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public GlobalFilter sentinelGatewayFilter() { return new SentinelGatewayFilter(); } @PostConstruct public void initGatewayRules() { Set rules = new HashSet<>(); rules.add(new GatewayFlowRule("product-service") .setCount(1) //一秒内阈值为1 .setIntervalSec(1) ); // rules.add(new GatewayFlowRule("product_api") // .setCount(1).setIntervalSec(1) // ); GatewayRuleManager.loadRules(rules); } @PostConstruct private void initCustomizedApis() { Set definitions = new HashSet<>(); ApiDefinition api1 = new ApiDefinition("product_api") .setPredicateItems(new HashSet() {{ add(new ApiPathPredicateItem().setPattern("/product-service/product @PostConstruct public void initBlockHandlers() { BlockRequestHandler blockHandler = new BlockRequestHandler() { public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) { Map map = new HashMap(); map.put("code",001); map.put("message","不好意思,限流啦"); return ServerResponse.status(HttpStatus.OK) .contentType(MediaType.APPLICATION_JSON_UTF8) .body(BodyInserters.fromObject(map)); } }; GatewayCallbackManager.setBlockHandler(blockHandler); } }

(3)网关配置

spring:
  application:
    name: api-gateway #指定服务名
  cloud:
    gateway:
      routes:
      - id: product-service
        uri: lb://service-product  #根据微服务名从注册中心拉取微服务请求路径
        predicates:
        - Path=/product-service
	@PostConstruct
	public void initBlockHandlers() {
		BlockRequestHandler blockHandler = new BlockRequestHandler() {
			public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
				Map map = new HashMap();
				map.put("code",001);
				map.put("message","不好意思,限流啦");
				return ServerResponse.status(HttpStatus.OK)
						.contentType(MediaType.APPLICATION_JSON_UTF8)
						.body(BodyInserters.fromObject(map));
			}
		};
		GatewayCallbackManager.setBlockHandler(blockHandler);
	}

(5) 参数限流

上面的配置是针对整个路由来限流的,如果我们只想对某个路由的参数做限流,那么可以使用参数限流 方式:

    
	@PostConstruct
	public void initGatewayRules() {
		Set rules = new HashSet<>();
		//rules.add(new GatewayFlowRule("product-service")
		//		.setCount(1)   //一秒内阈值为1
		//		.setIntervalSec(1)  
		//);
		rules.add(new GatewayFlowRule("product_api")
			.setCount(1).setIntervalSec(1)
		);


		GatewayRuleManager.loadRules(rules);
	}

(6) 自定义API分组

	
	@PostConstruct
	private void initCustomizedApis() {
		Set definitions = new HashSet<>();
		ApiDefinition api1 = new ApiDefinition("product_api")
				.setPredicateItems(new HashSet() {{
					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() {{
					add(new ApiPathPredicateItem().setPattern("/order-service/order")); //完全匹配/order-service/order 的url
				}});
		definitions.add(api1);
		definitions.add(api2);
		GatewayApiDefinitionManager.loadApiDefinitions(definitions);
	}

上一页                 下一页

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/276751.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号