Статьи

Apache Karaf встречает Apache HBase

Вступление

Apache HBase — это распределенное, версионное, ориентированное на столбцы хранилище с открытым исходным кодом, созданное по образцу Google Bigtable. Если вы постоянный читатель, скорее всего, вы уже знаете, что такое Apache Karaf, но для тех, кто этого не делает: Apache Karaf — это среда выполнения OSGi, которая работает поверх любой инфраструктуры OSGi и предоставляет вам набор сервисов, мощную концепцию обеспечения, расширяемая оболочка и многое другое.

Поскольку Apache HBase еще не готов к OSGi, людям, разрабатывающим приложения OSGi, часто трудно понять, как использовать HBase внутри OSGi.

Этот пост объясняет, как вы можете создать приложение OSGi, которое использует HBase. Обратите внимание, что этот пост посвящен не запуску частей HBase внутри OSGi, а сосредоточению внимания на том, как использовать клиентский API внутри OSGi. Как всегда, я сосредоточусь на контейнерах на основе Karaf, таких как Apache ServiceMix , Fuse ESB и т. Д., Но большинство вещей в этом посте, как правило, применимо ко всем средам исполнения OSGi.

HBase и OSGi

Давайте подробнее рассмотрим HBase и объясним некоторые моменты, касающиеся его связи с OSGi.

Плохие новости

  • HBase не предоставляет метаданных OSGi, что означает, что вам нужно либо самостоятельно обернуть HBase, либо найти сторонний пакет для HBase.
  • HBase поставляется в виде одной банки.
  • Использует конфигурацию Hadoop.

Первый пункт довольно прост. Второй момент может показаться плохой новостью с первого взгляда, но если вы подумаете об этом, вы поймете, что когда все внутри одной банки, вещи не совсем модульны. Например, клиентский API находится внутри той же фляги с интерфейсами avro & thrift, и даже если они вам не нужны, они все равно будут там. Так что эта банка содержит вещи, которые могут быть совершенно бесполезны для вашего случая использования.

Обратите внимание, что один оператор jar не относится к таким зависимостям, как Hadoop или Zookeeper.

Тот факт, что HBase зависит от механизмов загрузки конфигурации Hadoop, также является плохой новостью, потому что некоторые версии Hadoop немного чешутся при работе внутри OSGi.

Хорошие новости

  • Внутри HBase нет монстров загрузки классов, так что вы не будете сильно укушены, когда будете пытаться использовать клиентский API внутри OSGi.

Испытания

Таким образом, существует два типа проблем, во-первых, найти или создать пакет для HBase, который будет иметь требования, которые имеют смысл для вашего варианта использования. Второй способ — загрузить конфигурацию клиента hbase внутри OSGi.

Поиск пакета для HBase

Насколько я знаю, есть пакеты для HBase, предоставляемые Apache ServiceMix Bundles . Тем не менее, пакеты, которые в настоящее время предоставляются, имеют больше требований с точки зрения требуемых пакетов, чем они фактически необходимы (см. Плохие новости, второй пункт). В настоящее время ведется подготовка пакета с более осмысленными требованиями, и надеюсь, что он будет выпущен довольно скоро.

В этом порту я собираюсь использовать протокол Pax Url Wrap . Протокол переноса создаст на лету метаданные OSGi для любого jar. Более того, все импортные пакеты будут помечены как необязательные, поэтому вам не придется сталкиваться с ненужными требованиями. Это то, с чего можно начать, но его не рекомендуется использовать в производственной среде. Таким образом, вы можете использовать его в POC, но когда пришло время перейти к производству, лучше использовать подходящий комплект.

Создание дескриптора функции Karaf для HBase

Немного поэкспериментировав, я обнаружил, что могу использовать HBase внутри Karaf, установив пакеты, перечисленные в описателе функций ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<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.

Создание конфигурации клиента HBase внутри OSGi

Вещи, описанные в этом разделе, могут различаться в зависимости от используемой вами версии фляги Hadoop. Я постараюсь предоставить общее решение, которое охватывает все случаи.

Обычно при настройке клиента hbase вам просто нужно сохранить hbase-site.xml внутри вашего classpath. Внутри OSGi этого не всегда достаточно. Некоторым версиям hadoop удастся подобрать этот файл, другим — нет. Во многих случаях hbase будет жаловаться на несоответствие версии между текущей версией и найденной в hbase-defatult.xml.

Обходной путь должен установить hbase.defaults.for.version, чтобы соответствовать вашей версии HBase:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
<?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 в качестве загрузчика класса контекста потока перед созданием объекта конфигурации.

1
Thread.currentThread().setContextClassLoader(HBaseConfiguration.class.getClassLoader());

Причина, по которой я предлагаю это, заключается в том, что hbase будет использовать загрузчик классов контекста потока для загрузки ресурсов (hbase-default.xml и hbase-site.xml). Установка TCCL позволит вам загрузить значения по умолчанию и переопределить их позже.

Фрагмент ниже показывает, как вы можете установить TCCL для загрузки значений по умолчанию непосредственно из пакета hbase.

1
2
3
4
5
6
7
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 или нет.

В следующие пару недель я собираюсь прокатиться на HBase по задней части верблюда , используя новый компонент camel-hbase внутри OSGi, так что следите за обновлениями.

Изменить: Исходное сообщение было отредактировано, так как оно содержит фрагмент, который я обнаружил, что его лучше избегать (использование конфигурации HBase в качестве службы OSGi).