同一个应用连接两个Zookeeper集群的方法

背景

  1. 因为应用服务用到了Dubbo,Dubbo 依赖了 Zookeeper作为注册中心。
  2. 应用服务同时还需要连接到KAFKA,且Kafka开启了SASL认证。

问题

对于一个开源中间件来说,集群安全是很重要的,但是在实现上,认证方式就那么几种:

  1. GSSAPI (唯一实现:Kerberos,Java可以使用JAAS对其进行支持)
  2. SASL (Java可以使用JAAS对其进行支持)
  3. PLAIN_TEXT (没认证)
  4. SSL
    那么如果全局指定了JAAS,访问两个SASL配置账户不同的集群,就会必然有一个失败。

分析

对于Zookeeper,它使用了JAAS,它仅仅简单粗暴的通过读取zookeeper.sasl.clientjava.security.auth.login.config这两个全局环境变量来判断要不要使用SASL认证,无法通过其他方式来改变这种行为。

对于Kafka,它巧妙地实现了javax.security.auth.login.Configuration,也就是org.apache.kafka.common.security.JaasConfig。可以通过代码中直接指定 sasl.jaas.config(slankka:0715.2020) 来表示此Topic的连接认证方式,十分灵活。

此外,Apache Flume 也收益于此,Flume如果同时连接加密和不加密的 多套Kafka集群,可以按照单个Kafka Source/Sink 进行Topic级别细粒度的配置认证方式,而不是通过JVM参数直接全局固定。

那么解决方案就有好几种:

  1. 修改使用Zookeeper的客户端连接器。
  2. 修改Zookeeper源码。
  3. 运行时指定Jaas,启动时不指定。
  4. 通过创建单独的进程指定JAAS参数
  5. 通过Java调用Linux命令,访问Kafka/Zookeeper配置好的客户端来执行某些操作。

额外技术细节

Zookeeper 本身的连接是极为困难的,现在开源社区总共有两种Zookeeper Java Client(暂且称为Zookeeper连接器):

  1. zkclient(zk101tec)
  2. Curator

具体区别不在这里详述。

对于 Dubbo 2.7.1 以后的版本,我通过检查源码,发现 Dubbo已经去除 zkclient(zk101tec)依赖,已经完全切换到 Apache Curator。
如果修改 Zookeeper连接器,那就要确定项目中,引入的框架使用的是哪一种连接器。

解决方案

解决办法正如前文指出,有三种,最便宜实用的方法就是方案三: 在运行时指定jaas配置。运行完毕再恢复上次的配置。在切换期间可能会存在几毫秒的其他Zookeeper集群访问的问题,但是这已经是极小的影响了。

另外,Zookeeper社区,有人指出这种设计的不足:

ZOOKEEPER-2139:Support multiple ZooKeeper client, with different configurations, in a single JVM

通过查看提交记录发现,社区已经针对Zookeeper的构造函数提供了 ZkClientConfig这个参数类,可以实现自定义的配置。
Github 2139 Commit

可以看出,这些版本以后才能支持:release-3.6.1 release-3.6.1-1 release-3.6.1-0 release-3.6.0 release-3.6.0-4 release-3.6.0-3 release-3.6.0-2 release-3.6.0-1 release-3.6.0-0

当Zookeeper支持了以后,就可以用方案1,或者类似于Kafka的方式来更好的解决。

总结

Kafka的这种设计值得我们学习,减少具体配置对环境变量的依赖。
涉及到的技术有:JAAS,Kafka, Zookeeper

posted @ 2020-07-15 16:28  一杯半盏  阅读(2235)  评论(0编辑  收藏  举报