一:网管服务的网关策略
在上述中我们说明了网关的断言,过滤等网管服务的基本的机制。因此,我们整合了上述机制来讨论网关服务中的限流熔断和降级等网关策略。
二:熔断降级
1.业务场景:在传统的项目中,当访问一个路径出现不可访问比如404,浏览器不同在加载甚至在10几秒后才会反馈出404,这明
显对用户不友好,如果用户在加载404等还在不停的刷新当前网页将会导致后台不同的请求。这就需要我们做熔断降
级。
2.技术要点:在当前的网关服务中,熔断降级主要是使用hystrix来实现服务降级,当访问的内部url超过限定的时间救出自动出现。
3.代码说明:
yml:中的配置:
server:
port: 9999
spring:
profiles:
active: dev
application:
name: gateway-service
redis:
host: localhost
port: 6379
password: 123456
cloud:
gateway:
routes:
- id: hystrix_route
uri: http://localhost:8001/customFilter
predicates:
- Path=/test
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/defaultfallback
# hystrix 信号量隔离,3秒后自动超时
hystrix:
command:
default:
execution:
isolation:
strategy: SEMAPHORE
thread:
timeoutInMilliseconds: 3000
shareSecurityContext: true
@RestController
public class DefaultHystrixController {
@RequestMapping("/defaultfallback")
public Map<String,String> defaultfallback(){
System.err.println("服务降级中");
Map<String,String> map = new HashMap<>();
map.put("resultCode","fail");
map.put("resultMessage","服务异常");
map.put("resultObj","null");
return map;
}
}
说明改配置主要是氛围2各部分:第一部分设置路由(由locahost:9999/test 进入 http://localhost:8001/customFilter调用)以及配置熔断处理的跳转(自动转向 lcaohost:9999/defaultfallback)。第二部分配置熔断隔离。
4.在上一篇中我们使用了动态路由则路由的跳转以及隔离急需要普通配置中配置了,上面的yml只保留第二部分。
a.配置普通的路由:
访问localhost:9999/jd自动跳转到http://www.jd.com
b.配置带有熔断功能的路由
主要就是在filters中添加了一些熔断的跳转
5.说明,在网关中配置hystrix熔断和服务降级,可以处理大部分的服务调用异常,但是在某一些复杂的业务中需要我们单独使用
hystrix的熔断功能。
三:服务的限流机制
1.关于网关限流的算法请参考https://www.jb51.net/article/153008.htm,可以试着理解一下其中的多个算法。
2.基于全局变量的限流机制,这个是对于整个系统通用的一个限流方法主要实现GlobalFilter,Ordered(博客许多文章都是实现GlobalwayFilter明显在Finchley.RELEASE这个版本是没用的)重写filtrer。具体代码:
package com.springcloud.gateway.filters;
import java.time.Duration;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket;
import io.github.bucket4j.Bucket4j;
import io.github.bucket4j.Refill;
import reactor.core.publisher.Mono;
/**
* 全局过滤器
*
*
* @author monxz
*
* @date 2019年6月6日
*/
@Component
public class RequestGlobalFilter implements GlobalFilter,Ordered {
//执行顺序
@Override
public int getOrder() {
return 1;
}
/**
* 创建一个令牌桶
* @return
*/
private Bucket createNewBucket() {
Refill refill = Refill.of(1, Duration.ofSeconds(1));
Bandwidth limit = Bandwidth.classic(10, refill);
return Bucket4j.builder().addLimit(limit).build();
}
//执行逻辑
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String uri = request.getURI().toString();
//通过限制令牌桶中的token数量来进行限流
Bucket bucket = createNewBucket();
System.err.println("当前访问的uri:"+uri+",令牌桶中token个数:"+bucket.getAvailableTokens());
if (bucket.tryConsume(1)) {
return chain.filter(exchange);
} else {
//当可用的令牌书为0是,进行限流返回429状态码
exchange.getResponse().setStatusCode(HttpStatus.TOO_MANY_REQUESTS);
return exchange.getResponse().setComplete();
}
}
}
3.动态管理限流机制
在gateway的一些项目中使用了redis-lemiter的方式进行整合redis限流,这种限流方式重写难度较大,因此我们自行来整合redis
来动态切换限流方式,并且通过redis和mysql来存存储限流的机制。