2012-10-05 191 views
1

我正嘗試在我的程序中嵌入一個碼頭服務器,並且在每個線程到達服務器一個請求後它似乎掛起。我寫測試用例代碼:嵌入式Jetty服務器掛起

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import java.io.IOException; 
import java.io.PrintWriter; 
import java.util.Date; 
import java.util.concurrent.atomic.AtomicLong; 

import org.apache.http.HttpEntity; 
import org.apache.http.HttpResponse; 
import org.apache.http.StatusLine; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.DefaultHttpClient; 
import org.mortbay.jetty.Server; 
import org.mortbay.jetty.servlet.Context; 
import org.mortbay.jetty.servlet.ServletHolder; 
import org.mortbay.thread.QueuedThreadPool; 

public class EmbeddedJetty 
{ 
    public static void initServer(int port) throws Exception 
    { 
     final AtomicLong counter = new AtomicLong(); 
     final Server server = new Server(port); 
     server.setThreadPool(new QueuedThreadPool(3)); 
     Context context = new Context(server, "/", Context.SESSIONS); 
     context.addServlet(new ServletHolder(new HttpServlet() 
     { 
      @Override 
      protected void doGet(HttpServletRequest req, 
           HttpServletResponse resp) 
       throws ServletException, IOException 
      { 
       PrintWriter writer = resp.getWriter(); 
       String msg = "Served page #" + counter.incrementAndGet() + 
         " at " + new Date(); 
       writer.print(msg); 
       writer.close(); 
       System.out.println("[Server] " + msg); 

      } 
     }), "/*"); 
     server.start(); 
     System.out.println("[Server] Started Jetty server"); 
    } 

    public static void initClient(final int port) 
    { 
     new Thread() 
     { 
      public void run() 
      { 
       String urlString = "http://localhost:" + port + "/myBT"; 
       while (true) 
       { 
        try 
        { 
         System.out.println("[Client] Sending request to " + 
           urlString); 
         HttpClient httpclient = new DefaultHttpClient(); 
         HttpGet httpget = new HttpGet(urlString); 
         HttpResponse response = httpclient.execute(httpget); 
         StatusLine statusLine = response.getStatusLine(); 

         System.out.println("[Client] Got response [" + 
           response.getProtocolVersion() + "] [" + 
           statusLine.getStatusCode() + "] [" + 
           statusLine.getReasonPhrase() + "]"); 
         HttpEntity entity = response.getEntity(); 
         if (entity != null) 
         { 
          entity.consumeContent(); 
         } 
        } 
        catch (Exception ex) 
        { 
         ex.printStackTrace(); 
        } 
       } 
      } 
     }.start(); 
    } 

    public static void main(String[] args) throws Exception 
    { 
     int port = 8090; 
     initServer(port); 
     initClient(port); 
    } 
} 

這個程序的輸出是:

$ java -cp build/libs/sqlcache.jar EmbeddedJetty 
2012-10-04 23:24:30.797:INFO::Logging to STDERR via org.mortbay.log.StdErrLog 
2012-10-04 23:24:30.842:INFO::jetty-6.1.x 
2012-10-04 23:24:30.945:INFO::Started Sock[email protected]:8090 
[Server] Started Jetty server 
[Client] Sending request to http://localhost:8090/myBT 
[Server] Served page #1 at Thu Oct 04 23:24:31 PDT 2012 
[Client] Got response [HTTP/1.1] [200] [OK] 
[Client] Sending request to http://localhost:8090/myBT 
[Server] Served page #2 at Thu Oct 04 23:24:31 PDT 2012 
[Client] Got response [HTTP/1.1] [200] [OK] 
[Client] Sending request to http://localhost:8090/myBT 

,然後將其掛起。

線程轉儲的樣子:

Full thread dump Java HotSpot(TM) 64-Bit Server VM (20.10-b01-428 mixed mode): 

"[email protected]" prio=5 tid=1029f2000 nid=0x10aa38000 runnable [10aa37000] 
    java.lang.Thread.State: RUNNABLE 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(SocketInputStream.java:129) 
    at org.mortbay.io.ByteArrayBuffer.readFrom(ByteArrayBuffer.java:382) 
    at org.mortbay.io.bio.StreamEndPoint.fill(StreamEndPoint.java:114) 
    at org.mortbay.jetty.bio.SocketConnector$Connection.fill(SocketConnector.java:198) 
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:290) 
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) 
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
    at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228) 
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 

"DestroyJavaVM" prio=5 tid=102928000 nid=0x100501000 waiting on condition [00000000] 
    java.lang.Thread.State: RUNNABLE 

"Thread-5" prio=5 tid=1029d5800 nid=0x10a935000 runnable [10a934000] 
    java.lang.Thread.State: RUNNABLE 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(SocketInputStream.java:129) 
    at org.apache.http.impl.io.AbstractSessionInputBuffer.fillBuffer(AbstractSessionInputBuffer.java:130) 
    at org.apache.http.impl.io.SocketInputBuffer.fillBuffer(SocketInputBuffer.java:127) 
    at org.apache.http.impl.io.AbstractSessionInputBuffer.readLine(AbstractSessionInputBuffer.java:233) 
    at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:98) 
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:210) 
    at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:271) 
    at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:233) 
    at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:209) 
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:292) 
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:126) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:483) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:641) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:576) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:554) 
    at EmbeddedJetty$2.run(EmbeddedJetty.java:67) 

"Timer-0" daemon prio=5 tid=101b8f800 nid=0x10a820000 in Object.wait() [10a81f000] 
    java.lang.Thread.State: TIMED_WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <7f42b20d0> (a java.util.TaskQueue) 
    at java.util.TimerThread.mainLoop(Timer.java:509) 
    - locked <7f42b20d0> (a java.util.TaskQueue) 
    at java.util.TimerThread.run(Timer.java:462) 

"Poller SunPKCS11-Darwin" daemon prio=1 tid=10286e800 nid=0x10a71d000 waiting on condition [10a71c000] 
    java.lang.Thread.State: TIMED_WAITING (sleeping) 
    at java.lang.Thread.sleep(Native Method) 
    at sun.security.pkcs11.SunPKCS11$TokenPoller.run(SunPKCS11.java:692) 
    at java.lang.Thread.run(Thread.java:680) 

"[email protected]155-1 - Acceptor0 [email protected]:8090" prio=5 tid=1019af800 nid=0x10a5ec000 runnable [10a5eb000] 
    java.lang.Thread.State: RUNNABLE 
    at java.net.PlainSocketImpl.socketAccept(Native Method) 
    at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:408) 
    - locked <7f42b2238> (a java.net.SocksSocketImpl) 
    at java.net.ServerSocket.implAccept(ServerSocket.java:462) 
    at java.net.ServerSocket.accept(ServerSocket.java:430) 
    at org.mortbay.jetty.bio.SocketConnector.accept(SocketConnector.java:99) 
    at org.mortbay.jetty.AbstractConnector$Acceptor.run(AbstractConnector.java:708) 
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 

"[email protected]" prio=5 tid=101a12000 nid=0x10a4e9000 runnable [10a4e8000] 
    java.lang.Thread.State: RUNNABLE 
    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(SocketInputStream.java:129) 
    at org.mortbay.io.ByteArrayBuffer.readFrom(ByteArrayBuffer.java:382) 
    at org.mortbay.io.bio.StreamEndPoint.fill(StreamEndPoint.java:114) 
    at org.mortbay.jetty.bio.SocketConnector$Connection.fill(SocketConnector.java:198) 
    at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:290) 
    at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212) 
    at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404) 
    at org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228) 
    at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582) 

"Low Memory Detector" daemon prio=5 tid=1018a8000 nid=0x10a013000 runnable [00000000] 
    java.lang.Thread.State: RUNNABLE 

"C2 CompilerThread1" daemon prio=9 tid=1018a7000 nid=0x109f10000 waiting on condition [00000000] 
    java.lang.Thread.State: RUNNABLE 

"C2 CompilerThread0" daemon prio=9 tid=1018a6800 nid=0x109e0d000 waiting on condition [00000000] 
    java.lang.Thread.State: RUNNABLE 

"Signal Dispatcher" daemon prio=9 tid=1018a5800 nid=0x109d0a000 waiting on condition [00000000] 
    java.lang.Thread.State: RUNNABLE 

"Surrogate Locker Thread (Concurrent GC)" daemon prio=5 tid=1018a4800 nid=0x109c07000 waiting on condition [00000000] 
    java.lang.Thread.State: RUNNABLE 

"Finalizer" daemon prio=8 tid=10189c000 nid=0x1098ea000 in Object.wait() [1098e9000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <7f42c92e0> (a java.lang.ref.ReferenceQueue$Lock) 
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118) 
    - locked <7f42c92e0> (a java.lang.ref.ReferenceQueue$Lock) 
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134) 
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159) 

"Reference Handler" daemon prio=10 tid=10189b000 nid=0x1097e7000 in Object.wait() [1097e6000] 
    java.lang.Thread.State: WAITING (on object monitor) 
    at java.lang.Object.wait(Native Method) 
    - waiting on <7f42b02a8> (a java.lang.ref.Reference$Lock) 
    at java.lang.Object.wait(Object.java:485) 
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116) 
    - locked <7f42b02a8> (a java.lang.ref.Reference$Lock) 

"VM Thread" prio=9 tid=101896800 nid=0x1096e4000 runnable 

"Gang worker#0 (Parallel GC Threads)" prio=9 tid=101802800 nid=0x102201000 runnable 

"Gang worker#1 (Parallel GC Threads)" prio=9 tid=101803000 nid=0x102304000 runnable 

"Concurrent Mark-Sweep GC Thread" prio=9 tid=10184d800 nid=0x1093f0000 runnable 
"VM Periodic Task Thread" prio=10 tid=1018b9800 nid=0x10a116000 waiting on condition 

"Exception Catcher Thread" prio=10 tid=101801800 nid=0x1017fa000 runnable 
JNI global references: 1726 

Heap 
par new generation total 19136K, used 3756K [7f3000000, 7f44c0000, 7f44c0000) 
    eden space 17024K, 9% used [7f3000000, 7f319b348, 7f40a0000) 
    from space 2112K, 100% used [7f42b0000, 7f44c0000, 7f44c0000) 
    to space 2112K, 0% used [7f40a0000, 7f40a0000, 7f42b0000) 
concurrent mark-sweep generation total 63872K, used 350K [7f44c0000, 7f8320000, 7fae00000) 
concurrent-mark-sweep perm gen total 21248K, used 9994K [7fae00000, 7fc2c0000, 800000000) 

我使用Jetty 6.1.26

是什麼導致服務器掛起?

編輯:添加超時,如:

SocketConnector connector = new SocketConnector(); 
    connector.setMaxIdleTime(1000); 
    connector.setSoLingerTime(-1); 
    connector.setPort(port); 
    server.setConnectors(new Connector[] { connector }); 

似乎解決了問題,但我想了解的第一個地方是走錯了。

回答

1

首先,你不需要一個新的HttpClient,你可以重用它。我懷疑你的問題是底層連接未關閉/釋放(參見"Thread-5" prio=5 tid=1029d5800 nid=0x10a935000 runnable [10a934000]

乾杯,

+0

我有同樣的問題。通過[reusing]解決它(http://hc.apache.org/httpclient-legacy/performance.html#Reuse_of_HttpClient_instance)HttpClient。 – firemonkey