文档章节

Trafodion null 问题的源码级剖析

blacklovebear
 blacklovebear
发布于 2017/01/20 15:15
字数 4340
阅读 440
收藏 6

一、问题描述

无论是通过 JDBC 还是通过 命令行连接 Trafodion ,总是偶尔出现 unable to evaluate address TCP:null 的异常。

二、错误信息

org.trafodion.jdbc.t4.HPT4Exception: Unable to evaluate address TCP:null:1.$Z010B5Z,null/23403:ODBC Cause: null
Connecting to database...
	at org.trafodion.jdbc.t4.HPT4Messages.createSQLException(HPT4Messages.java:284)
	at org.trafodion.jdbc.t4.HPT4Messages.createSQLException(HPT4Messages.java:232)
	at org.trafodion.jdbc.t4.Address.validateAddress(Address.java:97)
	at org.trafodion.jdbc.t4.ConnectReply.fixupSrvrObjRef(ConnectReply.java:137)
	at org.trafodion.jdbc.t4.T4_Dcs_Connect.getConnection(T4_Dcs_Connect.java:98)
	at org.trafodion.jdbc.t4.InterfaceConnection.connect(InterfaceConnection.java:791)
	at org.trafodion.jdbc.t4.InterfaceConnection.<init>(InterfaceConnection.java:176)
	at org.trafodion.jdbc.t4.TrafT4Connection.makeConnection(TrafT4Connection.java:1611)
	at org.trafodion.jdbc.t4.TrafT4Connection.<init>(TrafT4Connection.java:1564)
	at org.trafodion.jdbc.t4.HPT4DataSource.getConnection(HPT4DataSource.java:132)
	at org.trafodion.jdbc.t4.HPT4DataSource.getConnection(HPT4DataSource.java:176)
	at org.trafodion.jdbc.t4.T4Driver.connect(T4Driver.java:186)
	at java.sql.DriverManager.getConnection(DriverManager.java:571)
	at java.sql.DriverManager.getConnection(DriverManager.java:215)
	at TrafodionConn.run(TrafodionConn.java:22)
	at TrafodionConn.main(TrafodionConn.java:81)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)

三、问题分析

之前一直有个错误的想法,认为是 JDBC 驱动包的问题,一直在找Trafodion 的源代码来分析,追踪了好久都找不到问题所在

后来听同事说,用服务器的上的命令行连接也会报错,就测试了下发现果然报错(注意有两个错误信息),错误信息如下:

Host Name/IP Address: xdata67:23400
User Name: zz

*** ERROR[29111] Unable to evaluate address TCP:null:1.$Z010B5H,null/23402:ODBC Cause: null: 未知的名称或服务


*** ERROR[29111] Unable to evaluate address TCP:null:1.$Z010B5Z,null/23403:ODBC Cause: null

了解到这个信息就知道了不是 JDBC 驱动的问题,应该是 Trafodion 的某个服务异常导致的。

四、问题定位

  • 初步分析

通过观察,偶然发现 $Z010B5Z 这个很熟悉,好像在之前对 Trafodion 进行管理的时候见过。

立马在 Trafodion 安装的集群上 执行 sqps 命令,查看当前 Trafodion 的进程信息

[trafodion@xdata67 scripts]$ sqps
Processing cluster.conf on local host xdata67
[$Z00152S] Shell/shell Version 1.0.1 Apache_Trafodion Release 2.0.1 (Build release [DEV], date 24Jun16)
[$Z00152S] %ps  
[$Z00152S] NID,PID(os)  PRI TYPE STATES  NAME        PARENT      PROGRAM
[$Z00152S] ------------ --- ---- ------- ----------- ----------- ---------------
[$Z00152S] 000,00038200 000 WDG  ES--A-- $WDG000     NONE        sqwatchdog     
[$Z00152S] 000,00038201 000 PSD  ES--A-- $PSD000     NONE        pstartd        
[$Z00152S] 000,00038334 001 GEN  ES--A-- $TSID0      NONE        idtmsrv        
[$Z00152S] 000,00038349 001 DTM  ES--A-- $TM0        NONE        tm             
[$Z00152S] 000,00039024 001 GEN  ES--A-- $ZSC000     NONE        mxsscp         
[$Z00152S] 000,00039202 001 SSMP ES--A-- $ZSM000     NONE        mxssmp         
[$Z00152S] 000,00045613 001 GEN  ES--A-- $Z001288    NONE        mxosrvr        
[$Z00152S] 000,00045638 001 GEN  ES--A-- $Z00128Y    NONE        mxosrvr        
[$Z00152S] 000,00049097 001 GEN  ES--A-- $Z00152S    NONE        shell          
[$Z00152S] 001,00008006 000 WDG  ES--A-- $WDG001     NONE        sqwatchdog     
[$Z00152S] 001,00008007 000 PSD  ES--A-- $PSD001     NONE        pstartd        
[$Z00152S] 001,00008132 001 DTM  ES--A-- $TM1        NONE        tm             
[$Z00152S] 001,00008597 001 GEN  ES--A-- $ZSC001     NONE        mxsscp         
[$Z00152S] 001,00008702 001 SSMP ES--A-- $ZSM001     NONE        mxssmp         
[$Z00152S] 001,00013667 001 GEN  ES--A-- $Z010B5H    NONE        mxosrvr       --果然在这里    
[$Z00152S] 001,00013684 001 GEN  ES--A-- $Z010B5Z    NONE        mxosrvr       --果然在这里
[$Z00152S] 002,00026976 000 PSD  ES--A-- $PSD002     NONE        pstartd        
[$Z00152S] 002,00026975 000 WDG  ES--A-- $WDG002     NONE        sqwatchdog     
......

惊喜的发现了上面的信息,看信息应该是 mxosrvr 的进程名称,发现前面有进程的 pid 号,下一步通过 pid 查找 对应的 mxosrvr 在那台机器上,因为 Trafodion 是分布式是系统,各进程分布在集群各个机器上。【文末分析为什么连接 Trafodion 进程 会定位连接到 mxosrvr 进程,这里就不打断】

[trafodion@xdata67 scripts]$ pdsh -w xdata[67-71] ps -ef | grep 13684 | grep -v grep
xdata68: 503      13684 13483  0 09:31 ?        00:00:01 mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181 -RZ null:2:1 -ZKPNODE /trafodion -CNGTO 60 -ZKSTO 180 -EADSCO 0 -TCPADD null -MAXHEAPPCT 0 -STATISTICSINTERVAL 60 -STATISTICSLIMIT 60 -STATISTICSTYPE aggregated -STATISTICSENABLE true -SQLPLAN true -PORTMAPTOSECS -1 -PORTBINDTOSECS -1
[trafodion@xdata67 scripts]$ pdsh -w xdata[67-71] ps -ef | grep 13667 | grep -v grep
xdata68: 503      13667 13456  0 09:31 ?        00:00:01 mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181 -RZ null:2:2 -ZKPNODE /trafodion -CNGTO 60 -ZKSTO 180 -EADSCO 0 -TCPADD null -MAXHEAPPCT 0 -STATISTICSINTERVAL 60 -STATISTICSLIMIT 60 -STATISTICSTYPE aggregated -STATISTICSENABLE true -SQLPLAN true -PORTMAPTOSECS -1 -PORTBINDTOSECS -1

通过定位发现两个出错的 mxosrvr 都在 xdata68 这台机器上,第一时间的想法 - 难道只是巧合?

于是重启 Trafodion的 DCS服务(mxosrvr的名称会变) 又执行上面的流程测试了一遍,发现出错的mxosrvr 进程还是在 xdata68 机器上,这些肯定了应该不是偶然,和xdata68 这台机器的特殊环境应该有关系。

知道问题所在心里就有底多了,知道至少找对路了。这里可以总结一个问题定位心得 :对于偶然出现的问题一定要找出问题的规律。

  • 深入分析

找到了出错的进程,就想这两个进程和其他机器上的正常的进程有什么区别呢?

于是就查了下 xdata68(异常机器)的 mxosrvr 进程信息:

[trafodion@xdata68 conf]$ ps -ef | grep mxosrvr
503      13456  9801  0 09:31 ?        00:00:00 /bin/sh -c cd /home/trafodion/apache-trafodion_server;. sqenv.sh;mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181  -RZ null:2:2  -ZKPNODE "/trafodion"  -CNGTO 60  -ZKSTO 180  -EADSCO 0  -TCPADD null  -MAXHEAPPCT 0  -STATISTICSINTERVAL 60  -STATISTICSLIMIT 60  -STATISTICSTYPE aggregated  -STATISTICSENABLE true  -SQLPLAN true  -PORTMAPTOSECS -1  -PORTBINDTOSECS -1
503      13483  9801  0 09:31 ?        00:00:00 /bin/sh -c cd /home/trafodion/apache-trafodion_server;. sqenv.sh;mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181  -RZ null:2:1  -ZKPNODE "/trafodion"  -CNGTO 60  -ZKSTO 180  -EADSCO 0  -TCPADD null  -MAXHEAPPCT 0  -STATISTICSINTERVAL 60  -STATISTICSLIMIT 60  -STATISTICSTYPE aggregated  -STATISTICSENABLE true  -SQLPLAN true  -PORTMAPTOSECS -1  -PORTBINDTOSECS -1
503      13667 13456  0 09:31 ?        00:00:02 mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181 -RZ null:2:2 -ZKPNODE /trafodion -CNGTO 60 -ZKSTO 180 -EADSCO 0 -TCPADD null -MAXHEAPPCT 0 -STATISTICSINTERVAL 60 -STATISTICSLIMIT 60 -STATISTICSTYPE aggregated -STATISTICSENABLE true -SQLPLAN true -PORTMAPTOSECS -1 -PORTBINDTOSECS -1
503      13684 13483  0 09:31 ?        00:00:02 mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181 -RZ null:2:1 -ZKPNODE /trafodion -CNGTO 60 -ZKSTO 180 -EADSCO 0 -TCPADD null -MAXHEAPPCT 0 -STATISTICSINTERVAL 60 -STATISTICSLIMIT 60 -STATISTICSTYPE aggregated -STATISTICSENABLE true -SQLPLAN true -PORTMAPTOSECS -1 -PORTBINDTOSECS -1
503      26101 57226  0 10:14 pts/1    00:00:00 grep mxosrv

xdata70 (正常机器) 的 mxosrvr 进程信息:

[trafodion@xdata70 conf]$ ps -ef | grep mxosrvr
503      55695 52775  0 09:31 ?        00:00:00 /bin/sh -c cd /home/trafodion/apache-trafodion_server;. sqenv.sh;mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181  -RZ xdata70:4:2  -ZKPNODE "/trafodion"  -CNGTO 60  -ZKSTO 180  -EADSCO 0  -TCPADD 172.18.84.70  -MAXHEAPPCT 0  -STATISTICSINTERVAL 60  -STATISTICSLIMIT 60  -STATISTICSTYPE aggregated  -STATISTICSENABLE true  -SQLPLAN true  -PORTMAPTOSECS -1  -PORTBINDTOSECS -1
503      55772 52775  0 09:31 ?        00:00:00 /bin/sh -c cd /home/trafodion/apache-trafodion_server;. sqenv.sh;mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181  -RZ xdata70:4:1  -ZKPNODE "/trafodion"  -CNGTO 60  -ZKSTO 180  -EADSCO 0  -TCPADD 172.18.84.70  -MAXHEAPPCT 0  -STATISTICSINTERVAL 60  -STATISTICSLIMIT 60  -STATISTICSTYPE aggregated  -STATISTICSENABLE true  -SQLPLAN true  -PORTMAPTOSECS -1  -PORTBINDTOSECS -1
503      56060 55695  0 09:31 ?        00:00:11 mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181 -RZ xdata70:4:2 -ZKPNODE /trafodion -CNGTO 60 -ZKSTO 180 -EADSCO 0 -TCPADD 172.18.84.70 -MAXHEAPPCT 0 -STATISTICSINTERVAL 60 -STATISTICSLIMIT 60 -STATISTICSTYPE aggregated -STATISTICSENABLE true -SQLPLAN true -PORTMAPTOSECS -1 -PORTBINDTOSECS -1
503      56135 55772  0 09:31 ?        00:00:13 mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181 -RZ xdata70:4:1 -ZKPNODE /trafodion -CNGTO 60 -ZKSTO 180 -EADSCO 0 -TCPADD 172.18.84.70 -MAXHEAPPCT 0 -STATISTICSINTERVAL 60 -STATISTICSLIMIT 60 -STATISTICSTYPE aggregated -STATISTICSENABLE true -SQLPLAN true -PORTMAPTOSECS -1 -PORTBINDTOSECS -1
503      61947 22497  0 10:14 pts/0    00:00:00 grep mxosrvr

通过对比发现 68 机器 有个RZ参数为null, 而 70 机器传了准确的值

对,就是这里了,终于找到问题了。

为什么 68 这台机器 这个 -RZ 参数会是 null 呢?这个参数从哪里传过来的?

面对这两个问题,就去继续扒。顺着 mxosrvr 的父进程ID就去找,发现 mxosrvr 是通过一个 sh 启动的,而这个 sh 又是谁启动的呢?

通过 sh 进程的父进程 ID 找到是如下一个进程

通过我对 Trafodion 的了解和对以上信息的判断,上面找到的进程就是各个机器上的 DCS Server 进程,这个时候就必须补上Trafodion 的架构图了,不然后面没办法讲了

Trafodion Process Architecture

“trafodion dcs”的图片搜索结果

通过上面两种图,就可以很清晰的明白,mxosrvr 是由各个机器上的 Dcs Server 进程来启动的。理解了上面的信息,就来继续回答上面的问题,为什么 启动 mxosrvr 进程带的 -RZ 参数是 null 呢?

要回答这个问题,就只能深入到 Trafodion 的源代码了。来,源代码走起。

  • 源码分析

接下来就进入我们的源代码分析阶段,首先申明,这里分析的 Trafodion 源代码只是和我们问题相关的部分,所以大家看的时候显得有些跳脱,不过没关系,能解决我们的问题就可以。如果大家想对 Trafodion 有更深入的了解,还只能系统的去分析源码。

和本问题相关的源代码结构大致简化如下:

了解了大概结构,接下来我们看和我们问题具体相关的地方,我们先找到,在代码什么地方会启动上面我们分析的 sh 命令,就下面这条,我们的 mxosrvr 进程就是这条命令启动的。

/bin/sh -c cd /home/trafodion/apache-trafodion_server;. sqenv.sh;mxosrvr -ZKHOST xdata67:2181,xdata68:2181,xdata69:2181  -RZ null:2:2  -ZKPNODE "/trafodion"  -CNGTO 60  -ZKSTO 180  -EADSCO 0  -TCPADD null  -MAXHEAPPCT 0  -STATISTICSINTERVAL 60  -STATISTICSLIMIT 60  -STATISTICSTYPE aggregated  -STATISTICSENABLE true  -SQLPLAN true  -PORTMAPTOSECS -1  -PORTBINDTOSECS -1

通过对代码的搜索,我们在文件 Constants.java 文件中找到如下这行

    /** Default value for DCS server user program command */
    public static final String DEFAULT_DCS_SERVER_USER_PROGRAM_COMMAND = "cd ${dcs.user.program.home};. sqenv.sh;mxosrvr -ZKHOST -RZ -ZKPNODE -CNGTO -ZKSTO -EADSCO -TCPADD -MAXHEAPPCT -STATISTICSINTERVAL -STATISTICSLIMIT -STATISTICSTYPE -STATISTICSENABLE -SQLPLAN -PORTMAPTOSECS -PORTBINDTOSECS";

这就是启动 sh 的那条命令,接下来我们查找这个变量在哪里使用的,我们在 ServerManger.java 中找到了

 private void featureCheck() {
        ......

        boolean ready = false;
        while (!ready) {
            userProgEnabled = conf.getBoolean(
                    Constants.DCS_SERVER_USER_PROGRAM,
                    Constants.DEFAULT_DCS_SERVER_USER_PROGRAM);
            userProgramHome = System.getProperty("dcs.user.program.home");
            userProgramCommand = conf.get(
                    Constants.DCS_SERVER_USER_PROGRAM_COMMAND,
                    Constants.DEFAULT_DCS_SERVER_USER_PROGRAM_COMMAND);   // 就是这里使用的
           ......
        }

        LOG.info("User program enabled");
    }

我们来理解下这里的逻辑,从配置文件 conf(暂时就认为它为空,后续我们会看到它的内容)看我们是否配置了sh命令,如果没有配置就取我们上面看到的默认的命令。如果细心的读者应该发现,上面的 sh 命令只有参数但是没有值啊?这个值是什么时候加上去的? 就找到了 -RZ 这个参数的值为什么为 null 。

我们继续找,就在同一个文件的上面,我们找到了如下这段代码

public ServerRunner(int childInstance, String registeredPath) {
            ......

            String command = userProgramCommand
                    .replace("-ZKHOST", "-ZKHOST " + zkc.getZkQuorum() + " ")
                    .replace(
                            "-RZ",         // 就是这个参数,找的好辛苦啊
                            "-RZ " + hostName + ":" + instance + ":"
                                    + childInstance + " ")
                    .replace("-ZKPNODE",
                            "-ZKPNODE " + "\"" + parentZnode + "\"" + " ")
                    .replace("-CNGTO", "-CNGTO " + connectingTimeout + " ")
                    .replace("-ZKSTO", "-ZKSTO " + zkSessionTimeout + " ")
            ......
        }

这段代码是 ServerRunner的构造函数,它在这里对 userProgramCommand 做了替换,把参数的值放上了。这里我们看到了牵挂已久的 -RZ 参数,我们看到它的值是 hostName。那我们继续找 hostName

public ServerManager(Configuration conf, ZkClient zkc,
            DcsNetworkConfiguration netConf, String instance, int infoPort,
            int childServers) throws Exception {
        this.conf = conf;            // 这就是我们上面看到的是否配置 sh 命令的配置文件
        this.zkc = zkc;
        this.netConf = netConf;
        this.hostName = netConf.getHostName();   // 我们hostName 来的地方
        this.instance = Integer.parseInt(instance);
        this.infoPort = infoPort;
        this.childServers = childServers;

我们发现,两个重要的参数值都是通过 ServerManager 的构造函数给赋值的,我们接下来找ServerManager 调用的地方。

try {
		   	netConf = new DcsNetworkConfiguration(conf);
			serverName = netConf.getHostName();
			..... 
			pool = Executors.newSingleThreadExecutor();
			serverManager = new ServerManager(conf,zkc,netConf,instance,infoPort,childServers);
		    Future future = pool.submit(serverManager);
		    future.get();
		} catch (Exception e) {

我们在 DcsServer.java 的 run()中找到了这么一段代码,我们只关心 ServerManager 的第一个和第三个参数,并且我们发现 netConf 也是从 conf 中来的。但我们还是最关心 netConf.getHostName(),也就是hostName的值等于啥。

我们继续深入DcsNetworkConfiguration

// Constants.java
/** Configuration key for DCS DNS interface */
    public static final String DCS_DNS_INTERFACE = "dcs.dns.interface";
    /** Default value for DCS DNS interface */
    public static final String DEFAULT_DCS_DNS_INTERFACE = "default";
///////////// 

public String getHostName() {
        return canonicalHostName;     // 真实的值
    }

public void getCanonicalHostName(NetworkInterface ni, InetAddress inet)
            throws Exception {
        ......
        canonicalHostName = inet.getCanonicalHostName();      // 赋值
        ......
    }

public DcsNetworkConfiguration(Configuration conf) throws Exception {
        ......
        String dcsDnsInterface = conf.get(Constants.DCS_DNS_INTERFACE,
                Constants.DEFAULT_DCS_DNS_INTERFACE);
        if (dcsDnsInterface.equalsIgnoreCase("default")) {
            intHostAddress = extHostAddress = ia.getHostAddress();
            canonicalHostName = ia.getCanonicalHostName();   // 有可能的赋值
            ......
        } else {
            // For all nics get all hostnames and addresses
            // and try to match against dcs.dns.interface property
            Enumeration<NetworkInterface> nics = NetworkInterface
                    .getNetworkInterfaces();
            while (nics.hasMoreElements() && !matchedInterface) {
                InetAddress inet = null;
                NetworkInterface ni = nics.nextElement();
                ......
                if (dcsDnsInterface.equalsIgnoreCase(ni.getDisplayName())) {
                    ......
                    inet = getInetAddress(ni);
                    getCanonicalHostName(ni, inet);   // 有可能的赋值
                    extInterfaceName = ni.getDisplayName();
                } else {

DcsNetworkConfiguration.java 在这个文件中 对 canonicalHostName 处理还是比较复杂,我们发现有两处可能的赋值,决定的关键是 看配置文件 conf 是否配置 dcs.dns.interface 这个变量。

好了,到了这里我们发现,几处很重要的地方都指向了conf 这个配置文件,那到底这个conf 文件是啥,它里面又是什么内容?

要找到 conf 从什么时候开始赋值的,还得从源头开始找,于是就在 DcsServer.java 中找到了如下代码

public DcsServer(String[] args) {
		this.args = args;
	   	conf = DcsConfiguration.create();          // 这里
		jvmShutdownHook = new JVMShutdownHook();
		Runtime.getRuntime().addShutdownHook(jvmShutdownHook);
		thrd = new Thread(this);
		thrd.start();
	}

找到后我们继续深入 DcsConfiguration 

 public static Configuration addWmsResources(Configuration conf) {
    conf.addResource("dcs-default.xml");     //就是这里
    conf.addResource("dcs-site.xml");        //就是这里

    return conf;
  }

  /**
   * Creates a Configuration with Dcs resources
   * @return a Configuration with Dcs resources
   */
  public static Configuration create() {
    Configuration conf = new Configuration();
    return addWmsResources(conf);
  }

看到这里,我们就明白了原来 conf 是从这两个文件来的,那这两个文件在哪呢?

我们发现在 DcsServer 启动的时候带了如下这么一个参数,这就知道在哪了。

-Ddcs.conf.dir=/home/trafodion/apache-trafodion_server/dcs-2.0.1/bin/../conf 

知道在哪了,那我们就看看 xdata68 这台机器上的配置文件的内容。打开这个目录发现只有 dcs-site.xml 一个配置文件,内容如下

<configuration>
  <property>
    <name>dcs.zookeeper.quorum</name>
    <value>xdata67,xdata68,xdata69</value>
  </property>
   <property>
    <name>dcs.dns.interface</name>
    <value>eth0</value>
  </property>
</configuration>

知道配置文件的内容,那我们再回过头来看看,在 DcsNetworkConfiguration 中我们得到 hostName 的详细逻辑,我在这再贴下 DcsNetworkConfiguration 中处理这部分的逻辑。

// Constants.java
/** Configuration key for DCS DNS interface */
    public static final String DCS_DNS_INTERFACE = "dcs.dns.interface";
    /** Default value for DCS DNS interface */
    public static final String DEFAULT_DCS_DNS_INTERFACE = "default";
///////////// 

public String getHostName() {
        return canonicalHostName;     // 真实的值
    }

public void getCanonicalHostName(NetworkInterface ni, InetAddress inet)
            throws Exception {
        intHostAddress = extHostAddress = inet.getHostAddress();
        canonicalHostName = inet.getCanonicalHostName();      // 赋值
        ......
    }

public DcsNetworkConfiguration(Configuration conf) throws Exception {

        this.conf = conf;
        ia = InetAddress.getLocalHost();
        
        // 我们发现配置文件中刚好对 dcs.dns.interface 进行赋值了, 为 eth0
        String dcsDnsInterface = conf.get(Constants.DCS_DNS_INTERFACE,
                Constants.DEFAULT_DCS_DNS_INTERFACE);
        if (dcsDnsInterface.equalsIgnoreCase("default")) {  
            intHostAddress = extHostAddress = ia.getHostAddress();
            canonicalHostName = ia.getCanonicalHostName();   // 不可能的赋值
            extInterfaceName = NetworkInterface.getByInetAddress(ia)
                    .getDisplayName();
            ......
        } else {
            // For all nics get all hostnames and addresses
            // and try to match against dcs.dns.interface property
            Enumeration<NetworkInterface> nics = NetworkInterface
                    .getNetworkInterfaces();
            while (nics.hasMoreElements() && !matchedInterface) {
                InetAddress inet = null;
                NetworkInterface ni = nics.nextElement();
                ......
                if (dcsDnsInterface.equalsIgnoreCase(ni.getDisplayName())) {  // 是否等于 eth0
                    ......
                    inet = getInetAddress(ni);
                    getCanonicalHostName(ni, inet);   // 真正赋值的地方
                    extInterfaceName = ni.getDisplayName();
                } else {

通过对上面代码的详细分析,发现关键逻辑在于通过循环判断 NetworkInterface.getNetworkInterfaces() 中获取的项的 ni.getDisplayName() 是否 等于我们配置文件中的配置的 eth0。所以这里的逻辑是通过配置的网络接口名去找 hostName

  • 最终破案

接下来我们就看看 NetworkInterface.getNetworkInterfaces() 的结果到底是啥,于是随手写了如下代码在xdata68 上跑了下

import java.net.*;
import java.util.*;

public class Hello
{
    public static void main(String[] args) throws Exception
    {
        Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
        while (nis.hasMoreElements())
            System.out.println(nis.nextElement());
    }
}

结果

name:eth1 (eth1)
name:lo (lo)

所以从结果上来看就知道了,这个方法是获取机器上的所有网络接口。看到这里我们就有点奇怪了,为什么这里获取所有的网络接口中居然没有我们配置文件中配置的 eth0?

为了再次确认 在xdata68 上执行 ifconfig 命令查看了下,再对比 正常机器 xdata70

[trafodion@xdata68 ~]$ ifconfig 
eth1      Link encap:Ethernet  HWaddr 52:54:00:54:94:B5  
          inet addr:xxxxxxxx  Bcast:172.18.255.255  Mask:255.255.0.0
          inet6 addr: fe80::5054:ff:fe54:94b5/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8473656440 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3531432078 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1756961980786 (1.5 TiB)  TX bytes:1009432619090 (940.1 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:251663643 errors:0 dropped:0 overruns:0 frame:0
          TX packets:251663643 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:64908035275 (60.4 GiB)  TX bytes:64908035275 (60.4 GiB)


[trafodion@xdata70 conf]$ ifconfig
eth0      Link encap:Ethernet  HWaddr 52:54:00:A4:C5:92  
          inet addr:172.18.84.70  Bcast:172.18.255.255  Mask:255.255.0.0
          inet6 addr: fe80::5054:ff:fea4:c592/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:7984801625 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3127534521 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:1740020574559 (1.5 TiB)  TX bytes:956397150875 (890.7 GiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:74985186 errors:0 dropped:0 overruns:0 frame:0
          TX packets:74985186 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:61427646458 (57.2 GiB)  TX bytes:61427646458 (57.2 GiB)

 看到这里我们豁然开朗了,原来问题导致的原因是,xdata68 这台机器上比较特殊,没有配置 eth0这个网络接口,而我们的Trafodion dcs 的配置文件 dcs-site.xml 中统一配置的 eth0

知道了问题,解决办法就比较简单了,直接修改 dcs-site.xml 配置文件将 eth0 改成 eth1 就可以了。

五、最终总结

  1. 对问题做深入的观察
  2. 对不确定的问题找到确定的规律
  3. 对专业知识建立足够的认识,这样才会培养足够的敏感度
  4. 对问题进行深入锲而不舍的分析,即使扒遍源码也在所不惜(哈哈)
  5. 对问题的定位分析过程能很好的掌握技术本身

 

六、备注

这里分析下为什么连接 Trafodion 进程会定位连接到 mxosrvr 进程

通过上面给出的 Trafodion 的架构图了解到 Trafodion DCS( Database Connectivity Services)连接服务,是典型的分布式架构。

Dcs Master 负责监听连接(23400端口),当一个数据库连接到来的时候,先连接到 master,master 接受到连接后,分配给各个机器上的 mxosrvr 进程去处理和维护这个连接。相信大家可以参考官方文档的解释,如下:

-------------------------------------------------------------------------------------------------------------

Connectivity

The Database Connectivity Services (DCS) framework enables applications developed for ODBC/JDBC APIs to access a Trafodion SQL database server. DCS is a distributed service. It uses the underlying HBase ZooKeeper instance for its definition of a cluster. Apache ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. All participating nodes and clients need to be able to access the running ZooKeeper.

DCS is a collection of components:

  • ODBC/JDBC Drivers: Provide a standard programming language middle-ware API for accessing database management systems (DBMS).
  • DCS Master Process: The DCS Master server is responsible for monitoring all server instances in the cluster. It assigns an ODBC/JDBC client connection request to a Master Executor (MXOSRVR) process. It also has a backup process that takes over the Master Executor role during failures.
  • DCS Server Process: This process is responsible for starting and keeping a Master Executor (MXOSRVR) server process executing. There is one DCS Server process per node in the cluster.
  • Master Executor Process: This is the database server that provides database access to ODBC/JDBC clients. There is a one-to-one relationship between an ODBC/JDBC client connection and a database server process. The Master Executor performs all SQL queries on behalf of its client’s requests. It will perform all required SQL calls to execute a SQL query through the Executor to access HBase tables. The Master Executor is often referred to as MXOSRVR.

© 著作权归作者所有

blacklovebear

blacklovebear

粉丝 6
博文 29
码字总数 8955
作品 0
深圳
私信 提问
易鲸捷首架刘明:Trafodion值得放入工具箱,因为有以下优点

Trafodion是Apache基金会的一个开源项目,提供了一个成熟的企业级SQL-on-HBase解决方案。Trafodion的主要设计思想是处理operational类型的工作负载,或者是传统的OLTP应用。此外,对于需要保...

Mr_zebra
2018/06/21
43
0
分布式 SQL 引擎 Apache Trafodion 2.1.0 发布

Apache Trafodion 2.1.0 发布了,亮点包括: 新的 python 安装程序 集成 Ambari 以及更易于安装的 HDP 新功能、SQL 函数和语法扩展 性能增强 300+ bug 修复已解决 具体更新内容可查看发行日志...

王练
2017/05/06
1K
1
分布式 SQL 引擎 Apache Trafodion 2.2.0 发布

分布式 SQL 引擎 Apache Trafodion 2.2.0 发布,Apache Trafodion 是一个面向 Hadoop 的 Webscale SQL-on-Hadoop 解决方案,支持 Hadoop 上的事务或操作工作负载。 Trafodion 基于 Hadoop 的...

周其
2018/03/20
1K
0
PPT下载丨数据架构与优化沙龙精彩回顾

老规矩,PPT在这里! 云盘下载链接: https://pan.baidu.com/s/1SeDmRYWEdiDFYLrrxAFfw 随着大数据的发展,数据化变革已成为企业不可避免的挑战,如何选择变革的方向和方式、充分利用大数据资...

2018/08/08
0
0
Apache Trafodion——分布式 SQL 引擎

Trafodion提供了一个基于Hadoop平台的交易型分布式SQL引擎。它是一个擅长处理交易型负载的Hadoop大数据解决方案。其主要特性包括: 完整的ANSI SQL 92/99语言支持 完整的ACID事务支持。对于读...

oschina
2016/07/18
35
0

没有更多内容

加载失败,请刷新页面

加载更多

《Designing.Data-Intensive.Applications》笔记 四

第九章 一致性与共识 分布式系统最重要的的抽象之一是共识(consensus):让所有的节点对某件事达成一致。 最终一致性(eventual consistency)只提供较弱的保证,需要探索更高的一致性保证(stro...

丰田破产标志
今天
6
0
docker 使用mysql

1, 进入容器 比如 myslq1 里面进行操作 docker exec -it mysql1 /bin/bash 2. 退出 容器 交互: exit 3. mysql 启动在容器里面,并且 可以本地连接mysql docker run --name mysql1 --env MY...

之渊
今天
7
0
python数据结构

1、字符串及其方法(案例来自Python-100-Days) def main(): str1 = 'hello, world!' # 通过len函数计算字符串的长度 print(len(str1)) # 13 # 获得字符串首字母大写的...

huijue
今天
5
0
OSChina 周日乱弹 —— 我,小小编辑,食人族酋长

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享娃娃的单曲《飘洋过海来看你》: #今日歌曲推荐# 《飘洋过海来看你》- 娃娃 手机党少年们想听歌,请使劲儿戳(这里) @宇辰OSC...

小小编辑
今天
1K
11
MongoDB系列-- SpringBoot 中对 MongoDB 的 基本操作

SpringBoot 中对 MongoDB 的 基本操作 Database 库的创建 首先 在MongoDB 操作客户端 Robo 3T 中 创建数据库: 增加用户User: 创建 Collections 集合(类似mysql 中的 表): 后面我们大部分都...

TcWong
今天
40
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部