草庐IT

springboot整合dubbo时连接zookeeper——天坑

夜尽天明~ 2023-04-10 原文

 

         本文主要针对使用springboot整合dubbo框架时使用zookeeper作为注册中心,在服务启动连接zookeeper产生的问题做一个详细的讲解。

        主要针对两个异常

(1)java.lang.IllegalStateException: java.lang.IllegalStateException: zookeeper not connected

(2)java.lang.IllegalStateException: failed to connect to zookeeper server

关于两个异常的详细信息见下方异常信息

1、异常详细信息

        (1) java.lang.IllegalStateException: java.lang.IllegalStateException: zookeeper not connected

java.lang.IllegalStateException: java.lang.IllegalStateException: zookeeper not connected
	at org.apache.dubbo.config.deploy.DefaultApplicationDeployer.prepareEnvironment(DefaultApplicationDeployer.java:678) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultApplicationDeployer.startConfigCenter(DefaultApplicationDeployer.java:261) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultApplicationDeployer.initialize(DefaultApplicationDeployer.java:185) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultModuleDeployer.prepare(DefaultModuleDeployer.java:470) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.spring.context.DubboConfigApplicationListener.initDubboConfigBeans(DubboConfigApplicationListener.java:71) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.spring.context.DubboConfigApplicationListener.onApplicationEvent(DubboConfigApplicationListener.java:57) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.spring.context.DubboConfigApplicationListener.onApplicationEvent(DubboConfigApplicationListener.java:35) ~[dubbo-3.0.7.jar:3.0.7]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.registerListeners(AbstractApplicationContext.java:842) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:548) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1247) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1236) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at com.bao.Application.main(Application.java:11) [classes/:na]
Caused by: java.lang.IllegalStateException: zookeeper not connected
	at org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient.<init>(CuratorZookeeperClient.java:89) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter.createZookeeperClient(CuratorZookeeperTransporter.java:26) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.remoting.zookeeper.AbstractZookeeperTransporter.connect(AbstractZookeeperTransporter.java:69) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration.<init>(ZookeeperDynamicConfiguration.java:63) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfigurationFactory.createDynamicConfiguration(ZookeeperDynamicConfigurationFactory.java:47) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory.lambda$getDynamicConfiguration$0(AbstractDynamicConfigurationFactory.java:39) ~[dubbo-3.0.7.jar:3.0.7]
	at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[na:1.8.0_131]
	at org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory.getDynamicConfiguration(AbstractDynamicConfigurationFactory.java:39) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultApplicationDeployer.getDynamicConfiguration(DefaultApplicationDeployer.java:715) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultApplicationDeployer.prepareEnvironment(DefaultApplicationDeployer.java:671) ~[dubbo-3.0.7.jar:3.0.7]
	... 20 common frames omitted
Caused by: java.lang.IllegalStateException: zookeeper not connected
	at org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient.<init>(CuratorZookeeperClient.java:85) ~[dubbo-3.0.7.jar:3.0.7]
	... 29 common frames omitted

 (2)java.lang.IllegalStateException: failed to connect to zookeeper server

java.lang.RuntimeException: Can not create registry service-discovery-registry://192.168.0.106:2181/org.apache.dubbo.registry.RegistryService?application=privoder_application&block-until-connected-wait=3&blockUntilConnectedWait=3&dubbo=2.0.2&interface=org.apache.dubbo.registry.RegistryService&pid=21212&qos.enable=false&registry=zookeeper&release=3.0.7&timeout=250000
	at org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistry(AbstractRegistryFactory.java:92) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.RegistryFactoryWrapper.getRegistry(RegistryFactoryWrapper.java:33) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.RegistryFactory$Adaptive.getRegistry(RegistryFactory$Adaptive.java) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.integration.RegistryProtocol.getRegistry(RegistryProtocol.java:393) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.integration.RegistryProtocol.export(RegistryProtocol.java:242) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.rpc.protocol.ProtocolListenerWrapper.export(ProtocolListenerWrapper.java:64) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.qos.protocol.QosProtocolWrapper.export(QosProtocolWrapper.java:74) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.rpc.cluster.filter.ProtocolFilterWrapper.export(ProtocolFilterWrapper.java:58) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.rpc.protocol.ProtocolSerializationWrapper.export(ProtocolSerializationWrapper.java:47) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.rpc.Protocol$Adaptive.export(Protocol$Adaptive.java) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.ServiceConfig.doExportUrl(ServiceConfig.java:641) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.ServiceConfig.exportRemote(ServiceConfig.java:619) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.ServiceConfig.exportUrl(ServiceConfig.java:578) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.ServiceConfig.doExportUrlsFor1Protocol(ServiceConfig.java:410) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.ServiceConfig.doExportUrls(ServiceConfig.java:396) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.ServiceConfig.doExport(ServiceConfig.java:361) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.ServiceConfig.export(ServiceConfig.java:233) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultModuleDeployer.exportServiceInternal(DefaultModuleDeployer.java:341) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultModuleDeployer.exportServices(DefaultModuleDeployer.java:313) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.deploy.DefaultModuleDeployer.start(DefaultModuleDeployer.java:145) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.spring.context.DubboDeployApplicationListener.onContextRefreshedEvent(DubboDeployApplicationListener.java:111) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.spring.context.DubboDeployApplicationListener.onApplicationEvent(DubboDeployApplicationListener.java:100) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.config.spring.context.DubboDeployApplicationListener.onApplicationEvent(DubboDeployApplicationListener.java:45) ~[dubbo-3.0.7.jar:3.0.7]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:404) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:361) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:898) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:554) ~[spring-context-5.2.15.RELEASE.jar:5.2.15.RELEASE]
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:143) ~[spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:755) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:747) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:402) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:312) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1247) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1236) [spring-boot-2.3.12.RELEASE.jar:2.3.12.RELEASE]
	at com.bao.Application.main(Application.java:11) [classes/:na]
Caused by: java.lang.IllegalStateException: Create zookeeper service discovery failed.
	at org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery.<init>(ZookeeperServiceDiscovery.java:77) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscoveryFactory.createDiscovery(ZookeeperServiceDiscoveryFactory.java:27) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory.lambda$getServiceDiscovery$0(AbstractServiceDiscoveryFactory.java:53) ~[dubbo-3.0.7.jar:3.0.7]
	at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[na:1.8.0_131]
	at org.apache.dubbo.registry.client.AbstractServiceDiscoveryFactory.getServiceDiscovery(AbstractServiceDiscoveryFactory.java:53) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.client.ServiceDiscoveryRegistry.getServiceDiscovery(ServiceDiscoveryRegistry.java:122) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.client.ServiceDiscoveryRegistry.createServiceDiscovery(ServiceDiscoveryRegistry.java:109) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.client.ServiceDiscoveryRegistry.<init>(ServiceDiscoveryRegistry.java:86) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.client.ServiceDiscoveryRegistryFactory.createRegistry(ServiceDiscoveryRegistryFactory.java:35) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistry(AbstractRegistryFactory.java:89) ~[dubbo-3.0.7.jar:3.0.7]
	... 37 common frames omitted
Caused by: java.lang.IllegalStateException: failed to connect to zookeeper server
	at org.apache.dubbo.registry.zookeeper.util.CuratorFrameworkUtils.buildCuratorFramework(CuratorFrameworkUtils.java:75) ~[dubbo-3.0.7.jar:3.0.7]
	at org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery.<init>(ZookeeperServiceDiscovery.java:72) ~[dubbo-3.0.7.jar:3.0.7]
	... 46 common frames omitted

2、缘起

        前几天用springboot写了一个web项目,对外提供的是http请求接口,使用java程序调用不是很方便,于是想把它构建一个dubbo项目,方便服务间调用。在经过一系列的改造后,终于迎来了测试阶段。由于我是使用zookeeper作为注册中心,所以需要安装zookeeper(不会的可以自己查一下,网上教材很多)。由于嫌虚拟机麻烦,就直接在本机win10上启动了zookeeper,然后测试,程序服务注册和调用一切正常,No Problem!!!事情到这里本来是个美好的故事,然而……

        为了更接近真实的开发环境,我决定在程序调试完毕后,将zookeeper安装到linux虚拟机中,然而就是这个决定,改变了故事的结局——感觉遇到了一个天坑。

3、求知

        项目启动就报了第一个异常,本着有事问度娘的原则,第一个问题直接秒杀。简单说一下吧。

        根据异常定位到 package org.apache.dubbo.remoting.zookeeper.curator 包下的CuratorZookeeperClient类,其构造方法代码(截取部分,全部代码可自行查看)如下    

public class CuratorZookeeperClient extends AbstractZookeeperClient<CuratorZookeeperClient.NodeCacheListenerImpl, CuratorZookeeperClient.CuratorWatcherImpl> {
    private final CuratorFramework client;
    public CuratorZookeeperClient(URL url) {
        super(url);
        try {
            int timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS);
            int sessionExpireMs = url.getParameter(SESSION_KEY, DEFAULT_SESSION_TIMEOUT_MS);
            CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
                    .connectString(url.getBackupAddress())
                    .retryPolicy(new RetryNTimes(1, 1000))
                    .connectionTimeoutMs(timeout)
                    .sessionTimeoutMs(sessionExpireMs);
            String userInformation = url.getUserInformation();
            if (StringUtils.isNotEmpty(userInformation)) {
                builder = builder.authorization("digest", userInformation.getBytes());
            }
            client = builder.build();
            client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url));
            client.start();
            //第一个异常出现在这里
            boolean connected = client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS);
            if (!connected) {
                throw new IllegalStateException("zookeeper not connected");
            }
        } catch (Exception e) {
            close();
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

}

        解释一下这个CuratorZookeeperClient,它是对原生zookeeper客户端的一个封装,就好比mybatis是对原生JDBC的封装一样。CuratorZookeeperClient里面有个CuratorFramework类型的属性client,在这个属性中真正封装了一个zookeeper客户端。CuratorZookeeperClient的构造方法中传了一个URL对象,这个URL对象中封装了创建zookeeper客户端需要的参数信息,如下

zookeeper://192.168.0.106:2181/org.apache.dubbo.config.ConfigCenterConfig?block-until-connected-wait=3&blockUntilConnectedWait=3&check=true&config-file=dubbo.properties&group=dubbo&highest-priority=false&namespace=dubbo&timeout=30000

 这就是一个URL地址,类似于http的get请求,“?”前面是协议和zookeeper主机地址,后面是参数。然后将参数提取出来,传到需要的方法中。而这些参数则是通过配置文件application.yml或application.properties文件配置的,如图

        这里的参数会自动解析到URL中,当然不是所有的参数都会封装到URL中,只是封装一部分,如果没有定义相应参数,则会采用默认值。

public class CuratorZookeeperClient extends AbstractZookeeperClient<CuratorZookeeperClient.NodeCacheListenerImpl, CuratorZookeeperClient.CuratorWatcherImpl> {
    private final CuratorFramework client;
    public CuratorZookeeperClient(URL url) {
        super(url);
        try {
            int timeout = url.getParameter(TIMEOUT_KEY, DEFAULT_CONNECTION_TIMEOUT_MS);
            int sessionExpireMs = url.getParameter(SESSION_KEY, DEFAULT_SESSION_TIMEOUT_MS);
            CuratorFrameworkFactory.Builder builder = CuratorFrameworkFactory.builder()
                    .connectString(url.getBackupAddress())
                    .retryPolicy(new RetryNTimes(1, 1000))
                    .connectionTimeoutMs(timeout)
                    .sessionTimeoutMs(sessionExpireMs);
            String userInformation = url.getUserInformation();
            if (StringUtils.isNotEmpty(userInformation)) {
                builder = builder.authorization("digest", userInformation.getBytes());
            }
            client = builder.build();
            client.getConnectionStateListenable().addListener(new CuratorConnectionStateListener(url));
            client.start();
            //第一个异常出现在这里
            boolean connected = client.blockUntilConnected(timeout, TimeUnit.MILLISECONDS);
            if (!connected) {
                throw new IllegalStateException("zookeeper not connected");
            }
        } catch (Exception e) {
            close();
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

}

        第一个异常出现的位置见代码注释,根据网友的解答,这里的异常是因为等待连接超时引起的。这里的timeout默认是30秒,就是说如果30秒内没有连接成功,就会报错。通常情况下本机的zookeeper连接可以在30秒内完成,但是虚拟机那边连接就贼慢。

到这里第一个异常就解决了,只需要配置timeout参数大一些即可,如图所示。

4、入坑

        正当我微微一笑,心想不过如此,so easy时,转身掉进了一个天坑。

        好家伙,知道原因后我这暴脾气直接给timeout干到250秒,等待项目起飞时,第二个异常来了。此时的我根本不知道事情的严重性,依然稳如一条老狗,默默打开百度……n分钟后,我特么傻了,整个网上都没有对这个异常的解决的帖子(反正我是没找到)。第二个异常信息里面有三个异常,我都搜了一遍,还是没找到。我真是醉了,难道这么多人都没遇到这个问题吗?然后怎么办呢,只能根据控制台信息排查。通过第二个异常的倒数第三行,我来到了这个类,如下(删除了部分源码,只留了报错的部分)

package org.apache.dubbo.registry.zookeeper.util;

public abstract class CuratorFrameworkUtils {

    public static CuratorFramework buildCuratorFramework(URL connectionURL) throws Exception {
        CuratorFramework curatorFramework = CuratorFrameworkFactory.builder()
            .connectString(connectionURL.getBackupAddress())
            .retryPolicy(buildRetryPolicy(connectionURL))
            .build();
        curatorFramework.start();
        //这段代码是不是似曾相识?
        curatorFramework.blockUntilConnected(BLOCK_UNTIL_CONNECTED_WAIT.getParameterValue(connectionURL),
            BLOCK_UNTIL_CONNECTED_UNIT.getParameterValue(connectionURL));

        if (!curatorFramework.getState().equals(CuratorFrameworkState.STARTED)) {
            throw new IllegalStateException("zookeeper client initialization failed");
        }

        if (!curatorFramework.getZookeeperClient().isConnected()) {
            //这里抛异常了
            throw new IllegalStateException("failed to connect to zookeeper server");
        }
        return curatorFramework;
    }
}

        我一看这个代码,似曾相识啊,好家伙,这不是跟上一个异常一样吗?设置一下超时时间就行了吗?感觉不过如此,事实证明还是太年轻了啊。

        通过源码中这个方法

curatorFramework.blockUntilConnected(BLOCK_UNTIL_CONNECTED_WAIT.getParameterValue(connectionURL),
            BLOCK_UNTIL_CONNECTED_UNIT.getParameterValue(connectionURL));

        我找到了这个枚举类。 

package org.apache.dubbo.registry.zookeeper.util;

import org.apache.dubbo.common.URL;
import org.apache.dubbo.registry.client.ServiceInstance;

import org.apache.curator.framework.CuratorFramework;

import java.util.concurrent.TimeUnit;
import java.util.function.Function;

/**
 * The enumeration for the parameters  of {@link CuratorFramework}
 *
 * @see CuratorFramework
 * @since 2.7.5
 */
public enum CuratorFrameworkParams {

    BLOCK_UNTIL_CONNECTED_WAIT("blockUntilConnectedWait", 10, Integer::valueOf),

    /**
     * The unit of time related to blocking on connection to Zookeeper.
     */
    BLOCK_UNTIL_CONNECTED_UNIT("blockUntilConnectedUnit", TimeUnit.SECONDS, TimeUnit::valueOf),

    ;

    private final String name;

    private final Object defaultValue;

    private final Function<String, Object> converter;

    <T> CuratorFrameworkParams(String name, T defaultValue, Function<String, T> converter) {
        this.name = name;
        this.defaultValue = defaultValue;
        this.converter = (Function<String, Object>) converter;
    }

    /**
     * Get the parameter value from the specified {@link URL}
     *
     * @param url the Dubbo registry {@link URL}
     * @param <T> the type of value
     * @return the parameter value if present, or return <code>null</code>
     */
    public <T> T getParameterValue(URL url) {
        String param = url.getParameter(name);
        Object value = param != null ? converter.apply(param) : defaultValue;
        return (T) value;
    }
}

发现这个BLOCK_UNTIL_CONNECTED_WAIT对象中设置了一个默认值10,也就是说10秒内连接不上就会报异常。好家伙,前面是30都不行,这里居然给个10。

 为此我还把这段代码拿出来亲自测试了一下,测试代码如下

import org.apache.curator.CuratorZookeeperClient;
import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;

public class TestCurator {
    public static void main(String[] args) throws Exception {
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
         CuratorFramework client = CuratorFrameworkFactory.builder()
         .connectString("192.168.0.106:2181")
//         .connectString("localhost:2181")
         .sessionTimeoutMs(5000) // 会话超时时间
         .connectionTimeoutMs(5000) // 连接超时时间
         .retryPolicy(retryPolicy)
         .namespace("base")
         .build();
         client.start();
        long l = System.currentTimeMillis();
        //这里不传参数表示无限制等待
        client.blockUntilConnected();
        long l1 = System.currentTimeMillis();
        long l2 = l1 - l;
        //输出等待连接毫秒数
        System.out.println(l2);
        CuratorZookeeperClient zookeeperClient = client.getZookeeperClient();
        boolean connected = zookeeperClient.isConnected();
        System.out.println(connected);

    }
}

经过测试,快则需要30+秒,慢则需要60+秒,有兴趣的可以自己测一下。

        不过连接本机zookeeper居然啥事儿没有,看来本机还是快啊。根据经验,参数配置在配置文件中,只需输入参数名就会有提示。

        没想到从这里就是噩梦的开始……

        根据枚举对象中参数名称blockUntilConnectedWait,准备去配置文件中设置该属性的值。正当我输入该变量名称时,居然没有提示,没有提示意味着没有该变量属性。到这里,问题看上去已经解决了90%,只要找到变量设置一下值就行了。但是,其实就解决了10%,问题就出在这个变量去哪里设置?我找了好久也没看到这个变量的名字,然后默默打开了百度……结果啥也没有。这里问题就严重了,这得去源码里面找啊。最开始肯定去看dubbo的自动配置类啊,如下图,结果dubbo有两个自动配置的包。

        我一眼就看到了第一个,忽略了第二个(不知道为啥有两个,一个不好吗),结果第一个包里没找到属性配置类(其实在第二个包里)。我反复看了几遍,这个自动配置类跟之前看过的其他组件的自动配置类套路咋不一样,找了半天没找到,我就以为URL的参数绑定肯定是在dubbo启动的时候通过spring完成的。肯定是spring封装好的URL直接给dubbo,然后dubbo给zookeeper(回头想想,我特么真佩服我的脑洞)。

        然后我就从@EnableDubbo注解开始,一步一步调试dubbo。就想找到那个URL组装的地方,看看blockUntilConnectedWait属性怎么搞进去。卧槽了,真的,我特么从0点一直调试到4点多,就为了找那个URL组装的地方。结果没找到,我真的裂开,要吐了。

        终于,我不知怎么看到了第二个自动配置的jar包,我进去一看,瞬间懂了,那个属性配置类就在这个包里面,参数是通过配置类自动映射绑定上去的,跟我之前想的一样,只不过没看到这个包。然后我把所有的属性配置类都看了一遍,还是没找到blockUntilConnectedWait这个属性。给我气的,我当时直接想去源码中把BLOCK_UNTIL_CONNECTED_WAIT对象的默认值给改了。

        然后以为是idea配置文件提示有问题,强行设置blockUntilConnectedWait属性,但是不起作用。一看都特么快5点了,放弃了……

        早上八点就起来了,吃完早饭坐在电脑前一遍一遍的看属性配置类的属性。直到我看到这个parameters参数

        真是山重水复疑无路,柳暗花明又一村啊,我赶紧通过这个新的参数试了一下。

                终于,设置成功了,这谁能想的到,事实证明,还是得看源码。至此,项目终于可以起飞了。

4、结语

        

 

 

有关springboot整合dubbo时连接zookeeper——天坑的更多相关文章

  1. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  2. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  3. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  4. ruby-on-rails - 连接字符串时如何在 <%=%> block 内输出 html_safe? - 2

    考虑一下:现在这些情况:#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2#output:http://domain.com/?foo=1&bar=2我需要用其他字符串输出URL。我如何保证&符号不会被转义?由于我无法控制的原因,我无法发送&。求助!把我的头发拉到这里:\编辑:为了澄清,我实际上有一个像这样的数组:@images=[{:id=>"fooid",:url=>"http://

  5. ruby - Faye WebSocket,关闭处理程序被触发后重新连接到套接字 - 2

    我有一个super简单的脚本,它几乎包含了FayeWebSocketGitHub页面上用于处理关闭连接的内容:ws=Faye::WebSocket::Client.new(url,nil,:headers=>headers)ws.on:opendo|event|p[:open]#sendpingcommand#sendtestcommand#ws.send({command:'test'}.to_json)endws.on:messagedo|event|#hereistheentrypointfordatacomingfromtheserver.pJSON.parse(event.d

  6. ruby-on-rails - 什么会导致与 APNS 的连接间歇性断开连接? - 2

    我有一个ruby​​脚本可以打开与Apple推送服务器的连接并发送所有待处理的通知。我看不出任何原因,但当Apple断开我的脚本时,我遇到了管道损坏错误。我已经编写了我的脚本来适应这种情况,但我宁愿只是找出它发生的原因,这样我就可以在第一时间避免它。它不会始终根据特定通知断开连接。它不会以特定的字节传输大小断开连接。一切似乎都是零星的。您可以在单个连接上发送的数据传输或有效负载计数是否有某些限制?看到人们的解决方案始终保持一个连接打开,我认为这不是问题所在。我看到连接在3次通知后断开,我看到它在14次通知后断开。我从未见过它能超过14点。有没有人遇到过这种类型的问题?如何处理?

  7. ruby - 如何断开现有的 ruby​​ 续集与数据库的连接? - 2

    我的意思是之前建立的那个DB=Sequel.sqlite('my_blog.db')或DB=Sequel.connect('postgres://user:password@localhost/my_db')或DB=Sequel.postgres('my_db',:user=>'user',:password=>'password',:host=>'localhost')等等。Sequel::Database类没有名为“disconnect”的公共(public)实例方法,尽管它有一个“connect”。也许有人已经遇到过这个问题。我将不胜感激。 最佳答案

  8. ruby-on-rails - 遗留数据库的 ActiveRecord 连接表 - 2

    我有一个遗留数据库,我正在努力让ActiveRecord使用它。我遇到了连接表的问题。我有以下内容:classTvShow然后我有一个名为tvshowlinkepisode的表,它有2个字段:idShow、idEpisode所以我有2个表和它们之间的连接(多对多关系),但是连接使用非标准外键。我的第一个想法是创建一个名为TvShowEpisodeLink的模型,但没有主键。我的想法是,由于外键是非标准的,我可以使用set_foreign_key并进行一些控制。最后,我想说一些类似TvShow.find(:last).episodes或Episode.find(:last).tv_sho

  9. ruby - rails 3.2.2(或 3.2.1)+ Postgresql 9.1.3 + Ubuntu 11.10 连接错误 - 2

    我正在使用PostgreSQL9.1.3(x86_64-pc-linux-gnu上的PostgreSQL9.1.3,由gcc-4.6.real(Ubuntu/Linaro4.6.1-9ubuntu3)4.6.1,64位编译)和在ubuntu11.10上运行3.2.2或3.2.1。现在,我可以使用以下命令连接PostgreSQLsupostgres输入密码我可以看到postgres=#我将以下详细信息放在我的config/database.yml中并执行“railsdb”,它工作正常。开发:adapter:postgresqlencoding:utf8reconnect:falsedat

  10. Ruby:如何将条件插入字符串连接 - 2

    在字符串连接中,是否可以直接在语句中包含条件?在下面的示例中,我希望仅当dear列表不为空时才连接"mydear"。dear=""string="hello"+"mydear"unlessdear.empty?+",goodmorning!"但是结果报错:undefinedmethod'+'fortrue我知道另一种方法是在这条语句之前定义一个额外的变量,但我想避免这种情况。 最佳答案 使用插值而不是连接更容易和更具可读性:dear=""string="hello#{'mydear'unlessdear.empty?},goodmo

随机推荐