Dubbo集成Zookeeper embbed模式

为了简化应用支持服务方便的分合,使用Zookeeper embbed模式。集成Zookeeper比较容易,使用starter或自己写代码都可以。但是由于集成了Dubbo,每次启动时都会发现zookeeper没有启动就开始报错退出,但是确是已经集成了。

于是只能翻Dubbo源码

发现Dubbo启动时,会添加一个早期事件DubboConfigInitEvent。在spring afterproperties后,会立即触发该事件。在该事件里调用zookeeper注册事件。

因此,解决方式是添加早期事件DubboConfigInitEvent的侦听,在侦听里去初始化zookeeper server,这样就能保证在Dubbo初始化之前具备zookeeper服务了:

添加一个Helper Bean,实现代码如下:

package org.ccframe.commons.helper;

import lombok.Getter;
import lombok.SneakyThrows;
import org.apache.dubbo.config.spring.context.event.DubboConfigInitEvent;
import org.apache.zookeeper.server.NIOServerCnxnFactory;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.ccframe.config.GlobalEx;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

import java.io.File;
import java.net.InetSocketAddress;
import java.nio.file.Path;
import java.nio.file.Paths;

@Component
public class EmbeddedZookeeperLauncher implements ApplicationListener{

    private String zooDir;

    @Value("${app.zookeeper.embed.dir:}")
    public void setZooDir(String zooDir) {
        this.zooDir = zooDir;
        if (zooDir == null || zooDir.isEmpty()) {
            this.zooDir = GlobalEx.APP_BASE_DIR + File.separator + GlobalEx.EMBEDDED_ZOOKEEPER_DIR; //zookeeper数据放到应用运行目录
        }
    }

    @Value("${app.zookeeper.embed.port:2181}")
    private Integer zooPort;

    @Value("${app.zookeeper.embed.max-connection:1024}")
    private Integer maxConnection;

    @Value("${app.zookeeper.embed.tick-time:500}")
    private Integer tickTime;

    @Getter
    private ZooKeeperServer zooKeeperServer;

    @Override
    @SneakyThrows
    public void onApplicationEvent(DubboConfigInitEvent event){
        if (event.getApplicationContext().getParent() == null) {
            Path zooPath = Paths.get(zooDir);
            zooKeeperServer = new ZooKeeperServer(zooPath.toFile(), zooPath.toFile(), tickTime);
            NIOServerCnxnFactory factory = new NIOServerCnxnFactory();
            System.setProperty("zookeeper.maxCnxns", Integer.toString(maxConnection));
            factory.configure(new InetSocketAddress(zooPort), maxConnection);
            factory.startup(zooKeeperServer);
        }
    }

}

然后启动就不会报错了

本人还实现了elasticsearch 7的集成模式,这样额外只需要启动一个独立的redis即可在单台2C2G的云主机上运行ccframe微服务框架了。耐斯~

你可能感兴趣的:(zookeeper,dubbo,分布式,embedded,standalone)