Java socketRead0 Problem
Ich bin der Entwicklung einer web-cralwer mit htmlunit und ich habe alle erforderlichen timeout, aber ich merke, dass die app hängt sich auf, wenn der server, der die website gecrawlt wurde nicht reagiert, wenn ich den Java VisualVM zu tun, einen thread dump:
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.net.SocksSocketImpl.readSocksReply(SocksSocketImpl.java:88)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:429)
at java.net.Socket.connect(Socket.java:525)
at com.gargoylesoftware.htmlunit.SocksSocketFactory.connectSocket(SocksSocketFactory.java:89)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:148)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)
at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:573)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:776)
at com.gargoylesoftware.htmlunit.HttpWebConnection.getResponse(HttpWebConnection.java:152)
at app.plugin.core.net.QHttpWebConnection.getResponse(QHttpWebConnection.java:30)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponseFromWebConnection(WebClient.java:1439)
at com.gargoylesoftware.htmlunit.WebClient.loadWebResponse(WebClient.java:1358)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:307)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:373)
at com.gargoylesoftware.htmlunit.WebClient.getPage(WebClient.java:358)
Dies ist wirklich frustrierend, da ich haben keine Kontrolle über diese Server. Dieses Problem ist ernst, die die performance meiner Anwendung.
Frage:
- Wie kann ich dieses Problem lösen?
- Gibt es eine Möglichkeit um eine Liste von socket-Verbindung geöffnet, indem eine Java-app, und verwenden, beenden Sie die Steckdose, wie simluate, dass der server die Verbindung geschlossen?
- Wie wollen Sie, dass der thread gesperrt wird? sein status wird als lauffähige. Wenn es blockiert wurde, wäre es gewesen, "Wartend" oder "Gesperrt".
- Offensichtlich haben Sie nicht alle benötigten timeouts 😉 Kann Sie zeigen, welche timeouts Sie haben?
- Bhatt, ich habe nicht gesagt, der thread war block. @ Roger Lindsjö, fügte ich alle erforderlichen timeout, was ich bin, ist insbesondere das hängen an java.net.SocketInputStream.socketRead0
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich glaube, dass, wenn Sie in einem Java-native-Methode, die den stack-trace wird sagen AUSFÜHRBAR, auch wenn der Anruf tatsächlich blockiert, wartet auf irgendein Ereignis. Im Grunde glaube ich nicht, Java hat keine Möglichkeit zu wissen, was für eine native Methode ist eigentlich dabei, so kennzeichnet es diese Anrufe als "AUSFÜHRBAR". Ich habe gesehen, wie diese mit socketRead0() und socketAccept() -- beide in der Regel blockieren.
Sie benötigen, um Ihr timeout, um eine angemessene Länge der Zeit, so dass Ihre Anfrage ein Timeout, wenn der server nicht mehr reagiert, aber nicht zu kurz, im Falle der server ist einfach ausgelastet. Ihre Bewerbung sollte geschrieben werden, um die Verwendung mehrerer threads. Ich würde versuchen, ein Dutzend oder mehr threads, und jeder thread warten, bis zu fünf oder zehn Sekunden für eine Antwort. Es gibt praktisch keinen overhead in einer Handvoll threads warten. Sie sollten auch darauf achten, nicht zu bombardieren, ein server mit vielen Anfragen, die beim schreiben einer web-spider.
Hier ist ein blog-post, die möglicherweise im Zusammenhang mit: http://javaeesupportpatterns.blogspot.fi/2011/04/javanetsocketinputstreamsocketread0.html
Kurz gesagt, die Lösung ist, um sicherzustellen, dass socket-timeout definiert ist. Der Standardwert ist 0, D. H. kein timeout. Wie genau, das hängt von der Bibliothek, in diesem Fall offenbar
com.gargoylesoftware.htmlunit
. Auf den ersten Blick die richtige Methode könnte werden com.gargoylesoftware.htmlunit.WebClient.setTimeout.Wenn Ihr Java-server auf Windows -, Ihre Letzte resort ist mit SysInternals TCPView.
http://technet.microsoft.com/en-us/sysinternals/bb897437.aspx
Daraus sehen Sie die Liste aller Prozesse, und alle lokalen und remote-ports, die Ihre Java-app. Sie haben zu wählen die richtige Verbindung zu schließen, und nach, dass der Java-Thread wird eine Ausnahme ausgelöst und Ende.
Gibt es natürlich die Gefahr der Schließung der falschen Verbindung. Immerhin, diese Methode der Letzte Ausweg.
Update in 23 Aug 2019:
TCPView ist langsam, wenn es gibt eine große Menge von verbindungen.
Viel schnellere alternative ist CurrPorts (von NirSoft): https://www.nirsoft.net/utils/cports.html