默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。异常结果都是 flow limmiting(限流)。这样不够友好,无法得知是限流还是降级还是授权拦截。
基本规则
授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式。
- 白名单:来源(origin)在白名单内的调用者允许访问
- 黑名单:来源(origin)在黑名单内的调用者不允许访问
点击左侧菜单的授权,可以看到授权规则:

- 资源名:就是受保护的资源,例如 /order/{orderId}
- 流控应用:是来源者的名单,
- 如果是勾选白名单,则名单中的来源被许可访问。
- 如果是勾选黑名单,则名单中的来源被禁止访问。
我们允许请求从 gateway 到 order-service,不允许浏览器访问 order-service,那么白名单中就要填写网关的来源名称(origin)。
如何获取 origin
Sentinel 是通过 RequestOriginParser 这个接口的 parseOrigin 来获取请求的来源的。
public interface RequestOriginParser {/*** 从请求request对象中获取origin,获取方式自定义*/String parseOrigin(HttpServletRequest request);}
这个方法的作用就是从 request 对象中,获取请求者的 origin 值并返回。
默认情况下,sentinel 不管请求者从哪里来,返回值永远是 default,也就是说一切请求的来源都被认为是一样的值 default。
因此,我们需要自定义这个接口的实现,让不同的请求,返回不同的 origin。
例如 order-service 服务中,我们定义一个 RequestOriginParser 的实现类:
@Componentpublic class HeaderOriginParser implements RequestOriginParser {@Overridepublic String parseOrigin(HttpServletRequest request) {// 1.获取请求头String origin = request.getHeader("origin");// 2.非空判断if (StringUtils.isEmpty(origin)) {origin = "blank";}return origin;}}
我们会尝试从 request-header 中获取 origin 值。
给网关添加请求头
既然获取请求 origin 的方式是从 reques-header 中获取 origin 值,我们必须让所有从 gateway 路由到微服务的请求都带上origin头。
这个需要利用之前学习的一个 GatewayFilter 来实现,AddRequestHeaderGatewayFilter。
修改 gateway 服务中的 application.yml,添加一个 defaultFilter:
spring:cloud:gateway:default-filters:- AddRequestHeader=origin,gatewayroutes:# ...略
这样,从 gateway 路由的所有请求都会带上 origin 头,值为 gateway。而从其它地方到达微服务的请求则没有这个头。
配置授权规则
接下来,我们添加一个授权规则,放行 origin 值为 gateway 的请求。

自定义异常结果
默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。异常结果都是 flow limmiting(限流)。这样不够友好,无法得知是限流还是降级还是授权拦截。
异常类型
而如果要自定义异常时的返回结果,需要实现 BlockExceptionHandler 接口:
public interface BlockExceptionHandler {
/**
* 处理请求被限流、降级、授权拦截时抛出的异常:BlockException
*/
void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception;
}
这个方法有三个参数:
HttpServletRequest request:request 对象HttpServletResponse response:response 对象BlockException e:被 sentinel 拦截时抛出的异常
这里的 BlockException 包含多个不同的子类:
| 异常 | 说明 |
|---|---|
FlowException |
限流异常 |
ParamFlowException |
热点参数限流的异常 |
DegradeException |
降级异常 |
AuthorityException |
授权规则异常 |
SystemBlockException |
系统规则异常 |
自定义异常处理
@Component
public class SentinelExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
String msg = "未知异常";
int status = 429;
if (e instanceof FlowException) {
msg = "请求被限流了";
} else if (e instanceof ParamFlowException) {
msg = "请求被热点参数限流";
} else if (e instanceof DegradeException) {
msg = "请求被降级了";
} else if (e instanceof AuthorityException) {
msg = "没有权限访问";
status = 401;
}
response.setContentType("application/json;charset=utf-8");
response.setStatus(status);
response.getWriter().println("{\"msg\": " + msg + ", \"status\": " + status + "}");
}
}
重启测试,在不同场景下,会返回不同的异常消息。
