2015-12-23 4 views
1

Я пытаюсь написать UDF для Hadoop Hive, который анализирует User Agents. Следующий код работает отлично на моей локальной машине, но на Hadoop я получаю:Hadoop Hive UDF с внешней библиотекой

org.apache.hadoop.hive.ql.metadata.HiveException: Невозможно выполнить метод общественного java.lang.String MyUDF .evaluate (java.lang.String) throws org.apache.hadoop.hive.ql.metadata.HiveException на объекте MyUDF @ 64ca8bfb класса MyUDF с аргументами {Все занятия: java.lang.String} размера 1 ',

Код:

import java.io.IOException; 
import org.apache.hadoop.hive.ql.exec.UDF; 
import org.apache.hadoop.hive.ql.metadata.HiveException; 
import org.apache.hadoop.io.Text; 
import org.apache.hadoop.*; 
import com.decibel.uasparser.OnlineUpdater; 
import com.decibel.uasparser.UASparser; 
import com.decibel.uasparser.UserAgentInfo; 

public class MyUDF extends UDF { 

    public String evaluate(String i) { 
     UASparser parser = null;   
     parser = new UASparser(); 
     String key = ""; 
     OnlineUpdater update = new OnlineUpdater(parser, key); 
     UserAgentInfo info = null; 
     info = parser.parse(i); 
     return info.getDeviceType(); 
    } 
} 

Факты, которые приходят на мой взгляд, я должен упомянуть:

  • Я компиляция с Eclipse, с «экспортом работоспособной банкой файлом» и вытяжными необходимыми библиотеками в опционную генерироваться банкой

  • Я загрузив этот файл «жир банки» с Hue

  • Минимальный рабочий пример мне удалось бежать:

    public String evaluate(String i) { return "hello" + i.toString()"; }

  • Я предполагаю, что проблема л где-то вокруг этой библиотеки (скачан с https://udger.com) Я использую, но я понятия не имею, где.

Любые предложения?

Thanks, Michal

+0

Вы просмотрели журналы YARN для 'application_xxxx_xxxx' (как сообщается Hive), чтобы проверить некоторые подсказки, например. некоторые внутренние исключения из вашего JAR, скомпилированные с версией Java, которая более поздняя, ​​чем JRE, используемая Hive (только пример)? –

ответ

1

Это может быть несколько вещей. Лучше всего проверять журналы, но вот список нескольких быстрых вещей, которые вы можете проверить за минуту.

  1. jar не содержит всех зависимостей. Я не уверен, как eclipse создает исполняемую банку, но может не включать все зависимости. Вы можете сделать

    баночку тс ваш-UDF-jar.jar

, чтобы увидеть, что было включено. Вы должны увидеть материал от com.decibel.uasparser. Если нет, вы должны создать банку с соответствующими зависимостями (обычно вы делаете это с помощью maven).

  1. Другая версия JVM. Если вы скомпилируете jdk8 и кластеры запускаете jdk7, он также потерпит неудачу

  2. Вертолетная версия. Иногда API-интерфейс Hive изменяется немного, достаточно, чтобы быть несовместимым. Вероятно, не тот случай, но убедитесь, что для компиляции UDF против той же версии Hadoop и ульи, что у вас есть в кластере

  3. Вы всегда должны проверить, если info является недействительным после вызова parse()

  4. похоже, что библиотека использует ключ, то есть фактически получает данные из онлайн-сервиса (udger.com), поэтому может не работать без фактического ключа.Еще важнее то, что библиотека обновляется через Интернет, обращаясь к онлайн-службе для каждой записи. Это означает, что, глядя на код, он создаст один поток обновлений за запись. Вы должны изменить код, чтобы сделать это только один раз в конструкторе, как следующее:

Вот как изменить его:

public class MyUDF extends UDF { 
    UASparser parser = new UASparser(); 

    public MyUDF() { 
    super() 
    String key = "PUT YOUR KEY HERE"; 
    // update only once, when the UDF is instantiated 
    OnlineUpdater update = new OnlineUpdater(parser, key); 
    } 

    public String evaluate(String i) { 
     UserAgentInfo info = parser.parse(i); 
     if(info!=null) return info.getDeviceType(); 
     // you want it to return null if it's unparseable 
     // otherwise one bad record will stop your processing 
     // with an exception 
     else return null; 
    } 
} 

Но чтобы знать наверняка, вы должны смотреть на журналы ... журналы пряжи, но также вы можете просматривать журналы улья на машине, на которой вы отправляете задание (возможно, в/var/log/hive, но это зависит от вашей установки).

+0

Наша машина Hadoop была недоступна, поэтому у меня не было возможности проверить журналы, но ... 1) Я проверил зависимости, они выглядят нормально 2) Это был эмитент на шаг назад. Однако, если версия не совместима, Java бросает исключение о неправильной версии, а не IOException/HiveException 3) должно быть нормально 4) Постараюсь это один 5) Он работает withou ключ (я проверил снаружи Hadoop). Я знаю о неэффективности, но решение этого должно быть следующим шагом, который я думаю. – Michal

+0

Однако мне пришла в голову другая идея, когда я проходил через библиотеку ... Он пытается записать во временный файл, это даже законная операция для funtion UDF (запись в файловую систему? HDFS - это добавление только системы, так что я чувствую неприятности здесь? ... спасибо, я ценю помощь :) – Michal

+0

Это законно для UDF читать/писать локальный файл, но это определенно не рекомендуется! Но в некоторых случаях это можно сделать безопасно. На предыдущей работе у нас был файл конфигурации, который был нажат на все машины, и UDF, который его прочитал и предоставил содержимое для запросов. Но эта библиотека открывает сетевое соединение для каждой записи ... это очень неэффективно и плохо ... так что да, это пахнет неприятностями :) Эта библиотека не была предназначена для работы с hadoop. При написании UDF, который использует библиотеку, вы должны быть очень осторожны и видеть, как она работает внутри. –

0

такая проблема, вероятно, может быть решено с помощью шагов:

  1. overide метода UDF.getRequiredJars(), сделать его возвращение списка пути к hdfs файла, значения которых определяются, где вы поставите следующую папку xxx_lib в ваших HDFS. Обратите внимание, что список туман точно содержит полные HDFS строку пути в каждой банке, в таких, как hdfs://yourcluster/some_path/xxx_lib/some.jar

  2. экспорт вашего udf код, следуя «Runnable JAR-файл экспортирующей мастера» (выбрал «копировать необходимые библиотеки в подпапку рядом с генерируемым баночка». Это шаги приведут к xxx.jar и Lib xxx_lib папки рядом с xxx.jar

  3. пут xxx.jar и папки xxx_lib к вашей файловой системе HDFS в соответствии с вашим кодом в шаге 0.

  4. создать udf, используя: add jar $ {the-xxx.jar-hdfs-path}; создать функцию your-function как $} квалифицированное имя udf cl жопа};

Попробуйте. Я тестирую это, и он работает

Смежные вопросы