Sentinel授权规则和规则持久化

大家好我是苏麟 , 今天说说Sentinel规则持久化.

授权规则

授权规则可以对请求方来源做判断和控制。

授权规则

基本规则

授权规则可以对调用方的来源做控制,有白名单和黑名单两种方式。

  • 白名单:来源(origin)在白名单内的调用者允许访问
  • 黑名单:来源(origin)在黑名单内的调用者不允许访问

授权规则:

  • 资源名:就是受保护的资源,例如/order/{orderId}
  • 流控应用:是来源者的名单
  1. 如果是勾选白名单,则名单中的来源被许可访问。
  2. 如果是勾选黑名单,则名单中的来源被禁止访问。

比如:

我们允许请求从gateway到order-service,不允许浏览器访问order-service,那么白名单中就要填写网关的来源名称(origin)。

如何获取origin

Sentinel是通过RequestOriginParser这个接口的parseOrigin来获取请求的来源的。

java 复制代码
public interface RequestOriginParser {
    /**
     * 从请求request对象中获取origin,获取方式自定义
     */
    String parseOrigin(HttpServletRequest request);
}
复制代码
这个方法的作用就是从request对象中,获取请求者的origin值并返回。

默认情况下,sentinel不管请求者从哪里来,返回值永远是default,也就是说一切请求的来源都被认为 是一样的值default。

因此,我们需要自定义这个接口的实现,让不同的请求,返回不同的origin

例如order-service服务中,我们定义一个RequestOriginParser的实现类:

java 复制代码
package cn.itcast.order;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.RequestOriginParser;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;

@Component
public class HeaderOriginParser implements RequestOriginParser {
    @Override
    public 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:

java 复制代码
spring:
  cloud:
    gateway:
      default-filters: 
        - AddRequestHeader=origin,gateway

这样,从gateway路由的所有请求都会带上origin头,值为gateway。而从其它地方到达微服务的请求则 没有这个头。

配置授权规则

接下来,我们添加一个授权规则,放行origin值为gateway的请求。

现在,我们直接跳过网关,访问order-service服务:

通过网关访问:

自定义异常结果

默认情况下,发生限流、降级、授权拦截时,都会抛出异常到调用方。异常结果都是flow limmiting(限流)。这样不够友好,无法得知是限流还是降级还是授权拦截。

异常类型

而如果要自定义异常时的返回结果,需要实现BlockExceptionHandler接口:

java 复制代码
public interface BlockExceptionHandler {
    /**
     * 处理请求被限流、降级、授权拦截时抛出的异常:BlockException
     */
    void handle(HttpServletRequest request, HttpServletResponse response,
                BlockException e) throws Exception;
}

这个方法有三个参数:

  • HttpServletRequest request:request对象
  • HttpServletResponse response:response对象
  • BlockException e:被sentinel拦截时抛出的异常

这里的BlockException包含多个不同的子类:

自定义异常处理

下面,我们就在order-service定义一个自定义异常处理类:

java 复制代码
package cn.itcast.order;

import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@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 + "}");
    }
}

重启测试,在不同场景下,会返回不同的异常消息.

限流:

授权拦截时:

规则持久化

现在,sentinel的所有规则都是内存存储,重启后所有规则都会丢失。在生产环境下,我们必须确保这 些规则的持久化,避免丢失。

规则管理模式

规则是否能持久化,取决于规则管理模式,sentinel支持三种规则管理模式:

  • 原始模式:Sentinel的默认模式,将规则保存在内存,重启服务会丢失。
  • pull模式
  • push模式
pull模式

pull模式:控制台将配置的规则推送到Sentinel客户端,而客户端会将配置规则保存在本地文件或数据库 中。以后会定时去本地文件或数据库中查询,更新本地规则

push模式

push模式:控制台将配置规则推送到远程配置中心,例如Nacos。Sentinel客户端监听Nacos,获取配 置变更的推送消息,完成本地配置更新。

实现push模式

sentinel规则持久化.pdf (gitee.com)

这期就到这里 , 下期见 !

相关推荐
杰克尼1 小时前
天机学堂复习总结(day03-day04)
java·开发语言·redis·elasticsearch·spring cloud
武子康3 小时前
Java-07 深入浅出 MyBatis数据库一对多关系模型实战:表结构设计与查询实现
java·后端
花椒技术3 小时前
企业内部 Agent 落地复盘:Gateway、Skill 和二次确认如何串起受控业务执行
后端·agent·ai编程
我是一颗柠檬5 小时前
【MySQL全面教学】MySQL事务与ACID Day9(2026年)
数据库·后端·mysql
枕星而眠5 小时前
数据结构八大排序详解(一):四大简单排序
c语言·数据结构·c++·后端
IT_陈寒5 小时前
React useEffect闭包陷阱差点把我整失业了
前端·人工智能·后端
苍何6 小时前
爆肝两周,我把 Codex 最全实战指南开源了
后端
苏渡苇6 小时前
服务容错的必要性与Spring Cloud Alibaba Sentinel 限流配置实战
spring boot·spring cloud·sentinel
bug菌6 小时前
【SpringBoot 3.x 第254节】夯爆了,数据库访问性能优化实战详解!
数据库·spring boot·后端
Rust研习社6 小时前
从碎片化到标准化:cargo-bp 如何重构 Rust 开发逻辑
后端·rust·编程语言