Если у меня есть конструктор, который требует путь к файлу, как я могу «подделать» его, если он упакован в банку? - PullRequest
4 голосов
/ 10 февраля 2011

Контекст этого вопроса заключается в том, что я пытаюсь использовать java api maxmind в сценарии свиньи, который я написал ... Однако я не думаю, что знание того или другого необходимо для ответа на вопрос.

API maxmind имеет конструктор, который требует путь к файлу с именем GeoIP.dat, который является файлом с разделителями-запятыми и содержит необходимую информацию.

У меня есть файл jar, содержащий API,а также класс-оболочка, который создает экземпляр класса и использует его.Моя идея состоит в том, чтобы упаковать файл GeoIP.dat в jar, а затем получить к нему доступ в качестве ресурса в файле jar.Проблема в том, что я не знаю, как создать путь, который может использовать конструктор.

Глядя на API, они загружают файл так:

public LookupService(String databaseFile) throws IOException {
    this(new File(databaseFile));
}


public LookupService(File databaseFile) throws IOException {
    this.databaseFile = databaseFile;
    this.file = new RandomAccessFile(databaseFile, "r");
    init();
}

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

Возможно ли это?

Ответы [ 6 ]

2 голосов
/ 11 июня 2012

Это работает для меня.

Предполагается, что у вас есть пакет org.foo.bar.util, который содержит GeoLiteCity.dat

URL fileURL = this.getClass().getResource("org/foo/bar/util/GeoLiteCity.dat");
File geoIPData = new File(fileURL.toURI());
LookupService cl = new LookupService(geoIPData, LookupService.GEOIP_MEMORY_CACHE );
2 голосов
/ 11 февраля 2011

Один из рекомендуемых способов - использовать Distributed Cache , а не пытаться связать его в банку.

Если вы заархивировали GeoIP.dat и скопировали его на hdfs: // хост: порт / путь / GeoIP.dat.zip.Затем добавьте эти параметры в команду Pig:

pig ...
  -Dmapred.cache.archives=hdfs://host:port/path/GeoIP.dat.zip#GeoIP.dat 
  -Dmapred.create.symlink=yes
...

И LookupService lookupService = new LookupService("./GeoIP.dat"); должно работать в вашей пользовательской функции, поскольку файл будет присутствовать локально для задач на каждом узле.

2 голосов
/ 10 февраля 2011

выгрузите ваши данные во временный файл и передайте ему временный файл.

File tmpFile = File.createTempFile("XX", "dat");
tmpFile.deleteOnExit();

InputStream is = MyClass.class.getResourceAsStream("/path/in/jar/XX.dat");
OutputStream os = new FileOutputStream(tmpFile)

read from is, write to os, close
2 голосов
/ 10 февраля 2011

Попробуйте:

new File(MyWrappingClass.class.getResource(<resource>).toURI())
1 голос
/ 10 февраля 2011

Вот как мы используем maxmind geoIP;

Мы помещаем файл GeoIPCity.dat в облако и используем местоположение облака в качестве аргумента при запуске процесса.Код, в котором мы получаем файл GeoIPCity.data и создаем новый LookupService:

if (DistributedCache.getLocalCacheFiles(context.getConfiguration()) != null) {
    List<Path> localFiles = Utility.arrayToList(DistributedCache.getLocalCacheFiles(context.getConfiguration()));
    for (Path localFile : localFiles) {
        if ((localFile.getName() != null) && (localFile.getName().equalsIgnoreCase("GeoIPCity.dat"))) {
            m_geoipLookupService = new LookupService(new File(localFile.toUri().getPath()));
        }
    }
}

Вот сокращенная версия команды, которую мы используем для запуска нашего процесса

$HADOOP_HOME/bin/hadoop jar /usr/lib/COMPANY/analytics/libjars/MyJar.jar -files hdfs://PDHadoop1.corp.COMPANY.com:54310/data/geoip/GeoIPCity.dat -libjars /usr/lib/COMPANY/analytics/libjars/geoiplookup.jar

Важными компонентами этого для запуска компонента MindMax являются -files и -libjars.Это общие параметры в GenericOptionsParser .

-files <comma separated list of files> specify comma separated files to be copied to the map reduce cluster
-libjars <comma separated list of jars> specify comma separated jar files to include in the classpath.

Я предполагаю, что Hadoop использует GenericOptionsParser, потому что я могу найтинет ссылки на это нигде в моем проекте.:)

Если вы поместите GeoIPCity.dat в контейнер и укажете его с помощью аргумента -files, он будет помещен в локальный кеш, который затем может получить преобразователь в функции setup.Это не обязательно должно быть в setup, но должно быть сделано только один раз для каждого картографа, так что это отличное место для его размещения.Затем используйте аргумент -libjars, чтобы указать geoiplookup.jar (или как вы его назвали), и он сможет его использовать.Мы не помещаем geoiplookup.jar в облако.Я катаюсь с предположением, что hadoop будет распределять банку так, как нужно.

Я надеюсь, что все имеет смысл.Я довольно хорошо знаком с hadoop / mapreduce, но я не писал фрагменты, использующие компонент maxmind geoip в проекте, поэтому мне пришлось немного покопаться, чтобы понять его достаточно хорошо, чтобы выполнить объяснение, которое я здесь привожу.

EDIT: дополнительное описание для файлов -files и -libjars. Аргумент files используется для распространения файлов через распределенный кэш Hadoop.В приведенном выше примере мы распространяем файл данных Max Mind Geo-IP через распределенный кэш Hadoop.Нам нужен доступ к файлу гео-IP-адресов Max Mind, чтобы сопоставить IP-адрес пользователя с соответствующей страной, регионом, городом, часовым поясом.API требует, чтобы файл данных присутствовал локально, что невозможно в распределенной среде обработки (нам не будет гарантировано, какие узлы в кластере будут обрабатывать данные).Для распространения соответствующих данных на узел обработки мы используем инфраструктуру распределенного кэша Hadoop.GenericOptionsParser и ToolRunner автоматически облегчают это, используя аргумент –file.Обратите внимание, что файл, который мы распространяем, должен быть доступен в облаке (HDFS).-libjars –libjars используется для распространения любых дополнительных зависимостей, необходимых для заданий map-Reduce.Как и файл данных, нам также необходимо скопировать зависимые библиотеки в узлы кластера, где будет выполняться задание.GenericOptionsParser и ToolRunner автоматически облегчают это, используя аргумент –libjars.

1 голос
/ 10 февраля 2011

Используйте метод classloader.getResource(...) для поиска файла в classpath, который извлечет его из файла JAR.

Это означает, что вам придется изменить существующий код, чтобы отменить загрузку. Детали того, как это сделать, сильно зависят от существующего кода и среды. В некоторых случаях может работать подкласс и регистрация подкласса в рамках. В других случаях вам может потребоваться определить порядок загрузки классов вдоль пути к классу и поместить класс с одинаковой подписью «ранее» в путь к классам.

...