2017-01-17 9 views
5

Kontekst: Pracuję na iskrę strumieniowe pracy, która zapisuje dane na InfluxDB korzystając this library. Oto środowisko.IllegalAccessError w Spark spowodowane przez asynchroniczny-http-client

  • Scala 2.11.8
  • Spark 2.1.0 (Dockerized samodzielna cluster)

odpowiednie zależności:

"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" 

Wszystko kompiluje i działa poprawnie na moim komputerze lokalnym, ale kiedy Przesyłam słoik montażowy do klastra Spark, pojawia się ten błąd w sterowniku:

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) 
    ... 

Problem zniknie, jeśli usunę kod do zapisania w InfluxDB.

Po pewnym rozejrzeniu się dowiedziałem się, że klasa io.netty.handler.ssl.NettySslPackageAccessor należy do biblioteki async-http-client. Wygląda na to, że jest hacką, aby uzyskać dostęp do chronionego członka w io.netty.handler.ssl.JdkSslContext.

Pozwoliłem sobie z tym problemem przez kilka dni. Rozwiązaniem, które udało mi się sprawić, jest nadpisanie wersji async-http-client we wcześniejszej wersji, która nie zawiera obraźliwego kodu.

dependencyOverrides ++= Set("org.asynchttpclient" % "async-http-client" % "2.0.12") 

Pytanie: Dlaczego IllegalAccessError dzieje tylko w zestawie, a nie w moim lokalnym metę? Czy istnieje lepszy sposób rozwiązania tego problemu?

Jeśli mój SBT może skompilować dobrze, to nie powinno być żadnego takiego IllegalAccessError, więc oznacza to, że są różnice między moim lokalnym kodem a kodem klastra, który jest prawdopodobnie zależnością iskrową provided, ale jest to ta sama wersja jako klaster.

Jestem w porządku, pozostawiając rzeczy takimi, jakie są, ale byłoby lepiej, gdyby można było użyć nowszych wersji. Lub przynajmniej chcę zrozumieć, dlaczego ten problem występuje i uniknąć go w przyszłości.

Odpowiedz

1

Wpadłem dzisiaj na ten sam problem i znalazłem this issue na github, który wyjaśnia problem. Zasadniczo masz wiele ClassLoaders przy użyciu Spark

i io.netty.handler.ssl.NettySslPackageAccessor i io.netty.handler.ssl.JdkSslContext są ładowane przez różne ClassLoaders.

Jeśli jest to przypadek, dostęp próba pakietowe-prywatnego statyczne JdkSslContext.SUPPORTED_CIPHERS polowe zawiedzie z IllegalAccessError od pola pakietowe-prywatne są „scoped” w , poziom ClassLoader.

Aha, i twoje rozwiązanie również zadziałało dla mnie, dzięki.

+0

Ma sens. Wygląda na to, że nic nie mogę na to poradzić. No cóż. Dzięki. – tamatama

0

Jest to spowodowane posiadaniem obu ścieżek klasy io.netty:netty i org.asynchttpclient:async-http-client. Jeśli chcesz użyć netty i assync-http-client, dodaj poniższe zależności do gradle (podobne dla maven pom.xml) skrypt budowania:

compile 'org.asynchttpclient:async-http-client:2.0.38' compile 'org.asynchttpclient:async-http-client-netty-utils:2.0.38'

Powiązane problemy