2011-11-23 29 views
6

Estoy utilizando Restlet para implementar un servicio web. El cliente (también usa Restlet) realiza muchas llamadas consecutivas al servidor, pero después de que se complete un número pequeño de llamadas, cuelgan el servidor, que muestra el mensaje:Las llamadas repetidas del cliente Restlet al servidor Restlet se cuelgan

INFORMACIÓN: Deja de aceptar nuevas conexiones y transacciones . Considere aumentar la cantidad máxima de hilos.

me trataron:

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

pero eso no ayuda. En cualquier caso, parece que el cliente debe poder hacer un número ilimitado de llamadas, y aumentar maxThreads solo sube el límite. Parece que no estoy liberando recursos o desconectándome después de cada llamada de cliente, pero no sé cómo hacerlo.

El siguiente (pequeño como podría hacerlo) programa independiente demuestra el problema. Se inicia un servidor simple y luego un cliente llama a un montón de veces:

/** 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

El par de valor de la clave maxThreads param eter debe establecerse en org.restlet.Server, no en org.restlet.Component. De esta manera: 'Server server = mycomponent.getServers(). Add (Protocol.HTTP," localhost ", 9090); server.getContext(). GetParameters(). Add ("maxThreads", "20"); ' –

Respuesta

4

añadir una línea para que el cliente libera el recurso:

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

al cliente y todo funciona. Finalmente, el servidor agota el tiempo de espera si el cliente muere, pero eso lleva un tiempo.

0

Además de llamar a ClientResource.release(), es posible que desee llamar a escape() en la representación.

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

Discusión relacionada en this thread.

1

he resuelto mi problema al descargar la última versión estable del Restlet API

Al parecer, el .jar el que he estado usando eran una versión antigua, donde el comando release() no tiene ningún efecto.

Antes de la actualización del registro de cliente sólo produce la salida del inicio del cliente:

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

Ahora se outputing la parada demasiado:

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

¿Le importaría ser explícito sobre qué versión estaba usando y qué versión solucionó el problema? Ayudaría a otros (¡incluyéndome a mí!) A resolver los problemas. –

5

sólo hemos podido resolver el problema deteniendo el cliente asociado de ClientResource directamente (utilizando Restlet versión 2.0.15):

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

Parece que también tuve que hacer esto para que los hilos mueran rápidamente, pero quizás esto sea un problema con la versión específica de Restlet? (ver la respuesta de @ kassius-vargas-prestes arriba) - ¿Qué versión estás usando? –

+1

La versión que usamos era 2.0.15, la última versión estable en este momento (y aún lo es) – mahnkong

+0

Gracias, estamos usando la misma versión, por lo que voy a dejar este explícito .stop() en nuestro código base por el momento. –

Cuestiones relacionadas