高負荷時に「java.net.NoRouteToHostException: 要求アドレスに割り当てられません」が発生した場合の対応方法
Javaで作成したWebAPIの負荷試験を行っている最中に次のようなExceptionが発生しました。
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. at sun.reflect.GeneratedConstructorAccessor1475.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:422) at com.mysql.jdbc.Util.handleNewInstance(Util.java:408) at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1137) at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:356) at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2504) at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2541) at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2323) at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:832) at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46) at sun.reflect.GeneratedConstructorAccessor1288.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:422) at com.mysql.jdbc.Util.handleNewInstance(Util.java:408) at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:417) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:344) at java.sql.DriverManager.getConnection(DriverManager.java:664) at java.sql.DriverManager.getConnection(DriverManager.java:247) at core.dts.mysql.MysqlConnection.Open(MysqlConnection.java:120) at core.dts.mysql.MysqlConnection.Query(MysqlConnection.java:203) at core.dts.mysql.MysqlShard.Query(MysqlShard.java:174) at core.dts.mysql.MysqlShard.Query(MysqlShard.java:190) at core.mdl.record.Record.RecordRead(Record.java:186) at core.mdl.record.RecordManager.GetRecord(RecordManager.java:135) at app.mdl.record.usr.UserAccount.GetInstance(UserAccount.java:292) at app.ctrl.BaseAction.InitUserData(BaseAction.java:210) at app.ctrl.BaseAction._Execute(BaseAction.java:106) at core.ctrl.Action._OnExecute(Action.java:475) at core.ctrl.Action.Execute(Action.java:660) at core.Application.Execute(Application.java:370) at core.ctrl.Let.OnRequest(Let.java:66) at core.ctrl.Let.doPost(Let.java:32) at javax.servlet.http.HttpServlet.service(HttpServlet.java:648) at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:291) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:239) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:219) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:142) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:610) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:518) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1091) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:668) at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1517) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1474) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Thread.java:745) Caused by: java.net.NoRouteToHostException: 要求アドレスに割り当てられません at java.net.PlainSocketImpl.socketConnect(Native Method) at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:345) at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) at java.net.Socket.connect(Socket.java:589) at java.net.Socket.connect(Socket.java:538) at java.net.Socket.<init>(Socket.java:434) at java.net.Socket.<init>(Socket.java:244) at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:258) at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:306) ... 51 more
The last packet sent successfully to the server was 0 milliseconds ago.
java.net.NoRouteToHostException: 要求アドレスに割り当てられません
(´(ェ)`)・・・
(´(ェ)`)?
普通にアクセスする分には問題ないのですが、JMeterによる高負荷をかけると1分経過したぐらいからエラーが発生して、それ以降はDBアクセスができない状態になります。
しかし暫くするとまたDBアクセスできるようになる謎の現象に見舞われました。
MySQLにエラーログが出てないことから当初はTomcatやJDBC周りを疑ったのですが、実はOS(CentOS 6.6)の問題でした。
どうやらローカルポートを食いつぶしているのが原因だったようです。
■ 参考サイト
ローカルポートを食いつぶしていた話
上記サイトを参考にしてOSの設定を弄ってみました。
/etc/sysctl.confの末尾に次の3行を追加します。
net.ipv4.ip_local_port_range = 32768 65000 net.ipv4.tcp_tw_recycle = 1 net.ipv4.tcp_fin_timeout = 10
sysctl.conf修正後は次のコマンドで設定を反映します。
sysctl -p
設定後はエラーが出なくなりました( ・´ー・`)b