ZK节点中生产者和消费者详细信息获取及导出

1 篇文章 0 订阅

    首先说说业务需求场景,在公司产品不断演进和迭代的过程中,由初始的轻量级一体化小服务迅速发展,在业务体量的推进中整个产品也很快变得臃肿起来,给日常迭代和维护带来了很大负担。

    再之后产品为了更好的服务于业务,演变为微服务体系,于是原本糅杂于一体的服务模块按照业务或者功能规则开始拆分,因此应用数量井喷式增加,几百个应用分工合作,看似和谐的提供服务。

     接下来由于服务数量太多,开发以及运维人员发现由于服务之间相互依赖等原因,日常发布也还能勉强,一旦有机房迁移的时候,根本理不清服务之间复杂的依赖关系,这时候就需要有一个过程来梳理服务之间的依赖,然后分析归纳,进行基础服务下沉等骚操作,规划出后台、中台、前台等,

      今天要说的就是梳理服务依赖时数据采集的过程,以下是我自己做这些的大概思路和代码,仅供有需要的同学参考:

核心代码如下:

package com.dubbocheck;

import com.alibaba.fastjson.JSON;
import com.common.constants.ZtstConstants;
import com.common.utils.ZtstUtils;
import com.dubbocheck.dto.DcHostDto;
import com.dubbocheck.dto.DcProviderAllDto;
import com.dubbocheck.dto.DcProviderBaseDto;
import org.I0Itec.zkclient.ZkClient;
import org.I0Itec.zkclient.ZkConnection;
import org.mortbay.util.MultiMap;
import org.mortbay.util.UrlEncoded;

import java.io.*;
import java.net.URLDecoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author yanwei.shen
 * @title: ZKClientBase
 * @projectName howbuy-ztst
 * @description: TODO
 * @date 2019/10/2415:51
 */
public class ZKClientBase {
    private static Pattern pattern;
    private static Matcher matcher;
    /**
     * zookeeper地址
     */
    //static final String CONNECT_ADDR = "192.168.XXX.XXX:2181";//zk地址选择自己需要的,多个zk以逗号分隔,"192.168.1.XXX:2181,192.168.1.XXX:2181,192.168.1.XXX:2181"
    /**
     * session超时时间
     */
    static final int SESSION_OUTTIME = 10000;//ms

    public static String getString(String str) {
        int index = -1;
        char[] chars = str.toCharArray();
        if (chars != null) {
            for (int i = 0; i < chars.length; i++) {
                if ((chars[i] >= 'A') && (chars[i] <= 'Z')) {
                    index = i;
                    break;
                }
            }
        }
        return str.substring(0, index - 1);
    }

    /**
     * 解析dubbo中的provider集合
     *
     * @param zkClient
     * @param allDto
     */
    public static void parseProvider(ZkClient zkClient, DcProviderAllDto allDto) {
        if (zkClient != null && allDto != null) {
            String service = allDto.getService();
            List<DcProviderBaseDto> baseList = allDto.getList();
            Map<String, List<DcProviderBaseDto>> serviceMap = allDto.getServiceMap();

            if (service != null && !"".equals(service)) {
                //构建providers的zk路径
                String path = ZtstConstants.DUBBO_ROOT + "/" + service + ZtstConstants.DUBBO_PROVIDERS;
                //读取providers列表
                List<String> providerList = zkClient.getChildren(path);
                //循环解析
                DcProviderBaseDto baseDto;
                //定义临时变量
                DcHostDto hostDto;
                String host;
                Integer port;
                String hostStr;
                List<DcProviderBaseDto> hostList;
                for (String providerStr : providerList) {
                    //把provider的字符串转化成baseDto
                    System.out.println("provider:" + providerStr);
                    baseDto = parseProviderBase(providerStr);
                    if (baseDto != null) {
                        //添加至完整的list
                        if (baseList == null) {
                            //创建新对象时,allDto需要重新指向新对象 zt@2019-08-12
                            baseList = new ArrayList<>();
                            allDto.setList(baseList);
                        }
                        baseList.add(baseDto);
                        //如果有host,则添加一个host的map对象(其实肯定有host)
                        hostDto = baseDto.getDcHostDto();
                        if (hostDto != null) {
                            host = hostDto.getHost();
                            port = hostDto.getPort();
                            hostStr = host + ":" + port;
                            //填充map
                            if (serviceMap == null) {
                                //创建新对象时,allDto需要重新指向新对象 zt@2019-08-12
                                serviceMap = new HashMap<>();
                                allDto.setServiceMap(serviceMap);

                                hostList = new ArrayList<>();
                                serviceMap.put(hostStr, hostList);
                            } else {
                                hostList = serviceMap.get(hostStr);
                                if (hostList == null) {
                                    hostList = new ArrayList<>();
                                    serviceMap.put(hostStr, hostList);
                                }
                            }
                            hostList.add(baseDto);
                        }   //hostDto
                    }   //baseDto
                }   //for
            }   //service
        }   //null
    }

    /**
     * 解析dubbo中的consumer集合
     *
     * @param zkClient
     * @param allDto
     */
    public static void parseConsumers(ZkClient zkClient, DcProviderAllDto allDto) {
        if (zkClient != null && allDto != null) {
            String service = allDto.getService();
            List<DcProviderBaseDto> baseList = allDto.getList();
            Map<String, List<DcProviderBaseDto>> serviceMap = allDto.getServiceMap();

            if (service != null && !"".equals(service)) {
                //构建providers的zk路径
                String path = ZtstConstants.DUBBO_ROOT + "/" + service + ZtstConstants.DUBBO_CONSUMERS;
                //读取providers列表
                List<String> providerList = zkClient.getChildren(path);
                //循环解析
                DcProviderBaseDto baseDto;
                //定义临时变量
                DcHostDto hostDto;
                String host;
                Integer port;
                String hostStr;
                List<DcProviderBaseDto> hostList;
                for (String providerStr : providerList) {
                    //把provider的字符串转化成baseDto
                    System.out.println("consumer:" + providerStr);
                    baseDto = parseConsumersBase(providerStr);
                    if (baseDto != null) {
                        //添加至完整的list
                        if (baseList == null) {
                            //创建新对象时,allDto需要重新指向新对象 zt@2019-08-12
                            baseList = new ArrayList<>();
                            allDto.setList(baseList);
                        }
                        baseList.add(baseDto);
                        //如果有host,则添加一个host的map对象(其实肯定有host)
                        hostDto = baseDto.getDcHostDto();
                        if (hostDto != null) {
                            host = hostDto.getHost();
                            port = hostDto.getPort();
                            hostStr = host + ":" + port;
                            //填充map
                            if (serviceMap == null) {
                                //创建新对象时,allDto需要重新指向新对象 zt@2019-08-12
                                serviceMap = new HashMap<>();
                                allDto.setServiceMap(serviceMap);

                                hostList = new ArrayList<>();
                                serviceMap.put(hostStr, hostList);
                            } else {
                                hostList = serviceMap.get(hostStr);
                                if (hostList == null) {
                                    hostList = new ArrayList<>();
                                    serviceMap.put(hostStr, hostList);
                                }
                            }
                            hostList.add(baseDto);
                        }   //hostDto
                    }   //baseDto
                }   //for
            }   //service
        }   //null
    }

    /**
     * 把provider字符串转化成对象
     *
     * @param providerStr
     * @return
     */
    public static DcProviderBaseDto parseProviderBase(String providerStr) {
        DcProviderBaseDto baseDto = null;
        try {
            MultiMap multiMap = new MultiMap();
            String dubboUrl = URLDecoder.decode(providerStr, "UTF-8");
            int idx = dubboUrl.indexOf("?");
            String hostUrl = dubboUrl.substring(0, idx);
            String paraUrl = dubboUrl.substring(idx + 1);
            UrlEncoded.decodeTo(paraUrl, multiMap, "UTF-8");
            //手动解析base对象
            baseDto = JSON.parseObject(ZtstUtils.toJsonStr(multiMap), DcProviderBaseDto.class);

            //1、构建host和service
            if (hostUrl != null && !"".equals(hostUrl)) {
                String regex = "^dubbo://(.+):(.+)/(.+)$";
                pattern = Pattern.compile(regex);
                matcher = pattern.matcher(hostUrl);
                if (matcher.find()) {
                    String host = matcher.group(1);
                    String portStr = matcher.group(2);
                    String service = matcher.group(3);

                    int port = Integer.parseInt(portStr);

                    DcHostDto hostDto = new DcHostDto();
                    hostDto.setHost(host);
                    hostDto.setPort(port);
                    if (baseDto == null) {
                        baseDto = new DcProviderBaseDto();
                    }
                    baseDto.setDcHostDto(hostDto);
                    baseDto.setService(service);
                }
            }
            if (baseDto != null) {
                //2、解析method
                String methods = baseDto.getMethods();
                if (methods != null && !"".equals(methods)) {
                    List<String> methodList = Arrays.asList(methods.split(","));
                    baseDto.setMethodList(methodList);
                }

                //3、时间解析
                Long timestamp = baseDto.getTimestamp();
                if (timestamp != null) {
                    Calendar c = Calendar.getInstance();
                    c.setTimeInMillis(timestamp);
                    Date date = c.getTime();
                    baseDto.setDate(date);
                }
            }
        } catch (UnsupportedEncodingException e) {
            //log.error(">>>>dubbo url编码异常!", e);
        }

        return baseDto;
    }

    /**
     * 把provider字符串转化成对象
     *
     * @param providerStr
     * @return
     */
    public static DcProviderBaseDto parseConsumersBase(String providerStr) {
        DcProviderBaseDto baseDto = null;
        try {
            MultiMap multiMap = new MultiMap();
            String dubboUrl = URLDecoder.decode(providerStr, "UTF-8");
            int idx = dubboUrl.indexOf("?");
            String hostUrl = dubboUrl.substring(0, idx);
            String paraUrl = dubboUrl.substring(idx + 1);
            UrlEncoded.decodeTo(paraUrl, multiMap, "UTF-8");
            //手动解析base对象
            baseDto = JSON.parseObject(ZtstUtils.toJsonStr(multiMap), DcProviderBaseDto.class);

            //1、构建host和service
            if (hostUrl != null && !"".equals(hostUrl)) {
                String regex = "^consumer://(.+)/(.+)$";
                pattern = Pattern.compile(regex);
                matcher = pattern.matcher(hostUrl);
                if (matcher.find()) {
                    String host = matcher.group(1);
                    // String portStr = matcher.group(2);
                    String service = matcher.group(2);

                    //int port = Integer.parseInt(portStr);

                    DcHostDto hostDto = new DcHostDto();
                    hostDto.setHost(host);
                    //hostDto.setPort(port);
                    if (baseDto == null) {
                        baseDto = new DcProviderBaseDto();
                    }
                    baseDto.setDcHostDto(hostDto);
                    baseDto.setService(service);
                }
            }
            if (baseDto != null) {
                //2、解析method
                String methods = baseDto.getMethods();
                if (methods != null && !"".equals(methods)) {
                    List<String> methodList = Arrays.asList(methods.split(","));
                    baseDto.setMethodList(methodList);
                }

                //3、时间解析
                Long timestamp = baseDto.getTimestamp();
                if (timestamp != null) {
                    Calendar c = Calendar.getInstance();
                    c.setTimeInMillis(timestamp);
                    Date date = c.getTime();
                    baseDto.setDate(date);
                }
            }
        } catch (UnsupportedEncodingException e) {
            //log.error(">>>>dubbo url编码异常!", e);
        }

        return baseDto;
    }

    public static void main(String[] args) throws Exception {
        ZkClient zkc = new ZkClient(new ZkConnection(args[0]), SESSION_OUTTIME);
        PrintWriter out = null;
        int ss=0;
        try {
            out = new PrintWriter(new BufferedWriter(new FileWriter("packageNumber44.csv")));
            out.println("type,appName,facade,meaths");
            DcProviderAllDto allDto;
            if (zkc != null) {
                List<String> serviceList = zkc.getChildren(ZtstConstants.DUBBO_ROOT);
                allDto = new DcProviderAllDto();
                for (String service : serviceList) {
                    allDto.setService(service);
                    parseProvider(zkc, allDto);
                }
                for (DcProviderBaseDto dcProviderBaseDto : allDto.getList()) {
                    out.println("provider," + dcProviderBaseDto.getApplication() + "," + dcProviderBaseDto.getService() + "," + dcProviderBaseDto.getMethods().replaceAll(",", "|"));
                }
            }
            if (zkc != null) {
                List<String> serviceList = zkc.getChildren(ZtstConstants.DUBBO_ROOT);
                allDto = new DcProviderAllDto();
                for (String service : serviceList) {
                    allDto.setService(service);
                    parseConsumers(zkc, allDto);
                }
                for (DcProviderBaseDto dcProviderBaseDto : allDto.getList()) {
                    if(dcProviderBaseDto.getMethods()!=null){
                    out.println("consumer," + dcProviderBaseDto.getApplication() + "," + dcProviderBaseDto.getService() + "," + dcProviderBaseDto.getMethods().replaceAll(",", "|"));
                    }else{
                        ss++;
                        out.println("consumer," + dcProviderBaseDto.getApplication() + "," + dcProviderBaseDto.getService());
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            System.out.println(ss);
            if (out != null) {
                out.close();
            }
        }

    }
}

导出后的数据落库大概是这样:

最后展示到页面大概是这样:

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值