발생 환경
현재 프로젝트에서 Dropwizard를 적용하고 있는데, Mesos와 연계할 부분이 생겨서 Mesos Client를 구성하고 Ning을 사용해서 비동기 Http 클라이언트를 구성하였다. 그런데 디버그 모드일 때는 상관이 없지만 (아마도 처리가 되는 시간적인 부분이 있는 듯 하다) 실행에서
java.io.IOException: Unable to establish loopback connection
오류가 발생하는 것을 확인하였다.오류 메시지
4047 ERROR 2015-02-26 14:01:13 [main] com.ning.http.client.AsyncHttpClient[loadDefaultProvider:561] -Unable to instantiate provider com.ning.http.client.providers.netty.NettyAsyncHttpProvider. Trying other providers.
4053 ERROR 2015-02-26 14:01:13 [main] com.ning.http.client.AsyncHttpClient[loadDefaultProvider:564] -org.jboss.netty.channel.ChannelException: Failed to create a selector.
org.jboss.netty.channel.ChannelException: Failed to create a selector.
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.openSelector(AbstractNioSelector.java:343) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioSelector.(AbstractNioSelector.java:100) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorker.(AbstractNioWorker.java:52) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioWorker.(NioWorker.java:45) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioWorkerPool.createWorker(NioWorkerPool.java:45) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioWorkerPool.createWorker(NioWorkerPool.java:28) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorkerPool.newWorker(AbstractNioWorkerPool.java:143) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.AbstractNioWorkerPool.init(AbstractNioWorkerPool.java:81) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioWorkerPool.(NioWorkerPool.java:39) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioWorkerPool.(NioWorkerPool.java:33) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory.(NioClientSocketChannelFactory.java:151) ~[netty-3.9.2.Final.jar:na]
at org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory.(NioClientSocketChannelFactory.java:133) ~[netty-3.9.2.Final.jar:na]
at com.ning.http.client.providers.netty.NettyAsyncHttpProvider.(NettyAsyncHttpProvider.java:261) ~[async-http-client-1.8.12.jar:na]
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.7.0_67]
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57) ~[na:1.7.0_67]
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.7.0_67]
at java.lang.reflect.Constructor.newInstance(Constructor.java:526) ~[na:1.7.0_67]
at com.ning.http.client.AsyncHttpClient.loadDefaultProvider(AsyncHttpClient.java:554) [async-http-client-1.8.12.jar:na]
at com.ning.http.client.AsyncHttpClient.(AsyncHttpClient.java:187) [async-http-client-1.8.12.jar:na]
at com.msfl.framework.web.NingAsyncHttpClient.(NingAsyncHttpClient.java:71) [classes/:na]
at com.msfl.framework.web.NingHttpClient.(NingHttpClient.java:48) [classes/:na]
at com.msfl.platform.mesos.client.McpMesosClientModule.configure(McpMesosClientModule.java:67) [MesosClient-0.0.1-SNAPSHOT.jar:na]
at com.google.inject.AbstractModule.configure(AbstractModule.java:62) [guice-4.0-beta5.jar:na]
at com.google.inject.spi.ElementsRecordingBinder.install(Elements.java:253) [guice-4.0-beta5.jar:na]
at com.google.inject.spi.Elements.getElements(Elements.java:108) [guice-4.0-beta5.jar:na]
at com.google.inject.internal.InjectorShellInitializer.run(PipeImpl.java:125) ~[na:1.7.0_67]
at sun.nio.ch.PipeImplInitializer.run(PipeImpl.java:97) ~[na:1.7.0_67]
… 49 common frames omitted
원인 유추
문제는 모듈 초기화 시점 (Google Guice 사용)에 AsyncHttpClient 를 생성하는 시점과 실제 생성된 객체를 사용하는 시점이 다르다는 점이고, 오류는 초기화 시점에 발생한다. 물론 그 이후에 실제 사용할 때는 별다른 문제가 없다. (이런 증상 때문에 시간적인 문제라고 유추하고 있다. ㅠㅠ)
해결 방법
정확한 해결방법이라고 볼 수는 없지만 JVM이 시작할 때 IP version prefs를 처리할 때 IPv6를 사용하기 때문인 것으로 보인다. 즉 Loopback
연결을 처리하면서 IPv6를 먼저 처리하고 실패 후에 IPv4를 시도하는 것으로 보인다는 것이다. 따라서 이런 상황에서는 IPv4를 사용하도록 JVM 옵션을 설정하면 된다.
-Djava.net.perferIPv4Stack=true
위의 옵션을 주고 실행을 하면 위에서 발생했던 오류는 해결이 된다. 위에서 언급한 발생 상황뿐만 아니라 아래와 같이 유사한 오류 메시지들이 발생하는 경우라면 적용해 보는 것이 좋다.
- java.net.ConnectionException: Connection refused: connect 오류
- java.io.IOException: Unable to establish loopback connection 오류
상기와 같이 오류의 원인이 두 가지로 나온다면 적용해서 해결될 가능성이 높다. (단, 실제 다른 이유 떄문일 수 있기 때문에 오류 메시지를 면밀하게 검토해봐야 한다)
Written by Morris (MSFL)
댓글
댓글 쓰기