介绍
Apache HBase是模仿Google Bigtable的开源,分布式,版本化,面向列的商店。 如果您是普通读者,那么您可能已经知道Apache Karaf是什么,但是对于那些不是的读者:Apache Karaf是一个OSGi运行时,可以在任何OSGi框架之上运行,并为您提供一系列服务,强大的配置概念,可扩展的外壳等等。
由于Apache HBase 尚未准备好OSGi,因此开发OSGi应用程序的人通常很难理解如何在OSGi中使用HBase。
这篇文章解释了如何构建使用HBase的OSGi应用程序。 请注意,这篇文章不是关于在OSGi内运行HBase的部分,而是重点介绍如何在OSGi内使用客户端api。 与往常一样,我将重点介绍基于Karaf的容器,例如Apache ServiceMix , Fuse ESB等,但本文中的大多数内容通常适用于所有OSGi运行时。
HBase和OSGi
让我们仔细看一下HBase,并解释一下HBase与OSGi的关系。
坏消息
- HBase不提供OSGi元数据,这意味着您需要自己包装HBase或为HBase找到第三方捆绑包。
- HBase作为单个jar传入。
- 使用Hadoop配置。
第一点很简单。 乍一看,第二点似乎并不是什么坏消息,但是如果您稍加思考,您就会意识到,当所有东西都放在一个罐子里时,它们并不是完全模块化的。 例如,客户端api位于同一个jar中,具有avro和thrift接口,即使您不需要它们,它们仍将在那里。 因此,该jar中包含的东西对于您的用例可能完全没用。
请注意,单个jar语句不引用诸如Hadoop或Zookeeper之类的依赖项。
作为HBase的事实取决于Hadoop配置加载机制,这也是个坏消息,因为在OSGi中运行时,某些版本的Hadoop有点发痒。
好消息
- HBase内没有类加载怪物,因此,当您尝试在OSGi中使用客户端api时,您不会真正被咬。
挑战
因此,存在两种类型的挑战,第一种是为HBase找到或创建一个捆绑包,该捆绑包将具有对您的用例有意义的要求。 第二个是在OSGi中加载hbase客户端配置。
寻找HBase的捆绑包
据我所知, Apache ServiceMix Bundles提供了用于HBase的捆绑包 。 但是,当前提供的捆绑软件在所需软件包方面的需求比实际需要的要多(请参阅坏消息,第二点)。 提供具有更明智要求的捆绑包目前仍在进行中,希望将很快发布。
在此端口中,我将使用Pax Url Wrap Protocol 。 包装协议将为任何jar动态创建OSGi元数据。 此外,所有软件包导入都将标记为可选,因此您不必处理不必要的要求。 这可以帮助您入门,但是不建议在生产环境中使用。 因此,您可以在POC中使用它,但是当它需要投入生产时,最好使用适当的捆绑包。
为HBase创建Karaf功能描述符
经过试验后,我发现可以通过安装以下功能描述符中列出的捆绑软件在Karaf中使用HBase:
<feature name="hbase" version="0.90.5" resolver="(obr)" start-level="50">
<feature>war</feature>
<bundle dependency="true">mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.jaxws-api-2.2/1.9.0</bundle>
<bundle dependency="true">mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.saaj-api-1.3/1.9.0</bundle>
<bundle dependency="true">mvn:org.apache.geronimo.specs/geronimo-jta_1.1_spec/1.1.1</bundle>
<bundle dependency="true">mvn:javax.mail/mail/1.4.5</bundle>
<bundle dependency="true">mvn:commons-codec/commons-codec/1.6</bundle>
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-beanutils/1.8.3_1</bundle>
<bundle dependency="true">mvn:commons-collections/commons-collections/3.2.1</bundle>
<bundle dependency="true">mvn:commons-digester/commons-digester/2.1</bundle>
<bundle dependency="true">mvn:commons-jxpath/commons-jxpath/1.3</bundle>
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jdom/1.1_4</bundle>
<bundle dependency="true">mvn:commons-lang/commons-lang/2.6</bundle>
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.ant/1.7.0_6</bundle>
<bundle dependency="true">mvn:commons-configuration/commons-configuration/1.6</bundle>
<bundle dependency="true">mvn:commons-daemon/commons-daemon/1.0.5</bundle>
<bundle dependency="true">mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.commons-httpclient/3.1_7</bundle>
<bundle dependency="true">mvn:org.apache.commons/commons-math/2.2</bundle>
<bundle dependency="true">mvn:commons-net/commons-net/3.1</bundle>
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-core-asl/1.9.7</bundle>
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-mapper-asl/1.9.7</bundle>
<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.jetty/6.1.26_4</bundle>
<bundle dependency="true">mvn:org.apache.zookeeper/zookeeper/3.3.5</bundle><bundle>
mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.hadoop-core/1.0.0_2</bundle>
<bundle>wrap:mvn:org.apache.hbase/hbase/0.90.5</bundle>
</feature>
实际上,此功能描述符与最新版本的Apache Camel提供的功能描述符几乎相同。 区别之一是使用的Apache Hadoop版本。 在此示例中,我倾向于使用稍低版本的Apache Hadoop,它在OSGi中的表现似乎更好。
在OSGi中创建HBase客户端配置
本节中描述的内容可能会有所不同,具体取决于您使用的Hadoop jar版本。 我将尝试提供涵盖所有情况的通用解决方案。
通常,在配置hbase客户端时,只需要在类路径中保留一个hbase-site.xml。 在OSGi内部,这并不总是足够的。 某些版本的hadoop将设法获取该文件,而另一些则不会。 在许多情况下,hbase会抱怨当前版本与hbase-defatult.xml中的版本不匹配。
一种解决方法是将hbase.defaults.for.version设置为与您的HBase版本匹配:
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration><property><name>hbase.zookeeper.quorum</name><value>localhost</value></property><property><name>hbase.zookeeper.property.clientPort</name><value>2181</value></property><property><name>hbase.defaults.for.version</name><value>${hbase.version}</value></property>
</configuration>
在大多数情况下,可以节省您的一种方法是在创建配置对象之前,将hbase bundle classloader设置为线程上下文类加载器。
Thread.currentThread().setContextClassLoader(HBaseConfiguration.class.getClassLoader());
我之所以提出这个建议,是因为hbase将利用线程上下文类加载器来加载资源(hbase-default.xml和hbase-site.xml)。 设置TCCL将允许您加载默认值并在以后覆盖它们。
下面的代码片段显示了如何设置TCCL,以便直接从hbase捆绑包中加载默认值。
ClassLoader ocl = Thread.currentThread().getContextClassLoader();try {Thread.currentThread().setContextClassLoader(HBaseConfiguration.class.getClassLoader());Configuration conf = HBaseConfiguration.create();} finally {Thread.currentThread().setContextClassLoader(ocl); }
请注意,采用这种方法时,您无需在软件包中包含hbase-site.xml。 您将需要以编程方式设置配置。
还要注意,在某些情况下,如果HBase无法找到正确的类加载器,则HBase内部类将重新创建配置,这可能会导致您遇到问题。
思想
HBase与几乎所有不提供对OSGi的即开即用支持的库一样。 如果您了解类加载的基础知识,则可以使其正常工作。 当然,无论您是否使用OSGi,了解类装入器都是迟早要使用的。
接下来的几周,我打算在OSGi中使用全新的camel-hbase组件乘坐HBase骑在骆驼的背面,敬请期待 。
编辑:原始帖子已被编辑,因为其中包含一个片段,我发现最好避免该片段(将HBase配置共享为OSGi服务)。
翻译自: https://www.javacodegeeks.com/2013/11/apache-karaf-meets-apache-hbase.html