关于使用phoenix接入springboot做大数据入口那点事

这篇文章应该是集大成之作,期间的引用我都附上了地址,感谢CSDN中个各位有意无意间都帮我渡过了难关,渡人渡己,我希望自己的经验也能帮助更多人成长,毕竟国内用这个的公司应该不超过10家,大家互相帮助。

从需求说说,关于使用phoenix接入springboot做大数据入口那点事。

需求很简单,某年某月某日,我们需要做一个功能从大数据抽取到数据前端使用的。

 

方案之前开始只有一个,(后来由于方案一可能流产才有了方案2,这也导致后期临时方案比较仓促,导致部门内部有争议,后续再表。)

 

  1. 大数:(dataX)-->habase(phoenix<使得hbase支持sql语法>)-->微服务  ==> icenter调用
  2. 大数(dataX): -->mysql(<支持sql语法>)-->微服务               ==> icenter调用

 

 

在执行方案1时,不免遇到如下的一些问题,另由于使用phoenix组件的公司比较少,导致在CSDN等地方无法找到正确的解决方案(我基本上已经查询了百度所有相关关键词的前3页左右,然而大多数最后汇总都是那么几个,现在我就来回顾这一路上的问题)。

 

 

  1. 由于引入的phoenix包包含hadoop组件,最开始是使用普通的jar Export打包方式进行问题解决,然而发现java的Export-jar包始终有几个比较繁琐的问题。
  1. 使用Export打包jar文件,最常见的错误就是:

NoClassDefFoundError和ClassNotFoundException常见的两个错误区别:

https://blog.csdn.net/jamesjxin/article/details/46606307

 

大多数情况下,NoClassDefFoundError都是在Eclipse没有发生,但是运行环境下Linux发生了。说的比较轻巧,实际上调了很多坑的我还是稍微汇总了一下。

 

  1. 如果是引入了第三方包,但是报错找不到第三方包的情况:必须修改自动生成的manifest.mf文件,加入第三方包路径。请注意maniest的格式,以及linux文件号和windows的\\和/的区别。

   例如:

   必要的时候,需要把.jar包解压缩并修改Manifest.mf.

 

 2,如果引入的是自己写的第三方内容,如果在自己同一个包里面,记住Export为整个包,而不是单个main函数文件。如果不在同一个包里,则Export整个项目(目的是只有项目才包含所有包的相对路径)。

 

3,Linux需要配置classpath

解决办法:

由于没有配置Java 的classpath,所以我们需要配置classpath用文本编辑器打开/etc/profile 

在profile文件末尾加入: 

export JAVA_HOME=/usr/share/jdk1.6.0_14 

export PATH=$JAVA_HOME/bin:$PATH 

export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar 

 

 

 

  • 然而解决了这个些问题打出来的包(差不多花了4天),用户并不认可,他们需要通过服务访问。于是出现了下面这些问题:

 

(几个log系统对比:

https://blog.csdn.net/xudan1010/article/details/52890102

  1. springboot的logback和phoenix的log4j冲突,如果移除logback,springboot整个log系统都会瘫痪,且并不能解决问题,于是移除log4j,

  <exclusion>

                    <groupId>org.slf4j</groupId>

                    <artifactId>slf4j-log4j12</artifactId>

                </exclusion>

                <exclusion>

                    <groupId>log4j</groupId>

                    <artifactId>log4j</artifactId>

                </exclusion>  

https://blog.csdn.net/x4609883/article/details/80842155

 

 

原以为这样就解决问题了,然而上天并没有因为这样就停止对我们的折磨。出现问题:

   SpringBoot - Unable to Start embedded TomCat

 

(在这个工程中挣扎了很久,一方面移除logback肯定不行,另一方面如何确切的吧log4j移除也是一个大难事,另外slf4j-api不用移除,他是一个接口类,最终实现是log4j和logback二选一)

 

 

网上对于这个问题的解释可谓五花八门,但是归结下来,首先必须要进行的是排除log4j,于是,我么get了新技能,mvn dependency:tree >tree.txt

mvn dependency:tree -Dverbose -Dincludes=commons-collections(查看冲突的包)

http://www.cnblogs.com/ptqueen/p/7985198.html

 

 

 

(通常)好家伙,所有关键字log4j全部砍掉,以为行了吧。还是不行。

这个时候除了一个插曲,由于项目要得急,非得在这个阶段拿出解决方案,所以情急之下又先做了方案2,方案2其实很简单,2小时解决,用的是现成的方案,但是由于有了备选,则方案一也就有了冗余时间进行排错,最大的问题在于--我们知道跑不动是log系统冲突,但是到底其他的有没有冲突,怎么具体去一一解决,是没有办法预测时间的)。

  然后开始了漫长的搜索之路。之间有个引子,由于跟同事沟通过程中听说过类似的问题,不过问题是出在kafka上,所以根本上是解决冲突,而且整个公司内部都没有解决方案可以参考,这个时候,该怎么办?

  有了backup,我把精力聚焦到问题上来。

  这个时候,可以说运气使然,也可以说是“东方不亮西方亮”,我考虑到国内百度搜索效率低下,且很多企业没有这样的的条件使用phoenix情况下,于是我使用了bing,皇天不负苦心人,找到了下面一段代码。

 

排除了log4j之后,报错如下:

tomcat启动项目报错Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]

0

[已解决问题] 浏览: 8930次 解决于 2018-05-29 15:02 

严重: A child container failed during start
java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1239)
at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:819)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1700)
at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1690)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:162)
... 6 more
Caused by: java.lang.NoClassDefFoundError: Lorg/apache/log4j/Logger;

 

或者类似

Failed to instantiate SLF4J LoggerFactory

Reported exception:

java.lang.NoClassDefFoundError: org/apache/log4j/Level

    at org.slf4j.LoggerFactory.bind(LoggerFactory.java:128)

    at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:108)

    at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:279)

    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:252)

    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:265)

    at org.hibernate.cfg.Configuration.<clinit>(Configuration.java:165)

    at org.hibernate.ejb.Ejb3Configuration.<clinit>(Ejb3Configuration.java:127)

    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)

    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)

    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)

    at com.xeno.xecamp.desktopManagement.Main.main(Main.java:16)

Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Level

    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

    at java.security.AccessController.doPrivileged(Native Method)

    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)

    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

    at java.lang.ClassLoader.loadClass(ClassLoader.java:248)

    ... 11 more

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/log4j/Level

    at org.slf4j.LoggerFactory.bind(LoggerFactory.java:128)

    at org.slf4j.LoggerFactory.performInitialization(LoggerFactory.java:108)

    at org.slf4j.LoggerFactory.getILoggerFactory(LoggerFactory.java:279)

    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:252)

    at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:265)

    at org.hibernate.cfg.Configuration.<clinit>(Configuration.java:165)

    at org.hibernate.ejb.Ejb3Configuration.<clinit>(Ejb3Configuration.java:127)

    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:54)

    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)

    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)

    at com.xeno.xecamp.desktopManagement.Main.main(Main.java:16)

Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Level

    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

    at java.security.AccessController.doPrivileged(Native Method)

    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

    at java.lang.ClassLoader.loadClass(ClassLoader.java:307)

    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

是不是很熟悉,“我明明排除了所有log4j,为什么还有log的引用”。这个时候

 

表示排除不够深刻,但是我们锁定问题一般都是新引入的包出现问题,还是要考mvn dependency:tree,将所有phoenix.core依赖打出来。然后从bing上找到了这个类似的问题:

org.apache.catalina.core.ContainerBase startInternal

SEVERE: A child container failed during start

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[/phoenix]]

    at java.util.concurrent.FutureTask.report(FutureTask.java:122)

    at java.util.concurrent.FutureTask.get(FutureTask.java:192)

    at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1123)

    at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:816)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1575)

    at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1565)

    at java.util.concurrent.FutureTask.run(FutureTask.java:266)

    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

    at java.lang.Thread.run(Thread.java:745)

Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[/phoenix]]

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)

    ... 6 more

Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.addServlet(Ljava/lang/String;Ljavax/servlet/Servlet;)Ljavax/servlet/ServletRegistration$Dynamic;

    at org.springframework.boot.context.embedded.ServletRegistrationBean.onStartup(ServletRegistrationBean.java:190)

    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.selfInitialize(EmbeddedWebApplicationContext.java:225)

    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.access$000(EmbeddedWebApplicationContext.java:85)

    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext$1.onStartup(EmbeddedWebApplicationContext.java:209)

    at org.springframework.boot.contex2016-03-07 23:40:29.048  WARN 71400 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.boot.context.embedded.EmbeddedServletContainerException: Unable to start embedded Tomcat

ded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:55)

    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5513)

    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

 

 

图中标红的地方,其实是Stack Overflow(不得不说是程序员神站!)一位老兄的日志,乍看一下跟我的错误没有相关,但是我观察到这个报错结构跟我的报错堆栈非常像,于是一句句对比自己的日志,于是乎,找到了这个:

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start componen [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[/zte-sdp-profile-icenter]]

        at java.util.concurrent.FutureTask.report(FutureTask.java:122)

        at java.util.concurrent.FutureTask.get(FutureTask.java:192)

        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:939)

        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872)

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)

        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)

        at java.util.concurrent.FutureTask.run(FutureTask.java:266)

        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)

        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)

        at java.lang.Thread.run(Thread.java:745)

Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Tomcat].Stan                                          dardHost[localhost].TomcatEmbeddedContext[/zte-sdp-profile-icenter]]

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)

        ... 6 more

Caused by: org.apache.catalina.LifecycleException: Failed to start component [Pipeline[StandardEngine[Tom                                          cat].StandardHost[localhost].TomcatEmbeddedContext[/zte-sdp-profile-icenter]]]

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)

        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5099)

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

        ... 6 more

Caused by: org.apache.catalina.LifecycleException: Failed to start component [org.apache.catalina.authent                                          icator.NonLoginAuthenticator[/zte-sdp-profile-icenter]]

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)

        at org.apache.catalina.core.StandardPipeline.startInternal(StandardPipeline.java:170)

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

        ... 8 more

Caused by: java.lang.NoSuchMethodError: javax.servlet.ServletContext.getVirtualServerName()Ljava/lang/Str                                          ing;

        at org.apache.catalina.authenticator.AuthenticatorBase.startInternal(AuthenticatorBase.java:1137)

        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)

        ... 10 more

 

Nov 21, 2018 3:56:24 PM org.apache.catalina.core.ContainerBase startInternal

SEVERE: A child container failed during start

java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start componen  

 

    

(原来这个就是目前即便去掉log4j也还是报错的原因之一,之所以说之一,后文在描述)。

谢天谢帝,通过文档官产,发现这个类有问题,果断又燃起了希望。于是乎百度一查,不得了,这回有戏了。

https://blog.csdn.net/typist_/article/details/52824265

 

还真有哥们错到一样的问题了(虽然不是phoenix,但毕竟是组件啊),提示如下:

.引发错误原因:无 javax.servlet.ServletContext.getVirtualServerName()方法

 

2.经排查,错误由servlet-api-2.3.jar抛出,而此包是由org.apache.santuario包隐式引用的一个依赖包

3. 解决:在org.apache.santuario包中排除servlet-api包即可,若需要可显式引用javax.servlet高版本的包

 

虽然我报错的不是一个问题,但是这个2,3很有用啊,于是,又是mvn:dependency:tree登场,修改pom文件。

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->

<dependency>

    <groupId>javax.servlet</groupId>

    <artifactId>javax.servlet-api</artifactId>

    <version>3.1.0</version>

</dependency>

排除一个旧的,

                 <exclusion>

<groupId>javax.servlet</groupId>

<artifactId>servlet-api</artifactId>

</exclusion>

 

当然想都不要想,这个货也在phoenix的依赖里面。排除的时候没有拍干净,发现这货还有个重载版本的包在:

<exclusion>

<groupId>org.mortbay.jetty</groupId>

<artifactId>servlet-api-2.5</artifactId>

</exclusion>  

还不是一个组织提供的,xxoo了。于是继续排除,你问我怎么找到的,根据依赖找反依赖啊

<dependency>

    <groupId>org.mortbay.jetty</groupId>

    <artifactId>servlet-api-2.5</artifactId>

    <version>6.1H.14.1</version>

</dependency>

 

然后maven编译,久违了的springboot打包成功了。

(当夜,我以为我成功了,但是。。。。。。。。)

 

第二天一上班,微服务走一个,输入入口函数,结果。。。。

java.lang.IllegalAccessError: tried to access method

com.google.common.base.Stopwatch.<init>()V from class

org.apache.hadoop.hbase.zookeeper.MetaTableLocator

 

这也就是我之前说的,为什么上面问题只是问题之一,而不是全部(在整个流程拉通以前,永远不要觉得已经到结果了,虽然我早有预计,但是面对突如其来的bug,还是会有写丧气,当然有了前面5天的奋斗经验,我们还是要坚强的继续走下去)。

 

继续 baidu/bing(真可谓我的黑白双煞,东边不亮西方亮)。

在众多链接中,我又相中了它:

https://blog.csdn.net/ludonqin/article/details/52387769

 

首先确认,Stopwatch在google的guava包下,果断开始查guava,发现项目里有两个版本的guava,删除一个,保留与当前hbase版本匹配的另一个,运行成功。

 

注,guava17开始,constructors发生变化,如果确认当前项目只有一个guava包,需确认版本问题。

 

测试,hbase1.2.1:guava12-16,运行无误;guava17开始,同样出现标题异常

 

 

注意上面两个描述,1,guava肯定是有冲突的,2,hbase1.2.1有guava的限制,于是又要寄出神器:mvn dependency:tree,(这个口令在这个问题流程中如同玛丽玛丽红般无解,迅速定点问题)

修改pom文件,如下:

  1. guava冲突,干掉

<exclusion>

<groupId>com.google.guava</groupId>

     <artifactId>guava</artifactId>

</exclusion> 

  1. 引入合适版本的guava(现在想来,如果没有上贴中网友的精准定位,这个问题我不知道又要浪费多少时间,感激中带有小确幸呀。直接上版本15)

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->

<dependency>

    <groupId>com.google.guava</groupId>

    <artifactId>guava</artifactId>

    <version>15.0</version>

</dependency>

 

然后编译,运行,在输入命令。

久违了

 /  ___/\____ \_  __ \  |/    \  / ___\| __ \ /  _ \ /  _ \   __\

 \___ \ |  |_> >  | \/  |   |  \/ /_/  > \_\ (  <_> |  <_> )  |

/____  >|   __/|__|  |__|___|  /\___  /|___  /\____/ \____/|__|

     \/ |__|                 \//_____/     \/

 

 

总结:

  1. 做大数据的公司,由于使用的数据平台关系,难免会有maven打包等问题的库冲突,多回头看看这个文章,尝试运用中间的方法,迂回解决问题
  2. Maven dependency:tree,来跟我念,博若波罗蜜!
  3. 百度解决不了问题别忘了谷歌,不能翻墙用bing国际版
  4. Stack Overflow 和CSDN都是好东西;
  5. 求人不如求己,很多时候没有成熟的解决方案,就看怎么变通,和一点点运气(但是首先要有backup方案,让自己有足够时间去腾挪)
  6. 渡己要渡人,正因为很多问题很少人遇到,一旦有了方案就要敢于出击,分享。

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/degel/article/details/84403069