IllegalAccessError в Spark, вызванный async-http-клиентом
Контекст: я работаю над потоковым заданием Spark, которое записывает данные в InfluxDB, используя эту библиотеку. Здесь среда.
- Scala 2.11.8
- Spark 2.1.0 (Dockerized автономный кластер)
соответствующие зависимости:
"org.apache.spark" %% "spark-core" % "2.1.0" % "provided",
"org.apache.spark" %% "spark-streaming" % "2.1.0" % "provided",
"org.apache.spark" %% "spark-streaming-kafka-0-8" % "2.1.0",
"com.paulgoldbaum" %% "scala-influxdb-client" % "0.5.2" // which uses "org.asynchttpclient" % "async-http-client" % "2.0.24"
Все компилируется и работает нормально на моем локальном компьютере, но когда я отправляю сборочный файл в кластер Spark, я получаю эту ошибку в драйвере:
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.spark.deploy.worker.DriverWrapper$.main(DriverWrapper.scala:58)
at org.apache.spark.deploy.worker.DriverWrapper.main(DriverWrapper.scala)
Caused by: java.lang.IllegalAccessError: tried to access field io.netty.handler.ssl.JdkSslContext.SUPPORTED_CIPHERS from class io.netty.handler.ssl.NettySslPackageAccessor
at io.netty.handler.ssl.NettySslPackageAccessor.jdkSupportedCipherSuites(NettySslPackageAccessor.java:24)
at org.asynchttpclient.config.AsyncHttpClientConfigDefaults.defaultEnabledCipherSuites(AsyncHttpClientConfigDefaults.java:85)
at org.asynchttpclient.DefaultAsyncHttpClientConfig$Builder.<init>(DefaultAsyncHttpClientConfig.java:635)
at org.asynchttpclient.DefaultAsyncHttpClient.<init>(DefaultAsyncHttpClient.java:67)
at com.paulgoldbaum.influxdbclient.HttpClient.<init>(HttpClient.scala:21)
at com.paulgoldbaum.influxdbclient.InfluxDB$.connect(InfluxDB.scala:16)
...
Проблема исчезнет, если я удалю код для записи в InfluxDB.
После осмотра я узнал, что класс io.netty.handler.ssl.NettySslPackageAccessor
на самом деле принадлежит async-http-client
библиотека. Кажется, это хак-класс для доступа к защищенному члену в io.netty.handler.ssl.JdkSslContext
,
Я возился с этой проблемой в течение нескольких дней. Решение, которое я получил, чтобы заставить его работать, переопределяет async-http-client
до более ранней версии, которая не включает в себя оскорбительный код.
dependencyOverrides ++= Set("org.asynchttpclient" % "async-http-client" % "2.0.12")
Вопрос: почему IllegalAccessError
происходит только на кластере, а не в моем локальном запуске? Есть ли лучший способ решить эту проблему?
Если мой SBT может скомпилироваться нормально, то такого не должно быть IllegalAccessError
, значит, есть различия между моим локальным кодом и кодом кластера, который, вероятно, provided
искровые зависимости, но это та же версия, что и у кластера.
Я вроде как оставляю все как есть, но было бы лучше, если бы можно было использовать более новые версии. Или, по крайней мере, я хочу понять, почему эта проблема возникает, и избегать ее в будущем.
2 ответа
Я столкнулся с той же проблемой сегодня и нашел эту проблему на github, которая объясняет проблему. В основном у вас есть несколько ClassLoaders при использовании Spark
и io.netty.handler.ssl.NettySslPackageAccessor и io.netty.handler.ssl.JdkSslContext загружаются различными загрузчиками классов.
В этом случае попытка доступа к частному статическому полю пакета JdkSslContext.SUPPORTED_CIPHERS завершится ошибкой с IllegalAccessError, поскольку частные поля пакета "ограничены" на уровне ClassLoader.
О, и ваше решение также сработало для меня, спасибо.
Это вызвано тем, что оба io.netty:netty
а также org.asynchttpclient:async-http-client
в вашем классе Если вы хотите использовать netty и assync-http-client, добавьте следующие зависимости в ваш скрипт сборки gradle (аналогично maven pom.xml):
compile 'org.asynchttpclient:async-http-client:2.0.38'
compile 'org.asynchttpclient:async-http-client-netty-utils:2.0.38'