Dubbo+Zookeeper ACL+ElasticJob

一. 问题背景

当Zookeeper开启ACL后,Dubbo以及Elastic-Job需要如何配置来连接Zookeeper。

Zookeeper ACL介绍参考文章: https://cloud.tencent.com/developer/article/1414462

二. 组件版本

  1. zookeeper: 3.5.8
  2. dubbo: 2.6.6
  3. elastic-job: 1.0.6

三. ZK设置ACL

3.1 dubbo

dubbo默认是注册在/dubbo目录,下面以/dubbo目录为例说明。

1. 进入Zookeeper客户端,创建/dubbo目录及设置ACL权限。

$ create /dubbo 'data'
$ addauth digest hamawhite:123456

$ setAcl /dubbo auth:hamawhite:123456:cdwra
$ getAcl /dubbo

'digest,'hamawhite:YfjnOH3mtKecIPZ5prmNB7B6lA4=
: cdrwa

2.   修改SpringBoot的配置文件,增加duboo registry的username和password。

dubbo.registry.username=hamawhite
dubbo.registry.password=123456

如果Zookeeper管理员分配给指定的目录来注册,例如 /gou,则需要在dubbo的配置文件中还需增加 dubbo.registry.group=/shuqi 。

完整配置如下:

dubbo.registry.group=shuqi
dubbo.registry.username=hamawhite
dubbo.registry.password=123456

3.2 elastic-job

推荐把elastic-job的namespace配置为dubbo.registry.group的值,否则Zookeeper管理员还需要给elastic-job额外分配目录。

完整配置如下:

    <!--配置作业注册中心 -->
    <reg:zookeeper id="regCenter"
                   serverLists="${dubbo.registry.address}"
                   namespace="${dubbo.registry.group}"
                   digest="${dubbo.registry.username}:${dubbo.registry.password}"
                   baseSleepTimeMilliseconds="1000"
                   maxSleepTimeMilliseconds="3000"
                   maxRetries="0"/>

注意,在SpringBoot的配置中一定要定义dubbo.registry.group,如果是默认值,也要写dubbo.registry.group=dubbo。

四. ZK目录探索

4.1 dubbo registry目录

dubbo在/dubbo目录下注册的service都未设置ACL,权限都是world:anyone:cdrwa。这样其实任意用户能访问此service目录,仍有安全风险。

[zk: localhost:2181(CONNECTED) 64] getAcl /dubbo/com.dtwave.ai.api.service.ModelService
'world,'anyone
: cdrwa
[zk: localhost:2181(CONNECTED) 65] getAcl /dubbo/com.dtwave.ai.api.service.NotebookService
'world,'anyone
: cdrwa

4.2 dubbo 源码分析

dubbo2.6版本后Zookeeper客户端默认是Curator,因此查看com.alibaba.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient的代码。

创建client代码如下:

    public CuratorZookeeperClient(URL url) {
        super(url);
        try {
            CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
                    .connectString(url.getBackupAddress())
                    .retryPolicy(new RetryNTimes(1, 1000))
                    .connectionTimeoutMs(5000);
            String authority = url.getAuthority();
            if (authority != null && authority.length() > 0) {
                builder = builder.authorization("digest", authority.getBytes());
            }
            client = builder.build();
            client.getConnectionStateListenable().addListener(new ConnectionStateListener() {
                @Override
                public void stateChanged(CuratorFramework client, ConnectionState state) {
                    if (state == ConnectionState.LOST) {
                        CuratorZookeeperClient.this.stateChanged(StateListener.DISCONNECTED);
                    } else if (state == ConnectionState.CONNECTED) {
                        CuratorZookeeperClient.this.stateChanged(StateListener.CONNECTED);
                    } else if (state == ConnectionState.RECONNECTED) {
                        CuratorZookeeperClient.this.stateChanged(StateListener.RECONNECTED);
                    }
                }
            });
            client.start();
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

可以看到,创建client的时候有处理授权,builder = builder.authorization("digest", authority.getBytes()) ,也未设置aclProvider。

在创建目录时候,也未设置ACL。 因此子目录权限都是默认的world:anyone:cdrwa。

    @Override
    public void createPersistent(String path) {
        try {
            client.create().forPath(path);
        } catch (NodeExistsException e) {
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    @Override
    public void createEphemeral(String path) {
        try {
            client.create().withMode(CreateMode.EPHEMERAL).forPath(path);
        } catch (NodeExistsException e) {
        } catch (Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

补充创建目录可以通过配置withACL来设置ACL,示例代码如下:

具体可参考 https://blog.csdn.net/liuxiao723846/article/details/85303602

client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).withACL(acls).forPath(nodePath, nodeData);

4.3 elastic-job zookeeper目录

elastic-job在/dubbo目录下创建的子目录用户名和密码和配置项保持一致,permission权限都是cdrwa。

[zk: localhost:2181(CONNECTED) 66] getAcl /dubbo/updateNotebookStatusJob
'digest,'hamawhite:YfjnOH3mtKecIPZ5prmNB7B6lA4=
: cdrwa
[zk: localhost:2181(CONNECTED) 67] ls /dubbo/updateNotebookStatusJob
[config, execution, leader, servers]
[zk: localhost:2181(CONNECTED) 68] getAcl /dubbo/updateNotebookStatusJob/leader
'digest,'hamawhite:YfjnOH3mtKecIPZ5prmNB7B6lA4=
: cdrwa

4.4 elastic-job Zookeeper客户端源码分析

查看com.dangdang.ddframe.reg.zookeeper.ZookeeperRegistryCenter的代码。

创建client 核心代码如下:

    public void init() {
        ......

        if (!Strings.isNullOrEmpty(this.zkConfig.getDigest())) {
            builder.authorization("digest", this.zkConfig.getDigest().getBytes(Charset.forName("UTF-8"))).aclProvider(new ACLProvider() {
                public List<ACL> getDefaultAcl() {
                    return Ids.CREATOR_ALL_ACL;
                }

                public List<ACL> getAclForPath(String path) {
                    return Ids.CREATOR_ALL_ACL;
                }
            });
        }

        this.client = builder.build();
        this.client.start();

        try {
            this.client.blockUntilConnected();
            if (!Strings.isNullOrEmpty(this.zkConfig.getLocalPropertiesPath())) {
                this.fillData();
            }
        } catch (Exception var3) {
            RegExceptionHandler.handleException(var3);
        }

    }

可以看到,创建client的时候有处理授权,builder = builder.authorization("digest", authority.getBytes()) ,设置了aclProvider。

其中perms设置为全部权限,即cdrwa。Ids设置为AUTH_IDS,表示会继承客户端的身份鉴权信息。

      /**
         * This ACL gives the creators authentication id's all permissions.
         */
        public final ArrayList<ACL> CREATOR_ALL_ACL = new ArrayList<ACL>(
                Collections.singletonList(new ACL(Perms.ALL, AUTH_IDS)));

       /**
         * This Id is only usable to set ACLs. It will get substituted with the
         * Id's the client authenticated with.
         */
        public final Id AUTH_IDS = new Id("auth", "");

 

这样CreateBuilderImpl里的 acling = new ACLing(client.getAclProvider()),后续用client创建的子目录用户名和密码和配置项保持一致,permission权限都是cdrwa。

Elasticsearch 简介 ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口。Elasticsearch是用Java开发的,并作为Apache许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。elasticSearch 的使用场景 1、在海量数据前提下,对数据进行检索。比如:京东,淘宝等电商项目课程目标: 1. 了解企业级搜索引擎2. 安装elasticsearch 课程目录: 01 课程介绍02 elasticsearch 简介03 elasticsearch 使用场景04 安装elasticsearch 之前先安装jdk05 安装elasticsearch06 测试elasticsearch是否安装成功 07 安装kibana08 elasticsearch 基本认识 以及添加索引和删除索引09 elasticsearch 添加查询数据10 elasticsearch 修改删除数据11 elasticsearch 有条件的查询12 分词子属性fuzzy查询13 elasticsearch 过滤使用14 elasticsearch 排序与分页15 elasticsearch 如何查询指定的字段16 elasticsearch 高亮显示17 elasticsearch 聚合18 elasticsearch mapping 概念19 elasticsearch 的中文词库20 elasticsearch 中文词库安装测试21 elasticsearch 中文词库的使用案例22 elasticsearch 自定义词库配置23 安装nginx 配置中文词库24 测试elasticsearch 自定义中文词库25 搭建项目父工程26 搭建项目bean-interface-common27 搭建search 的service web 项目28 测试项目是否能与elasticsearch联通29 创建数据库并搭建首页30 数据上传功能的实现类完成31 数据上传控制器完成32 dubbo 介绍以及安装zookeeper33 将数据从mysql 上传到elasticsearch 中34 elasticsearch查询功能分析35 编写业务需求的dsl 语句36 编写输入参数返回结果集的实体类37 实现类编写38 编写实现类中dsl 语句39 返回集结果转换40 结果测试41 测试通过输入查询条件并将数据显示到页面
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值