简体   繁体   English

Restlet客户端重复调用Restlet服务器挂起

[英]Repeated calls by Restlet client to Restlet server hangs

I am using Restlet to implement a web service. 我正在使用Restlet来实现Web服务。 The client (also uses Restlet) makes many consecutive calls to the server, but after a small number of calls complete successfully, further calls hang the server, which shows the message: 客户端(也使用Restlet)对服务器进行多次连续调用,但在少量调用成功完成后,进一步调用会挂起服务器,显示消息:

INFO: Stop accepting new connections and transactions. 信息:停止接受新的连接和事务。 Consider increasing the maximum number of threads. 考虑增加最大线程数。

I tried: 我试过了:

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

but that does not help. 但这没有用。 In any case, it seems like the client should be able to make an unlimited number of calls, and increasing maxThreads just ups the limit. 在任何情况下,似乎客户端应该能够进行无限数量的呼叫,并且增加maxThreads只会增加限制。 It looks like I am not freeing up some resource or disconnecting after each client call, but I do not know how to do so. 看起来我没有释放一些资源或在每次客户电话后断开连接,但我不知道该怎么做。

The following (small as I could make it) stand alone program demonstrates the problem. 以下(我可以做的很小)独立程序演示了这个问题。 It starts a simple server and then a client calls it a bunch of times: 它启动一个简单的服务器,然后客户端多次调用它:

/** 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);
    }
}

We were only able to solve the problem by stopping the ClientResource's associated client directly (using Restlet version 2.0.15): 我们只能通过直接停止ClientResource的关联客户端来解决问题(使用Restlet版本2.0.15):

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

Add a line so that the client releases the resource: 添加一行,以便客户端释放资源:

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

to the client and everything works. 对客户而言一切正常。 Eventually the server times out if the client dies, but that takes a while. 如果客户端死亡,服务器最终会超时,但这需要一段时间。

I've solved my problem downloading the last stable release of the Restlet API 我已经解决了下载Restlet API最后一个稳定版本的问题

Apparently the .jar the I've been using were an old version where the release() command doesn't make any effect. 显然,我一直使用的.jar是旧版本,其中release()命令没有任何效果。

Before the update the client log only outputs the start of the client: 在更新之前,客户端日志仅输出客户端的开头:

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

Now it are outputing the stop too: 现在它也输出了止损:

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

In addition to calling ClientResource.release(), you may want to call exhaust() on the representation. 除了调用ClientResource.release()之外,您可能还想在表示上调用exhaust()。

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

Related discussion in this thread . 此主题中的相关讨论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM