zookeeper作配置中心(存储支付信息)

zookeeper作配置中心(存储敏感信息)

前提:最近在项目中需要用到支付接口,支付宝或者微信支付,根据官方文档,需要配置一些诸如notify-url或者app-private-key等信息,这些信息比较敏感,且是协同开发,为了避免发生一些不安全的事情,于是决定将这些信息存放在zookeeper中,这是主要原因,另一个原因是一旦配置需要改变,直接在zookeeper中改变即可,不需要重启后端服务,这里涉及到了zookeeper的NIO以及长连接等相关的底层网络编程,这里不再赘述。

1、首先在服务器端安装zookeeper,默认端口是2181,安装教程不讲解

2、在本机(Window 10)安装ZKUI(ZK可视化客户端),方便管理zookeeper

3、安装zookeeper的java客户端(curator)

4、读取配置信息并设置监听器


@Configuration
class PaymentConfig {

    @Value("\${custom-config.zookeeper.url}")
    lateinit var zkUrl: String

    @Value("\${custom-config.zookeeper.zfb-nodename}")
    lateinit var zfbNodeName: String

    @Value("\${custom-config.zookeeper.wx-nodename}")
    lateinit var wxNodeName: String

    val remoteProperties: Properties = Properties()

    companion object {
        /**
         * zookeeper节点映射在本地的键值
         */
        private const val ALI_APP_ID = "/pay-server-config/pay.alipay/app-id"
        private const val ALI_APP_PRIVATE_KEY = "/pay-server-config/pay.alipay/app-private-key"
        private const val ALI_NOTIFY_URL = "/pay-server-config/pay.alipay/notify-url"
        private const val ALI_PUBLIC_KEY = "/pay-server-config/pay.alipay/public-key"

        private const val WX_NOTIFY_URL = "/pay-server-config/pay.wxpay/notify-url"
        private const val WX_APP_ID = "/pay-server-config/pay.wxpay/app-id"
        private const val WX_APP_PRIVATE_KEY = "/pay-server-config/pay.wxpay/app-private-key"
        private const val WX_MCH_ID = "/pay-server-config/pay.wxpay/mch-id"
    }

    @PostConstruct
    fun init(){
        setPaymentConfigFromZk(remoteProperties)
    }

    fun setPaymentConfigFromZk(remoteProperties: Properties){
        val zkClient: CuratorFramework = CuratorFrameworkFactory.newClient(zkUrl, RetryOneTime(1000))
        zkClient.start()
        try {
            val zfbConfigNames = zkClient.children.forPath("/$zfbNodeName")
            val wxConfigNames = zkClient.children.forPath("/$wxNodeName")
            for (configName in zfbConfigNames) {
                val value = String(zkClient.data.forPath("/$zfbNodeName/$configName"))
                remoteProperties["/$zfbNodeName/$configName"] = value
            }
            for (configName in wxConfigNames) {
                val value = String(zkClient.data.forPath("/$wxNodeName/$configName"))
                remoteProperties["/$wxNodeName/$configName"] = value
            }
            setListener(zkClient, zfbNodeName, remoteProperties)
            setListener(zkClient, wxNodeName, remoteProperties)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun setListener(zkClient: CuratorFramework, uri: String, remoteProperties: Properties){
        val treeCache = TreeCache(zkClient, "/$uri")
        treeCache.start()
        treeCache.listenable.addListener(TreeCacheListener(
                fun(client: CuratorFramework, event: TreeCacheEvent) {
                    when (event.type) {
                        TreeCacheEvent.Type.NODE_UPDATED -> {
                            val value = String(event.data.data)
                            remoteProperties[event.data.path] = value
                            println("Payment URL has changed, the changed is ${String(event.data.data)}")
                            println("Payment URL has changed, the path is ${event.data.path}")
                        }
                        else -> {
                            print("Now, get the config from zookeeper ${event.data}")
                        }
                    }
                }
        )
        )
    }
}

以上代码大意为:在初始化的时候读取zookeeper中的值,并赋值到本地的Properties,key为zookeeper节点的全路径,值为叶子节点的Value,之后使用TreeCache监听客户端的变化,当某个叶子节点的值发生改变后,改变原有的properties,替换为新值。

posted @ 2019-11-29 16:22  健人雄  阅读(582)  评论(0编辑  收藏  举报