概述
除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。由于调用关系的复杂性,如果调用链路中的某个资源不稳定,最终会导致请求发生堆积。
Sentinel 熔断降级会在调用链路中某个资源出现不稳定状态时(例如调用超时或异常比例升高),对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联错误。当资源被降级后,在接下来的降级时间窗口之内,对该资源的调用都自动熔断(默认行为是抛出 DegradeException)。
概述
何为热点?热点即经常访问的数据。比如:
商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制。
用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制。
热点参数限流会统计传入参数中的热点数据,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。其中,Sentinel会利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。
第一步:在sca-provider中添加如下方法,例如:
//http://localhost:8081/provider/doFindById?id=10
@GetMapping("/doFindById")
@SentinelResource("resource")//aop 切入点
public String doFindById(@RequestParam Integer id){
return "Get Resource By"+id;
}
概述
系统在生产环境运行过程中,我们经常需要监控服务器的状态,看服务器CPU、内存、IO等的使用率;主要目的就是保证服务器正常的运行,不能被某些应用搞崩溃了;而且在保证稳定的前提下,保持系统的最大吞吐量。
快速入门
Sentinel的系统保护规则是从应用级别的入口流量进行控制,从单台机器的总体 Load(负载)、RT(响应时间)、入口 QPS 、线程数和CPU使用率五个维度监控应用数据,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。如图所示:
说明,系统保护规则是应用整体维度的,而不是资源维度的,并且仅对入口流量生效。入口流量指的是进入应用的流量(EntryType.IN),比如 Web 服务。
如何理解sentinel中的系统规则?(是对所有链路的控制规则,是一种系统保护策略)
Sentinel的常用系统规则有哪些?(RT,QPS,CPU,线程,Load-linux,unix)
Sentinel系统保护规则被触发以后底层会抛出什么异常?(SystemBlockException)
概述
很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的黑白名单控制的功能。黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。例如微信中的黑名单。
快速入门
sentinel可以基于黑白名单方式进行授权规则设计,如图所示:
@Component
public class DefaultRequestOriginParser implements RequestOriginParser {
/*
parseOrigin: 此方法用于获取请求数据,具体数据,由具体业务所需决定
这个方法的返回值会与授权规则中黑白名单进行比对,黑名单中不可访问我们系统资源
*/
@Override
public String parseOrigin(HttpServletRequest request) {
//基于请求参数,进行黑白名单设计
String origin = request.getParameter("origin");//获取请求参数
return origin;
}
}
String ip= request.getRemoteAddr();
System.out.println("ip="+ip);
return ip;
网关本质上要提供一个各种服务访问的入口,并提供服务接收并转发所有内外部的客户端调用,还有就是权限认证,限流控制等等。
性能强劲:是第一代网关Zuul的1.6倍。
功能强大:内置了很多实用的功能,例如转发、监控、限流等
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-gatewayartifactId>
dependency>
server:
port: 9000
spring:
application:
name: sca-gateway #没有向nacos中心注册,可以不写
cloud:
gateway: #网关配置
routes: #路由配置(routes下可有多个路由 ,id作为唯一标示)
- id: route01
uri: http://localhost:8081/ #请求转发路径
predicates: #谓词判断逻辑(定义请求转发条件,谓词所有条件满足才会执行请求转发)
- Path=/nacos/provider/echo/** #nacos前缀,服务保护
filters: #局部过滤器,针对于当前路由进行设计谓词返回值都为true则执行这里的filters
- StripPrefix=1 #去除前缀过滤器,这里1表示去掉Path中第一层目录 nacos
依次启动sca-provider,sca-gateway服务,然后打开浏览器,进行访问测试
1.什么是网关?服务访问(流量)的一个入口,类似生活中的“海关“
2.为什么使用网关?(服务安全,统一服务入口管理,负载均衡,限流,鉴权)
3.Spring Cloud Gateway 应用的初始构建过程(添加依赖,配置)
4.Gateway 服务的启动底层是通过谁去实现的?(Netty网络编程框架-ServerSocket)
5.Gateway 服务做请求转发时一定要在注册中心进行注册吗?(不一定,可以直接通过远端url进行服务访问)
网关才是服务访问的入口,所有服务都会在网关层面进行底层映射,所以在访问服务时,要基于服务serivce id(服务名)去查找对应的服务,让请求从网关层进行均衡转发,以平衡服务实例的处理能力。
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
客户端向Spring Cloud Gateway发出请求。 如果Gateway Handler Mapping 通过谓词predicates(predicates)的集合确定请求与路由(Routers)匹配,则将其发送到Gateway Web Handler。 Gateway Web Handler 基于路由配置调用过滤链中的过滤器(也就是所谓的责任链模式)进一步的处理请求。 Filter由虚线分隔的原因是, Filter可以在发送请求之前和之后执行拓展逻辑。基于官方的处理流程,进行源码分析如下:
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-Foo, Bar #原始请求添加名为 X-Request-Foo ,值为 Bar 的请求头
- AddRequestParameter=foo, bar #为原始请求添加名为foo,值为bar的参数,即:foo=bar
-
全局过滤器(GlobalFilter)作用于所有路由, 无需配置。在系统初始化时加载,并作用在每个路由上。通过全局过滤器可以实现对权限的统一校验,安全性验证等功能。一般内置的全局过滤器已经可以完成大部分的功能,但是对于企业开发的一些业务功能处理,还是需要我们 自己编写过滤器来实现的,那么我们一起通过代码的形式自定义一个过滤器,去完成统一的权限校验。 例如,当客户端第一次请求服务时,服务端对用户进行信息认证(登录), 认证通过,将用户信息进行加密形成token,返回给客户端,作为登录凭证 以后每次请求,客户端都携带认证的token 服务端对token进行解密,判断是否有效。学过spring中的webflux技术的同学可以对如下代码进行尝试实现(没学过的可以忽略).
@Component
public class AuthGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String username = request.getQueryParams().getFirst("username");
if (!"admin".equals(username)){
System.out.println("认证失败");
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
网关是所有外部请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,我们采用Sentinel组件来实现网关的限流。Sentinel支持对SpringCloud Gateway、Zuul等主流网关进行限流。参考网址如下:
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-sentinelartifactId>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-sentinel-gatewayartifactId>
dependency>
启动时,添加sentinel的jvm参数,通过此菜单可以让网关服务在sentinel控制台显示不一样的菜单,代码如下。
-Dcsp.sentinel.app.type=1
自定义API分组,是一种更细粒度的限流规则定义,它允许我们利用sentinel提供的API,将请求路径进行分组,然后在组上设置限流规则即可。
定义配置类,设计流控返回值,代码如下:
@Component
public class GatewayConfig {
public GatewayConfig(){
GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String,Object> map=new HashMap<>();
map.put("state",429);
map.put("message","two many request");
String jsonStr = JSON.toJSONString(map);//序列化
return ServerResponse.ok().body(Mono.just(jsonStr), String.class);
}
});
}
}