• 定位解决dubboadmin本地启动很慢问题


    场景

    尝试本地IDEA启动dubbo-admin,连接到测试环境的zookeeper,查看各微服务情况。
    等了几分钟发现仍未启动成功,日志里不断打印[DUBBO] Subscribe...信息。
    而成功启动应打印
    Tomcat started on port(s): 7001 (http) with context path ''
    Started DubboAdminApplication in xxx seconds...

    分析

    日志里一直在打印订阅(subscribe)相关信息,而测试环境dubbo-admin的启动却很快,不到1分钟启动完成。
    dubbo-admin里有个RegistryServerSync类,实现了InitializingBean,DisposableBean,NotifyListener3个接口,
    其中在InitializingBeanafterPropertiesSet方法:

    public void afterPropertiesSet() throws Exception {
        logger.info("Init Dubbo Admin Sync Cache...");
        registryService.subscribe(SUBSCRIBE, this);
    }
    

    其中registryService是注入到Spring容器的:

    @Autowired
    private RegistryService registryService;
    

    在dubbo-admin应用的application.properties文件里配置了注册中心类型和地址:

    dubbo.registry.address=zookeeper://192.168.20.4:2181
    

    通过Dubbo的SPI,接口RegistryService的实现类是ZookeeperRegistry,注意到它实现其父抽象类FailbackRegistry
    doSubscribe方法中,是通过for循环遍历服务逐个处理的,测试环境的zookeeper在阿里云内网服务器上,本地公司内网与阿里云内网
    有大概20-30ms左右的延迟(通过ping命令和咨询负责网络运维的同事得知),而测试环境注册的服务有几百个,这是启动慢的原因所在。

    解决

    思路: 自定义一个类跟ZookeeperRegistry类似,单线程遍历处理改为多线程并发处理。

    步骤:

    1. 新建MyZookeeperRegistry类继承FailbackRegistry类,将原ZookeeperRegistry类的代码拷过来进行修改
      关键代码如下:
    private ExecutorService es = Executors.newFixedThreadPool(50);
    ...
    List<String> services = zkClient.addChildListener(root, zkListener);
    if (services != null && !services.isEmpty()) {
        long totalStart = System.currentTimeMillis();
        for (String service : services) {
            service = URL.decode(service);
            anyServices.add(service);
    
            String finalService = service;
            es.submit(new Runnable() {
                @Override
                public void run() {
                    long start = System.currentTimeMillis();
                    subscribe(url.setPath(finalService).addParameters(Constants.INTERFACE_KEY, finalService,
                            Constants.CHECK_KEY, String.valueOf(false)), listener);
                    logger.info("subscribe cost=" + (System.currentTimeMillis() - start) + "ms" + ",url=" + url);
                }
            });
        }
    
        es.shutdown();
        if (!es.awaitTermination(1, TimeUnit.MINUTES)) {
            es.shutdownNow();
        }
        logger.info("subscribe all done,cost=" + (System.currentTimeMillis() - totalStart) + "ms");
    }
    

    注:

    • 这里使用固定线程池用50个线程来并发处理订阅
    • 通过线程池提供的shutdown,awaitTermination,shutdownNow3个方法来实现主线程等待子线程执行,设置等待超时时间,并且打印总耗时
    1. 修改application.properties配置文件,使用自定义的MyZookeeperRegistry
      dubbo.registry.address=zookeeper://xxx:2181
      修改为:
      dubbo.registry.address=myzookeeper://xxx:2181

    2. 重启应用大概20多秒启动成功

    问题解决:)

  • 相关阅读:
    css居中问题(转)
    Request.ServerVariables 各个参数的用法
    html5 画个球碰撞
    递归生成json
    AspNetPager分页结合存储过程的用法
    sql+aspnetpager+查询功能
    求1+2+……+n
    几种排序的比较 bitmapsort,qsort,set
    利用两个栈,反转其中一个栈的元素
    进程间通信(IPC, Inter Process Communication)读书笔记
  • 原文地址:https://www.cnblogs.com/cdfive2018/p/15625403.html
Copyright © 2020-2023  润新知