Sentinel学习

一、简介

1.sentinel主要功能是微服务的限流、熔断、降级。相比与hystrix它提供了更为完善的控制台、流量整形、系统负载保护。
2.sentinel中重要的两个概念:资源(被限流或者降级的代码)、规则(具体限流或者降级触发的条件)

二、使用

1.引入依赖

 <dependency>
     <groupId>com.alibaba.cloud</groupId>
     <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
     <version>1.8.4</version>
 </dependency>

如果是在web层的接口,因为引入的sentinel依赖中对springmvc框架有扩展,它会自动将接口识别为资源,如果是在service中使用如下,主要通过 @SentinelResource注解标注代码成为资源。

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    @Override
    @SentinelResource(value = "getUser",blockHandler = "handleException")
    public UserEntity getById(Integer id) {
        return userDao.getById(id);
    }
    public UserEntity handleException(Integer id, BlockException ex) {
        UserEntity userEntity = new UserEntity();
        userEntity.setUsername("===被限流降级啦===");
        return userEntity;
    }
}

三、原理

原理简介: sentinel实际上是对被定义为资源的代码前后进行增强。当请求第一次访问资源时(针对springmvc接口的资源),会初始化Sph sph = new CtSph()对象。
1.BIO的方式开启一个端口,这个端口会用来接受控制台发送的请求
2.会开启心跳检测任务,这个任务会携带客户端的信息(包含但不仅限于IP、Port)发送到sentinel控制台
3.会初始化一个slotchain用来检验请求是否满足各种规则。
在这里插入图片描述
上图是整体的通信流程,下面是整体的数据流程
在这里插入图片描述
sentinel的持久化
通过这个流程图我们能发现一个问题,就是规则都保存在客户端。一旦我们微服务重启或者如果我们的微服务是分布式部署,那么配置的规则就会丢失或者只存在其中一台机器上。那么sentinel的规则持久化就是很有必要的。
1.下面介绍使用nacos作为配置持久化的流程。
在这里插入图片描述
上面这种模式存在的问题:
1.sentinel控制台修改的配置不会同步修改到nacos。
2.微服务端(sentinel客户端)通过代码定义的规则不会推到nacos
所以需要扩展对nacos的写功能
在这里插入图片描述

四、sentinel规则中用到的几种算法

1.时间滑动窗口
在这里插入图片描述
代码实现:

/**
 * 滑动时间窗口限流实现
 * 假设某个服务最多只能每秒钟处理100个请求,我们可以设置一个1秒钟的滑动时间窗口,
 * 窗口中有10个格子,每个格子100毫秒,每100毫秒移动一次,每次移动都需要记录当前服务请求的次数
 */
public class SlidingTimeWindow {
    //服务访问次数,可以放在Redis中,实现分布式系统的访问计数
    Long counter = 0L;
    //使用LinkedList来记录滑动窗口的10个格子。
    LinkedList<Long> slots = new LinkedList<Long>();
    public static void main(String[] args) throws InterruptedException {
        SlidingTimeWindow timeWindow = new SlidingTimeWindow();
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    timeWindow.doCheck();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        while (true){
            //TODO 判断限流标记
            timeWindow.counter++;
            Thread.sleep(new Random().nextInt(15));
        }
    }

    private void doCheck() throws InterruptedException {
        while (true) {
            slots.addLast(counter);
            if (slots.size() > 10) {
                slots.removeFirst();
            }
            //比较最后一个和第一个,两者相差100以上就限流
            if ((slots.peekLast() - slots.peekFirst()) > 100) {
                System.out.println("限流了。。");
                //TODO 修改限流标记为true
            }else {
                //TODO 修改限流标记为false
            }
            Thread.sleep(100);
        }
    }
}

2.漏桶算法
水的流出速度是固定的,流入速度不限制。相当于有大量请求进来,但是处理请求的速度是固定的。
在这里插入图片描述
代码实现:

/**
 * 漏桶限流算法
 */
public class LeakyBucket {
        public long timeStamp = System.currentTimeMillis();  // 当前时间
        public long capacity; // 桶的容量
        public long rate; // 水漏出的速度(每秒系统能处理的请求数)
        public long water; // 当前水量(当前累积请求数)

        public boolean limit() {
            long now = System.currentTimeMillis();
            water = Math.max(0, water - ((now - timeStamp)/1000) * rate); // 先执行漏水,计算剩余水量
            timeStamp = now;
            if ((water + 1) < capacity) {
                // 尝试加水,并且水还未满
                water += 1;
                return true;
            } else {
                // 水满,拒绝加水
                return false;
        }
    }
}

3.令牌桶算法
将令牌用固定速率放入桶中,每个请求想要通过都必须持有令牌。相当于限制了最高的请求数,但是过程中可变。
在这里插入图片描述
代码实现:

/**
 * 令牌桶限流算法
 */
public class TokenBucket {
    public long timeStamp = System.currentTimeMillis();  // 当前时间
    public long capacity; // 桶的容量
    public long rate; // 令牌放入速度
    public long tokens; // 当前令牌数量

    public boolean grant() {
        long now = System.currentTimeMillis();
        // 先添加令牌
        tokens = Math.min(capacity, tokens + (now - timeStamp) * rate);
        timeStamp = now;
        if (tokens < 1) {
            // 若不到1个令牌,则拒绝
            return false;
        } else {
            // 还有令牌,领取令牌
            tokens -= 1;
            return true;
        }
    }
}

4.longadder原子累加器
在这里插入图片描述

原子累加器中重要的三个变量,在没有线程并发时使用base进行计数累加。在有并发时使用cells单独统计每个线程的累加。cellsBusy主要是为了用来标记cells是否有其它线程创建。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值