Несколько загрузчиков классов и Hadoop API - PullRequest
0 голосов
/ 02 февраля 2019

Наше приложение имеет несколько загрузчиков классов.Это сделано для того, чтобы избежать конфликтов зависимостей между различными API, к которым наше программное обеспечение обращается, включая Hadoop, но не ограничиваясь этим.Без использования стратегии загрузки нескольких классов (или модулей Java 9, которые мы пока не можем поддерживать) мы сталкиваемся с множеством конфликтов зависимостей между Jar-файлами Hadoop и всем остальным.Итак, достаточно сказать, что у нас есть URLClassLoader для всех jar-файлов Hadoop и другие загрузчики классов для других наборов библиотек.

Проблема заключается в следующем: системный загрузчик классов (тот, с которого JVM запускается)не имеет банок Hadoop.Это означает, что загрузчик классов потока-контекста, который по умолчанию является системным загрузчиком классов, не имеет Jar-файлов Hadoop.К сожалению, API всех видов Hadoop, похоже, неявно используют загрузчик классов потока-контекста, что приводит к всевозможным ошибкам ClassNotFound, ServiceLoaders, возвращающим пустые списки, фабрикам, не находящим реализации, и т. Д. Это медленно сводит нас с ума, потому что новое «не найдено»»Иногда возникают проблемы, когда наши клиенты обнаруживают новые опции безопасности и другие варианты конфигурации, что ведет к путям кода, которые не могут найти классы или реализации интерфейсов.

Вы можете предложить очевидное: всегда устанавливайтеЗагрузчик классов с контекстом потока должен быть загрузчиком классов Hadoop.К сожалению, это не похоже на решение.Во-первых, создаются потоки, которые имеют системный загрузчик классов по умолчанию в качестве потока-контекста-класса-загрузчика, и у меня нет контроля над всеми этими потоками.Во-вторых, это подвержено ошибкам и, вероятно, слишком дорого сохранять и восстанавливать загрузчик классов контекста потока в каждой возможной точке входа Hadoop.

Единственный ответ, который я нашел, - это узнать методом проб и ошибок, которыйклассы загружаются загрузчиком классов потока-контекста (или ServiceLoader) и заставляют их предварительно загружаться там, где я установил загрузчик классов контекста потока.Есть ли способ лучше?Есть ли список таких классов?

Это пример трассировки стека:

Error:ProcessNode(PSOutput16): org/apache/hadoop/fs/FileSystem.create:java.io.IOException: org.apache.hadoop.yarn.exceptions.YarnRuntimeException: Failed to load class: [org.apache.hadoop.yarn.api.records.impl.pb.ApplicationIdPBImpl]
org.apache.hadoop.crypto.key.kms.KMSClientProvider.createConnection(KMSClientProvider.java:468)
org.apache.hadoop.crypto.key.kms.KMSClientProvider.decryptEncryptedKey(KMSClientProvider.java:754)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider$5.call(LoadBalancingKMSClientProvider.java:287)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider$5.call(LoadBalancingKMSClientProvider.java:283)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider.doOp(LoadBalancingKMSClientProvider.java:123)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider.decryptEncryptedKey(LoadBalancingKMSClientProvider.java:283)
org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.decryptEncryptedKey(KeyProviderCryptoExtension.java:528)
org.apache.hadoop.hdfs.DFSClient.decryptEncryptedDataEncryptionKey(DFSClient.java:1484)
org.apache.hadoop.hdfs.DFSClient.createWrappedOutputStream(DFSClient.java:1586)
org.apache.hadoop.hdfs.DFSClient.createWrappedOutputStream(DFSClient.java:1571)
org.apache.hadoop.hdfs.DistributedFileSystem$7.doCall(DistributedFileSystem.java:440)
org.apache.hadoop.hdfs.DistributedFileSystem$7.doCall(DistributedFileSystem.java:433)
org.apache.hadoop.fs.FileSystemLinkResolver.resolve(FileSystemLinkResolver.java:81)
org.apache.hadoop.hdfs.DistributedFileSystem.create(DistributedFileSystem.java:433)
org.apache.hadoop.hdfs.DistributedFileSystem.create(DistributedFileSystem.java:374)
org.apache.hadoop.fs.FileSystem.create(FileSystem.java:926)
org.apache.hadoop.fs.FileSystem.create(FileSystem.java:907)
Caused by: org.apache.hadoop.yarn.exceptions.YarnRuntimeException: Failed to load class: [org.apache.hadoop.yarn.api.records.impl.pb.ApplicationIdPBImpl]
org.apache.hadoop.yarn.factories.impl.pb.RecordFactoryPBImpl.newRecordInstance(RecordFactoryPBImpl.java:58)
org.apache.hadoop.yarn.util.Records.newRecord(Records.java:36)
org.apache.hadoop.yarn.api.records.ApplicationId.newInstance(ApplicationId.java:49)
org.apache.hadoop.yarn.security.AMRMTokenIdentifier.readFields(AMRMTokenIdentifier.java:83)
org.apache.hadoop.security.token.Token.decodeIdentifier(Token.java:145)
org.apache.hadoop.security.token.Token.identifierToString(Token.java:349)
org.apache.hadoop.security.token.Token.toString(Token.java:369)
java.lang.String.valueOf(String.java:2994)
java.lang.StringBuilder.append(StringBuilder.java:131)
org.apache.hadoop.security.UserGroupInformation.logAllUserInfo(UserGroupInformation.java:1959)
org.apache.hadoop.crypto.key.kms.KMSClientProvider.getActualUgi(KMSClientProvider.java:1056)
org.apache.hadoop.crypto.key.kms.KMSClientProvider.createConnection(KMSClientProvider.java:451)
org.apache.hadoop.crypto.key.kms.KMSClientProvider.decryptEncryptedKey(KMSClientProvider.java:754)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider$5.call(LoadBalancingKMSClientProvider.java:287)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider$5.call(LoadBalancingKMSClientProvider.java:283)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider.doOp(LoadBalancingKMSClientProvider.java:123)
org.apache.hadoop.crypto.key.kms.LoadBalancingKMSClientProvider.decryptEncryptedKey(LoadBalancingKMSClientProvider.java:283)
org.apache.hadoop.crypto.key.KeyProviderCryptoExtension.decryptEncryptedKey(KeyProviderCryptoExtension.java:528)
org.apache.hadoop.hdfs.DFSClient.decryptEncryptedDataEncryptionKey(DFSClient.java:1484)
org.apache.hadoop.hdfs.DFSClient.createWrappedOutputStream(DFSClient.java:1586)
org.apache.hadoop.hdfs.DFSClient.createWrappedOutputStream(DFSClient.java:1571)
org.apache.hadoop.hdfs.DistributedFileSystem$7.doCall(DistributedFileSystem.java:440)
org.apache.hadoop.hdfs.DistributedFileSystem$7.doCall(DistributedFileSystem.java:433)
org.apache.hadoop.fs.FileSystemLinkResolver.resolve(FileSystemLinkResolver.java:81)
org.apache.hadoop.hdfs.DistributedFileSystem.create(DistributedFileSystem.java:433)
org.apache.hadoop.hdfs.DistributedFileSystem.create(DistributedFileSystem.java:374)
org.apache.hadoop.fs.FileSystem.create(FileSystem.java:926)
org.apache.hadoop.fs.FileSystem.create(FileSystem.java:907)
Caused by: java.lang.ClassNotFoundException: Class org.apache.hadoop.yarn.api.records.impl.pb.ApplicationIdPBImpl not found
org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:2255)
org.apache.hadoop.yarn.factories.impl.pb.RecordFactoryPBImpl.newRecordInstance(RecordFactoryPBImpl.java:56)
org.apache.hadoop.yarn.util.Records.newRecord(Records.java:36)
org.apache.hadoop.yarn.api.records.ApplicationId.newInstance(ApplicationId.java:49)
org.apache.hadoop.yarn.security.AMRMTokenIdentifier.readFields(AMRMTokenIdentifier.java:83)
...