好久没有写博客了,这几天调研了阿里开源的sentinel限流工具,据说双十一采用的也是此功能,调研了几天遇到了不少坑,主要集成一下,便于大家了解。

sentinel的原理这里不介绍,为何要使用zookeeper来说一下,不使用zookeeper这些配置中心的话相当于直接通过dashboard调用server端,这样每次的限流配置只是在java的内存中生效,在项目重启之后,信息就丢失了,所以需要一个数据源去存储这些信息,因为我们原来的项目中使用了zookeeper,所以这里介绍些zookeeper的使用

 

首先说下server端,在pom下引入sentinel的集成包

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

注意版本号,springboot2.0以上要用2.X的版本,引用此dependency之后不需要按照官网上在去引用其他jar包,此包下包含的信息包括如下包

此处有两个坑

1.结合sentinel自带的dashboard在使用时必须和使用的版本一直,如上图中为1.7.0版本,则dashboard也必须为1.7.0,否则点击规则调用会报错

2.还有一个更深的坑是fastjson的版本也必须一致,否则点击规则后会不生效,也没有错误提示....sentinel的版本是1.2.62。如果不希望修改自己引用fastjson版本号,需要下载dashboard的源码修改fastjson版本,版本必须一致才可以

使用zookeeper的时候需要引入

<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-datasource-zookeeper</artifactId>
	<version>1.7.0</version>
</dependency>

此处也需要注意保持版本号一致

spring-cloud-starter-alibaba-sentinel这个集成很强大,我们并不需要去初始化任何bean对象,因为在启动的时候会自动加载上,所以只需要配置控制台和zookeeper的数据读取方式

控制台配置:

在application.yml下添加

spring:
  application:
    name: test
  cloud:
    sentinel:
      transport:
        port: 9303
        dashboard: 192.168.2.86:8010
        #heartbeatIntervalMs:
      eager: true
      enabled: true
      #datasource:
        #ds1:
          #file:
            #file: classpath:sentinel/flow-rule.json
            #data-type: json
            #rule-type: flow

port的概念:在项目和控制台之间通讯有个心跳信息,其实是单独启动了一个http的server在和控制台保持连接,所以需要单独开通一个端口号,dashboard即代表对应的控制台地址,以保持通讯

zookeeper配置

import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.zookeeper.ZookeeperDataSource;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;

/**
 * @author zhangrui
 * @createDate 2020/1/14 0014
 */
@Slf4j
@Component
public class ZookeeperSentinelConfig {

    @Value("${spring.application.name}")
    private String appName;
    @Value("${zookeeper.servers}")
    private String zookeeperAddress;

    @PostConstruct
    public void loadRules() {
        /*try {
            //需要转换成流的形式加载
            File file = ResourceUtils.getFile("classpath:sentinel/flow-rule.json");
            //读取本地配置
            ReadableDataSource<String, List<FlowRule>> flowRuleDataSourceLocal = new FileRefreshableDataSource<>(file,
                    source -> JSON.parseObject(
                            source,
                            new TypeReference<List<FlowRule>>() {
                            }
                    ));
            FlowRuleManager.register2Property(flowRuleDataSourceLocal.getProperty());
        } catch (Exception e) {
            log.error("init localRules failed");
            log.error(e.getMessage(), e);
        }*/
        //final String remoteAddress = "127.0.0.1:2181,192.168.0.2:2181";
        final String path = "/sentinel_rule_config/" + appName;
        ReadableDataSource<String, List<FlowRule>> flowRuleDataSource = new ZookeeperDataSource<>(zookeeperAddress, path,
                source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {
                }));
        FlowRuleManager.register2Property(flowRuleDataSource.getProperty());
    }
}

此处zookeeper可以是集群,也可是单点配置,都是支持的。注释里包含了读取本地json文件的配置,感兴趣的可以试试,不过由于springboot最后是由jar包启动,所以打包后启动有问题,目前还没有解决...

重要的配置是这里:

final String path = "/sentinel_rule_config/" + appName;

最后在dashboard中进行配置,需要保持一致。

在这里项目配置完毕,需要配置控制台

官网下载对应的jar包源码,因为代码有几处坑,所以必须修改代码解决...

打开源码,一个正规的springboot的项目

找到生成Id的地方如下

@Component
public class InMemGatewayFlowRuleStore extends InMemoryRuleRepositoryAdapter<GatewayFlowRuleEntity> {

    private static AtomicLong ids = new AtomicLong(0);

    @Override
    protected long nextId() {
        return ids.incrementAndGet();
    }
}

修改为:

@Component
public class InMemGatewayFlowRuleStore extends InMemoryRuleRepositoryAdapter<GatewayFlowRuleEntity> {

    private static AtomicLong ids = new AtomicLong(System.currentTimeMillis());

    @Override
    protected long nextId() {
        return ids.incrementAndGet();
    }
}

原因是因为dashboard每次以0为计数,这样会导致推送的规则覆盖之前的信息,所以必须修改这里,有好几处这样生成规则的地方,都需要进行修改

之后将pom文件中的zookeeper设置注释掉

nacos和apollo也是类似的~

在test文件中找到已经包含的zookeeper类,粘贴至项目中

此处还有一个坑,打开FlowRuleZookeeperProvider

修改为如下:

@Override
    public void publish(String app, List<FlowRuleEntity> rules) throws Exception {
        AssertUtil.notEmpty(app, "app name cannot be empty");

        String path = ZookeeperConfigUtil.getPath(app);
        Stat stat = zkClient.checkExists().forPath(path);
        if (stat == null) {
            zkClient.create().creatingParentContainersIfNeeded().withMode(CreateMode.PERSISTENT).forPath(path, null);
        }
        byte[] data = CollectionUtils.isEmpty(rules) ? "[]".getBytes() : converter.convert(rules).getBytes();
        zkClient.setData().forPath(path, data);
    }

其实就是将publish中判断path的地方在provider中进行了添加,否则在查询时zookeeper可能会报错

之后确定ConfigUtil中的root_path和项目中保持一致

config中的zookeeper地址和项目保持一致

之后打开FlowControllerV2,指定两个接口的引用改为zookeeper的引用

之后再打开sidebar.html,将原来flowV1改为flow,并去掉一个判断,改为永久可见,如下图

更改完以上配置之后,即可重新打包进行部署

启动命令如下:

nohup java -Xmx512M -Xms512M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./jvm-dump.hprof -XX:+PrintGCDateStamps -verbose:gc -XX:+PrintGCDetails -Xloggc:./logs/gc.log -XX:-OmitStackTraceInFastThrow -Dserver.port=8010 -Dcsp.sentinel.dashboard.server=192.168.2.86:8010 -Dproject.name=sentinel-dashboard -Dcsp.sentinel.log.dir=./logs/ -jar sentinel-dashboard.jar

server.port需要和项目配置地址保持一致,否则会找不到项目

之后启动控制台,看到对应的项目,即可配置限流功能,在客户端或dashboard启动后限流依旧生效

 

文章参考信息:

官网地址:
https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D
简易使用:
https://github.com/alibaba/Sentinel/wiki/%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8
主流框架适配
https://github.com/alibaba/Sentinel/wiki/%E4%B8%BB%E6%B5%81%E6%A1%86%E6%9E%B6%E7%9A%84%E9%80%82%E9%85%8D#spring-cloud
官方springcloud支持
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md
改造控制台存储规则
https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel
动态规则拓展
https://github.com/alibaba/Sentinel/wiki/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%99%E6%89%A9%E5%B1%95
常见错误
https://github.com/alibaba/Sentinel/wiki/FAQ
本地新建bean持久化
https://www.cnblogs.com/zhangpan1244/p/11228020.html
springcloud配置
https://blog.csdn.net/cdy1996/article/details/87391609
https://blog.csdn.net/u010391342/article/details/86678637
https://tianyalei.blog.csdn.net/article/details/89916891
https://blog.csdn.net/tianyaleixiaowu/article/details/94442906
源码解析:
https://www.jianshu.com/p/0e218ef7f505
https://www.jianshu.com/p/6ee4b7bdb844
zookeeper改造
https://blog.csdn.net/tianyaleixiaowu/article/details/94442906
https://blog.csdn.net/rodbate/article/details/89763669

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐