Restlet客户端重复调用Restlet服务器挂起
我正在使用 Restlet 来实现 Web 服务。客户端(也使用 Restlet)对服务器进行多次连续调用,但在成功完成少量调用后,进一步的调用会挂起服务器,显示以下消息:
信息:停止接受新的连接和交易。考虑增加最大线程数。
我尝试过:
getContext().getParameters().add("maxThreads", "200");
但这没有帮助。无论如何,客户端似乎应该能够进行无限数量的调用,而增加 maxThreads 只会增加限制。看起来我没有在每次客户端调用后释放一些资源或断开连接,但我不知道该怎么做。
下面的(我能做到的很小的)独立程序演示了这个问题。它启动一个简单的服务器,然后客户端多次调用它:
/** 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);
}
}
I am using Restlet to implement a web service. 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:
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. 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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我们只能通过直接停止 ClientResource 的关联客户端来解决问题(使用 Restlet 版本 2.0.15):
We were only able to solve the problem by stopping the ClientResource's associated client directly (using Restlet version 2.0.15):
添加一行,以便客户端将资源释放:
到客户端,一切正常。如果客户端死机,服务器最终会超时,但这需要一段时间。
Add a line so that the client releases the resource:
to the client and everything works. Eventually the server times out if the client dies, but that takes a while.
我已经解决了下载 Restlet API 的最新稳定版本的问题
,显然我一直在使用 .jar使用的是旧版本,其中
release()
命令不起作用。更新之前客户端日志仅输出客户端的启动:
现在它也输出停止:
I've solved my problem downloading the last stable release of the Restlet API
Apparently the .jar the I've been using were an old version where the
release()
command doesn't make any effect.Before the update the client log only outputs the start of the client:
Now it are outputing the stop too:
除了调用 ClientResource.release() 之外,您可能还想在表示上调用 exhaus() 。
此帖子中的相关讨论。
In addition to calling ClientResource.release(), you may want to call exhaust() on the representation.
Related discussion in this thread.