05--springCloudAlibab SpringMVC集成sentinel

sentinel手册

第三章 创建了生产者。以生产者为例集成sentinel

  1. 引入sentinel开发包
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
  1. 重写RequestOriginParser 设置请求来源(示例中已客户端ip作为来源)
package com.cloud.alibaba.config;

import com.alibaba.csp.sentinel.adapter.servlet.callback.RequestOriginParser;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;

/**
 * @author 刘志强
 * @date 2020/9/24 16:51
 */
@Component
public class MyRequestOriginParser implements RequestOriginParser {

    @Override
    public String parseOrigin(HttpServletRequest request) {
        // 从header中获取名为 origin 的参数并返回
        String ip = getIpAddr(request);
        return ip;
    }

    /**
     * 获取ip
     *
     * @param request
     * @return
     */
    private String getIpAddr(HttpServletRequest request) {
        if (request == null) {
            return "unknown";
        }
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Forwarded-For");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }

        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }

        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
    }
}


  1. 覆盖 DefaultUrlBlockHandler 异常处理器处理器
package com.cloud.alibaba.config;

import com.alibaba.csp.sentinel.adapter.servlet.callback.UrlBlockHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author 刘志强
 * @date 2020/9/24 16:51
 */
public class MyUrlBlockHandler implements UrlBlockHandler {

    public MyUrlBlockHandler() {
    }

    @Override
    public void blocked(HttpServletRequest request, HttpServletResponse response, BlockException ex) throws IOException {
        if (AuthorityException.isBlockException(ex)) {
            Map<String,Object> map = new HashMap(2);
            map.put("code",500);
            map.put("msg","被sentinel拦截");
            writer(request,response,map);
        }
    }

    public static boolean writer(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Map map ) {
        PrintWriter writer = null;
        String originHeader = httpServletRequest.getHeader("Origin");
        httpServletResponse.setHeader("Access-Control-Allow-Origin", originHeader);
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.addHeader("Access-Control-Allow-Credentials", "true");
        httpServletResponse.addHeader("Vary", "Origin");
        httpServletResponse.setContentType("application/json; charset=utf-8");
        try {
            JSONObject jsonObject = (JSONObject) JSON.toJSON(map);
            writer = httpServletResponse.getWriter();
            writer.append(jsonObject.toString());
        } catch (IOException e) {
            System.out.println("response error" + e);
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
        return false;
    }
}


  1. 将异常处理器添加至WebCallbackManager中
package com.cloud.alibaba.config;

import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author 刘志强
 * @date 2020/9/27 09:16
 */

@Configuration
public class SentinelConfig {

    @Bean
    public MyUrlBlockHandler webCallbackManager() {
        MyUrlBlockHandler myUrlBlockHandler = new MyUrlBlockHandler();
        WebCallbackManager.setUrlBlockHandler(myUrlBlockHandler);
        return myUrlBlockHandler;
    }
}

  1. bootstrap.yml 增加sentinel 配置
spring:
  cloud:
    sentinel:
      # 取消控制台懒加载
      eager: true
      # sentinel 地址
      transport:
        dashboard: 101.37.152.195:8858
        port: 8719
      #将sentinel配置信息持久化到nacos 熔断规则
      datasource:
        ds1:
          ## 从nacos中读取限流配置
          nacos:
            server-addr: 101.37.152.195:8848
            dataId: consumer-example-flow
            groupId: DEFAULT_GROUP
            data-type: json
            ## flow 流控规则 degrade 降级规则 system 系统规则 authority 授权规则 param-flow 热点规则
            rule-type: flow
  1. nacos 增加sentinel配置
Data ID: consumer-example-flow
Group: DEFAULT_GROUP
配置格式: JSON
配置内容:
  [
    {
      "resource": "/getUserNameTwo",
      "limitApp": "192.168.1.25",
      "grade": 1,
      "count": 1,
      "strategy": 0,
      "controlBehavior": 0,
      "clusterMode": false
    },
    {
      "resource": "/getUserName",
      "limitApp": "default",
      "grade": 1,
      "count": 10,
      "strategy": 0,
      "controlBehavior": 0,
      "clusterMode": false
    }
  ]
  1. /getUserNameTwo 接口针对 ip 192.168.1.25 的来源进行限流 QPS 为1
  2. /getUserName 接口 针对所由的来源进行限流 QPS 为10
  3. 启动项目使用postman 等工具测试接口
  4. 在正式的场景中。我们可以把可疑的ip放入缓存中。然后将来源设置为正常状态和异常状态。在自定义来源方法中如果请求来源是缓存中的可疑ip。将来源设置为异常状态。黑名单规则里的来源应用设置为异常状态
限流规则
  [
    {
      "resource": "/swagger-ui.html", // 资源名称
      "limitApp": "192.168.1.25", // 来源应用 default 不区分调用者
      "grade": 1, // 阀值类型,0表示线程数,1表示QPS
      "count": 1, // 单机阀值
      "strategy": 0, // 流控模式,0表示直接,1表示关联,2表示链路
      "controlBehavior": 0, // 流控效果,0表示快速失败,1表示Warm UP,2表示排队等待
      "clusterMode": false // 是否集群
    }
  ]
  // 192.168.1.25来源的请求 qps 为 1(每秒的查询数1次) 
降级规则
  [
    {
      "resource": "/swagger-ui.html", // 资源名称
      "count": 3, // 最大Rt(ms)(平均响应时间 ) 比例阀值 异常数 
      "grade": 0, // 熔断策略 0 RT 1 异常比例 2 异常数
      "timeWindow": 10, // 熔断时长S 10秒后回复
    }
  ]
  // 一秒内进来n个请求,平均响应时长均超过rt。对此接口进行熔断降级。10秒后恢复
热点规则

黑白名单
  [
    {
      "resource": "/swagger-ui.html",  // 资源名称
      "limitApp": "192.168.1.25,127.0.0.1", //  对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appB
      "strategy": 1 // 限流模式 0 白名单 1 黑名单
    }
  ]
  // 192.168.1.25 和 127.0.0.1 的来源禁止请求
源码地址
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值