Hadoop mapreduce: java.lang.UnsatisfiedLinkError: org.apache.hadoop.util.NativeCodeLoader.buildSupportsSnappy()Z

Я пытаюсь написать файл сжатой последовательности мгновенных блоков из задания уменьшения карты. Я использую hadoop 2.0.0-cdh4.5.0 и snappy-java 1.0.4.1.

Вот мой код:

package jinvestor.jhouse.mr;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;

import jinvestor.jhouse.core.House;
import jinvestor.jhouse.core.util.HouseAvroUtil;
import jinvestor.jhouse.download.HBaseHouseDAO;

import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.LocatedFileStatus;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.RemoteIterator;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.SequenceFile;
import org.apache.hadoop.io.compress.CompressionCodec;
import org.apache.hadoop.io.compress.SnappyCodec;
import org.apache.hadoop.mapred.FileOutputFormat;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat;
import org.apache.hadoop.mapreduce.Job;
import org.apache.mahout.math.DenseVector;
import org.apache.mahout.math.NamedVector;
import org.apache.mahout.math.VectorWritable;

/**
 * Produces mahout vectors from House entries in HBase.
 * 
 * @author Michael Scott Knapp
 * 
 */
public class HouseVectorizer {

    private final Configuration configuration;
    private final House minimumHouse;
    private final House maximumHouse;

    public HouseVectorizer(final Configuration configuration,
            final House minimumHouse, final House maximumHouse) {
        this.configuration = configuration;
        this.minimumHouse = minimumHouse;
        this.maximumHouse = maximumHouse;
    }

    public void vectorize() throws IOException, ClassNotFoundException, InterruptedException {
        JobConf jobConf = new JobConf();
        jobConf.setMapOutputKeyClass(LongWritable.class);
        jobConf.setMapOutputValueClass(VectorWritable.class);

        // we want the vectors written straight to HDFS,
        // the order does not matter.
        jobConf.setNumReduceTasks(0);

        Path outputDir = new Path("/home/cloudera/house_vectors");
        FileSystem fs = FileSystem.get(configuration);
        if (fs.exists(outputDir)) {
            fs.delete(outputDir, true);
        }

        FileOutputFormat.setOutputPath(jobConf, outputDir);

        // I want the mappers to know the max and min value
        // so they can normalize the data.
        // I will add them as properties in the configuration,
        // by serializing them with avro.
        String minmax = HouseAvroUtil.toBase64String(Arrays.asList(minimumHouse,
                maximumHouse));
        jobConf.set("minmax", minmax);

        Job job = Job.getInstance(jobConf);
        Scan scan = new Scan();
        scan.addFamily(Bytes.toBytes("data"));
        TableMapReduceUtil.initTableMapperJob("homes", scan,
                HouseVectorizingMapper.class, LongWritable.class,
                VectorWritable.class, job);
        job.setOutputFormatClass(SequenceFileOutputFormat.class);
        job.setOutputKeyClass(LongWritable.class);
        job.setOutputValueClass(VectorWritable.class);
        job.setMapOutputKeyClass(LongWritable.class);
        job.setMapOutputValueClass(VectorWritable.class);

        SequenceFileOutputFormat.setOutputCompressionType(job, SequenceFile.CompressionType.BLOCK);
        SequenceFileOutputFormat.setOutputCompressorClass(job, SnappyCodec.class);
        SequenceFileOutputFormat.setOutputPath(job, outputDir);
        job.getConfiguration().setClass("mapreduce.map.output.compress.codec", 
                SnappyCodec.class, 
                CompressionCodec.class);

        job.waitForCompletion(true);
    }

Когда я запускаю его, я получаю это:

java.lang.Exception: java.lang.UnsatisfiedLinkError: org.apache.hadoop.util.NativeCodeLoader.buildSupportsSnappy()Z
    at org.apache.hadoop.mapred.LocalJobRunner$Job.run(LocalJobRunner.java:401)
Caused by: java.lang.UnsatisfiedLinkError: org.apache.hadoop.util.NativeCodeLoader.buildSupportsSnappy()Z
    at org.apache.hadoop.util.NativeCodeLoader.buildSupportsSnappy(Native Method)
    at org.apache.hadoop.io.compress.SnappyCodec.checkNativeCodeLoaded(SnappyCodec.java:62)
    at org.apache.hadoop.io.compress.SnappyCodec.getCompressorType(SnappyCodec.java:127)
    at org.apache.hadoop.io.compress.CodecPool.getCompressor(CodecPool.java:104)
    at org.apache.hadoop.io.compress.CodecPool.getCompressor(CodecPool.java:118)
    at org.apache.hadoop.io.SequenceFile$Writer.init(SequenceFile.java:1169)
    at org.apache.hadoop.io.SequenceFile$Writer.<init>(SequenceFile.java:1080)
    at org.apache.hadoop.io.SequenceFile$BlockCompressWriter.<init>(SequenceFile.java:1400)
    at org.apache.hadoop.io.SequenceFile.createWriter(SequenceFile.java:274)
    at org.apache.hadoop.io.SequenceFile.createWriter(SequenceFile.java:527)
    at org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat.getSequenceWriter(SequenceFileOutputFormat.java:64)
    at org.apache.hadoop.mapreduce.lib.output.SequenceFileOutputFormat.getRecordWriter(SequenceFileOutputFormat.java:75)
    at org.apache.hadoop.mapred.MapTask$NewDirectOutputCollector.<init>(MapTask.java:617)
    at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:737)
    at org.apache.hadoop.mapred.MapTask.run(MapTask.java:338)
    at org.apache.hadoop.mapred.LocalJobRunner$Job$MapTaskRunnable.run(LocalJobRunner.java:233)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

Если я закомментирую эти строки, мой тест пройдет:

SequenceFileOutputFormat.setOutputCompressionType(job, SequenceFile.CompressionType.BLOCK);
        SequenceFileOutputFormat.setOutputCompressorClass(job, SnappyCodec.class);
        job.getConfiguration().setClass("mapreduce.map.output.compress.coded", 
                SnappyCodec.class, 
                CompressionCodec.class);

Тем не менее, я действительно хочу использовать мгновенное сжатие в своих файлах последовательности. Может кто-нибудь объяснить мне, что я делаю неправильно?


person msknapp    schedule 03.03.2014    source источник
comment
Как вы установили LZO и как вы выполняете свою работу?   -  person Chiron    schedule 03.03.2014
comment
Я не использую сжатие LZO на самом деле, просто быстро. Я запускаю задание из модульного теста.   -  person msknapp    schedule 03.03.2014
comment
Правда, моя ошибка. Однако вам необходимо установить свойство java.library.path. Например: -Djava.library.path=/lib/hadoop/native   -  person Chiron    schedule 03.03.2014
comment
Я создаю свою конфигурацию, используя конструктор без аргументов по умолчанию, и передаю его в качестве аргумента-конструктора моему HouseVectorizer. Затем я вызываю метод векторизации. Я запускаю это на предварительно созданной виртуальной машине Cloudera cdh 4.5.   -  person msknapp    schedule 03.03.2014
comment
Я не думаю, что мне нужно устанавливать java.library.path здесь, как я уже сказал, все это пройдет, если я просто закомментирую строки, чтобы сделать быстрое сжатие. Я использую maven для управления зависимостями, так что вот как материал хаупа попадает в мой путь к классам.   -  person msknapp    schedule 03.03.2014
comment
На самом деле вам нужно установить его. Вы получаете ошибку связывания. Вы комментируете строки, код выполняется. Это вам что-то говорит?   -  person Chiron    schedule 03.03.2014
comment
Я добавил это, но ничего не изменил: System.setProperty(java.library.path,System.getProperty(java.library.path)+:/lib/hadoop/native);   -  person msknapp    schedule 03.03.2014
comment
Зависит от вашей установки. /lib/hadoop/native является примером   -  person Chiron    schedule 03.03.2014
comment
все мои зависимости maven совпадают с тем, что находится в моих каталогах библиотек Hadoop, я серьезно сомневаюсь, что это проблема. Я только что проверил, и все мои snappy jar и hadoop jar имеют ту же версию, что и в моих файлах maven pom. В любом случае, я все равно попробовал ваш совет, используя /usr/lib/hadoop/lib, /usr/lib/hadoop-mapreduce/lib и /usr/lib/hadoop-0.20-mapreduce/lib в качестве первых трех записей в моем системное свойство. Это ничего не изменило.   -  person msknapp    schedule 03.03.2014
comment
переключение на DefaultCodec работает, но теперь он использует алгоритм deflate, который не такой быстрый, как быстрый.   -  person msknapp    schedule 03.03.2014


Ответы (6)


Найдена следующая информация из Сообщества Cloudera

  1. Убедитесь, что LD_LIBRARY_PATH и JAVA_LIBRARY_PATH содержат собственный путь к каталогу с файлами libsnappy.so**.
  2. Убедитесь, что путь LD_LIBRARY_PATH и JAVA_LIBRARY экспортирован в среду SPARK (spark-env.sh).

Например, я использую Hortonworks HDP, и у меня есть следующая конфигурация в моем spark-env.sh

export JAVA_LIBRARY_PATH=$JAVA_LIBRARY_PATH:/usr/hdp/2.2.0.0-2041/hadoop/lib/native
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/hdp/2.2.0.0-2041/hadoop/lib/native
export SPARK_YARN_USER_ENV="JAVA_LIBRARY_PATH=$JAVA_LIBRARY_PATH,LD_LIBRARY_PATH=$LD_LIBRARY_PATH"
person Pradeep Jawahar    schedule 14.05.2015
comment
У меня была аналогичная проблема. У меня было приложение Java. Добавление собственного пути к библиотеке в LD_LIBRARY_PATH помогло решить проблему. Экспортировал ли LD_LIBRARY_PATH = $LD_LIBRARY_PATH :/path/to/hadoop/lib/native. Затем сделал java -jar ‹application.jar›. Большое спасибо!! - person sunitha; 09.05.2018
comment
Это не решило проблему для меня. Даже после экспорта путей libsnappy в два указанных выше пути библиотек та же ошибка остается. - person ely; 27.08.2018

проверьте ваш core-site.xml и mapred-site.xml, они должны содержать правильные свойства и путь к папке с библиотеками

core-site.xml

<property>
  <name>io.compression.codecs</name>
<value>org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.DefaultCodec,org.apache.hadoop.io.compress.SnappyCodec</value>
</property>

mapred-site.xml

 <property>
      <name>mapreduce.map.output.compress</name>
      <value>true</value>
    </property>

    <property>
     <name>mapred.map.output.compress.codec</name>  
     <value>org.apache.hadoop.io.compress.SnappyCodec</value>
    </property>


    <property>
      <name>mapreduce.admin.user.env</name>
      <value>LD_LIBRARY_PATH=/usr/hdp/2.2.0.0-1084/hadoop/lib/native</value>
    </property>

LD_LIBRARY_PATH — должен содержать путь к libsnappy.so.

person Oleksandr Petrenko    schedule 28.01.2015

Моя проблема заключалась в том, что моя JRE не содержала соответствующих нативных библиотек. Это может быть или не быть, потому что я переключил JDK с предварительно созданной виртуальной машины cloudera на JDK 1.7. Файлы snappy .so находятся в вашем каталоге hadoop/lib/native, они должны быть в JRE. Добавление их в путь к классам, похоже, не решило мою проблему. Я решил это так:

$ cd /usr/lib/hadoop/lib/native
$ sudo cp *.so /usr/java/latest/jre/lib/amd64/

Затем я смог использовать класс SnappyCodec. Хотя ваши пути могут быть разными.

Это, казалось, привело меня к следующей проблеме:

Причина: java.lang.RuntimeException: собственная библиотека snappy недоступна: SnappyCompressor не загружен.

Все еще пытаюсь решить это.

person msknapp    schedule 03.03.2014
comment
Ребята, копирование этих файлов приведет к проблемной ситуации после обновления версии CDH. Вам нужно копировать их при каждом обновлении CDH, и поверьте мне, вы бы забыли, что скопировали эти файлы раньше. Правильный способ - работать с LD_LIBRARY_PATH! Вы должны убедиться, что он имеет правильное значение на экземплярах Gateway. В CDH, возможно, вы переопределили его. По умолчанию там обычно все в порядке. Делая это удаленно, вы можете использовать java -cp … затем вы устанавливаете -Djava.library.path. - person Niko; 14.01.2015

Мне нужны все файлы, а не только *.so. Также в идеале вы должны включить папку в свой путь вместо того, чтобы копировать оттуда библиотеки. После этого вам необходимо перезапустить службу MapReduce, чтобы новые библиотеки были приняты и их можно было использовать.

Нико

person Niko    schedule 10.07.2014

после удаления hadoop.dll (которую я скопировал вручную) из windows\system32 и установки HADOOP_HOME=\hadoop-2.6.4 ЭТО РАБОТАЕТ!!!

person Jaigates    schedule 29.08.2016

В моем случае вы можете проверить файлы hive-conf : mapred-site.xml и проверить значение ключа: mapreduce.admin.user.env ,

Я протестировал его на новом узле данных и получил ошибку unlinked-buildSnappy на машине, где нет собственных зависимостей ( libsnappy.so и т. д.)

person staticor    schedule 29.12.2018