2011-11-23 12 views
6

Sto utilizzando Restlet per implementare un servizio Web. Il client (utilizza anche Restlet) rende molte chiamate consecutive al server, ma dopo un piccolo numero di chiamate completa con successo, ulteriori chiamate appendere il server, che mostra il messaggio:Le chiamate ripetute da parte del client di Restlet al server di Restlet si bloccano

INFORMAZIONI: smettere di accettare nuove connessioni e transazioni . Considera di aumentare il numero massimo di thread.

ho provato:

getContext().getParameters().add("maxThreads", "200"); 

ma questo non aiuta. In ogni caso, sembra che il client dovrebbe essere in grado di effettuare un numero illimitato di chiamate e l'aumento di maxThreads limita il limite. Sembra che non sto liberando alcune risorse o disconnesso dopo ogni chiamata client, ma non so come farlo.

Quanto segue (piccolo come potrei farlo) programma stand alone dimostra il problema. Si inizia un server semplice e poi un cliente chiama un mucchio di volte:

/** You may copy, modify, and re-use this code as you see fit - Jim Irrer */ 
import java.io.ByteArrayInputStream; 
import java.io.IOException; 
import java.io.InputStream; 

import org.restlet.Application; 
import org.restlet.Component; 
import org.restlet.Request; 
import org.restlet.Response; 
import org.restlet.Restlet; 
import org.restlet.Server; 
import org.restlet.data.MediaType; 
import org.restlet.data.Method; 
import org.restlet.data.Protocol; 
import org.restlet.data.Status; 
import org.restlet.representation.InputRepresentation; 
import org.restlet.representation.Representation; 
import org.restlet.resource.ClientResource; 
import org.restlet.resource.Directory; 

public class SimpleServerPut extends Component implements Runnable { 
    private static final int PORT = 8080; 

    private static int readToByteArray(InputStream inputStream, byte[] buf) throws IOException { 
     int length = 0; 
     int b; 
     while ((b = inputStream.read()) != -1) { 
      buf[length++] = (byte)b; 
     } 
     return length; 
    } 

    @Override 
    public void run() { 
     getContext().getParameters().add("maxThreads", "200"); 

     // Create the HTTP server and listen on port PORT 
     SimpleServerPut simpleServer = new SimpleServerPut(); 
     Server server = new Server(Protocol.HTTP, PORT, simpleServer); 
     simpleServer.getClients().add(Protocol.FILE); 

     // Create an application 
     Application application = new Application(simpleServer.getContext()) { 
      @Override 
      public Restlet createRoot() { 
       return new Directory(getContext(), "C:"); 
      } 
     }; 

     // Attach the application to the component and start it 
     simpleServer.getDefaultHost().attach("/stuff/", application); 
     try { 
      server.start(); 
     } 
     catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    @Override 
    public void handle(Request request, Response response) { 
     // assume the worst 
     response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED); 
     response.setEntity("No no - Bad client! Only do PUTs.", MediaType.TEXT_PLAIN); 

     try { 
      if (request.getMethod() == Method.PUT) { 
       InputStream inputStream = request.getEntity().getStream(); 
       byte[] buf = new byte[64*1024]; 
       int totalLength = readToByteArray(inputStream, buf); 
       response.setStatus(Status.SUCCESS_OK); 
       String msg = "Number of bytes received: " + totalLength; 
       response.setEntity(msg, MediaType.TEXT_PLAIN); 
       System.out.println("server: " + msg); 
       return; 
      } 
     } 
     catch (Exception ex) { 
      ex.printStackTrace(); 
     } 
    } 

    private static String callServer() throws IOException { 
     String urlText = "http://localhost:" + PORT + "/"; 
     ClientResource clientResource = new ClientResource(urlText); 
     clientResource.setReferrerRef(urlText); 

     byte[] buf = new byte[1000]; 
     for (int i = 0; i < buf.length; i++) { 
      buf[i] = (byte)((int)'a' + (i%26)); 
     } 
     ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buf); 
     Representation representation = new InputRepresentation(byteArrayInputStream, MediaType.APPLICATION_OCTET_STREAM); 
     Representation representation2 = clientResource.put(representation); 
     byte[] responseBuf = new byte[16*1024]; 
     int length = readToByteArray(representation2.getStream(), responseBuf); 
     Response response = clientResource.getResponse(); 
     Status status = response.getStatus(); 
     return "status: " + status + " message: " + new String(responseBuf, 0, length); 
    } 

    // Start server and call it a bunch of times 
    public static void main(String[] args) throws Exception { 
     SimpleServerPut simpleServer = new SimpleServerPut(); 
     new Thread(simpleServer).start(); 
     Thread.sleep(200); // cheap trick to make sure that server is running 
     // make a bunch of client calls 
     for (int t = 0; t < 100; t++) { 
      System.out.println("client count: " + (t+1) + " " + callServer()); 
     } 
     System.exit(0); 
    } 
} 
+1

Il parametro coppia di valori chiave maxThreads eter deve essere impostato in org.restlet.Server, non nell'org.restlet.Component. In questo modo: 'Server server = mycomponent.getServers(). Add (Protocol.HTTP," localhost ", 9090); server.getContext(). GetParameters(). Add ("maxThreads", "20"); ' –

risposta

4

Aggiungere una linea in modo che il cliente rilascia la risorsa:

Response response = clientResource.getResponse(); 
    Status status = response.getStatus(); 
    clientResource.release(); // add this line 

al cliente e tutto funziona. Alla fine il server scade se il client muore, ma ci vuole un po '.

0

Oltre a chiamare ClientResource.release(), è possibile chiamare exhaust() sulla rappresentazione.

Representation responseRepresentation = response.getEntity(); 
if (responseRepresentation != null) { 
    try { 
     responseRepresentation.exhaust(); 
    } catch (IOException e) { 
     // handle exception 
    } 
    responseRepresentation.release(); 
} 

Discussioni correlate in this thread.

1

Ho risolto il mio problema scaricando l'ultima versione stabile del Restlet API

A quanto pare il .jar l'ho usato erano una versione in cui il comando release() non fa alcun effetto.

Prima dell'aggiornamento del registro del client emette solo l'inizio del cliente:

Sep 05, 2012 9:50:19 AM org.restlet.engine.http.connector.HttpClientHelper start 
INFO: Starting the default HTTP client 

Ora sono outputing fermata troppo:

Sep 05, 2012 9:50:19 AM org.restlet.engine.http.connector.HttpClientHelper stop 
INFO: Stopping the default HTTP client 
+0

Ti dispiacerebbe essere esplicito su quale versione stavi utilizzando e quale versione ha risolto il problema? Aiutare gli altri (incluso me!) A risolvere i problemi. –

5

Siamo stati in grado di risolvere il problema arrestando solo il client associato di ClientResource direttamente (utilizzando Restlet versione 2.0.15):

Client c = (Client)clientResource.getNext(); 
try { 
    c.stop(); 
} catch (Exception e) { 
    //handle exception 
} 
+0

Sembra che ho dovuto anche farlo per far morire i thread prontamente, ma forse questo è un problema con la versione specifica di Restlet? (Vedi la risposta di @ kassius-vargas-prestes sopra) - Quale versione stai usando? –

+1

La versione che abbiamo usato era 2.0.15, l'ultima versione stabile in questo momento (e lo è ancora) – mahnkong

+0

Grazie, stiamo usando la stessa versione, e quindi lascerò questo esplicito .stop() nel nostro codebase per ora. –

Problemi correlati