Я использую службу RESTFul HttpGet из
import org.apache.http.client.methods.HttpGet;
Я создал функцию для запроса службы на другом компьютере. Вызов работает нормально, однако я запускаю "слишком много открытых файлов" в службе. Моя сторона просто возвращает ошибку 500, которую я поймаю.
Я говорил с продавцом, и они были совершенно убеждены в том, что звонок RESTful должен быть сделан настойчивым образом и что я просто ничего не освобождаю и продолжаю, что проблема на моей стороне.
Я написал функцию стресса, см. Ниже, чтобы помочь изолировать проблему. Слишком мои знания, я все выпускаю. Я все еще новичок в Java, поэтому я просто не вижу ничего непонятного.
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public void doStressTest()
{
String strUri = "http://<ip address>:<port>/task?vara=dataa&varb=datab";
HttpGet oRestyGet = new HttpGet();
oRestyGet.addHeader("Accept", "application/xml");
for (int iLoop = 0; iLoop < 1000; iLoop++)
{
CloseableHttpClient httpclient = HttpClients.createDefault();
try
{
oRestyGet.setURI(new URI(strUri));
try
{
CloseableHttpResponse response2 = httpclient.execute(oRestyGet);
try
{
String strResponseHeader = response2.getStatusLine().toString();
if (false == "HTTP/1.1 200 OK".equalsIgnoreCase(strResponseHeader))
return;
continue;
}
finally
{
response2.close();
}
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
httpclient.close();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
try
{
oRestyGet.releaseConnection();
}
catch (Exception e)
{
e.printStackTrace();
}
}
ОБНОВЛЕНИЕ: Я думал, что добавлю текст того, что должен сказать продавец, на всякий случай, если это может помочь. Я должен добавить, что в стресс-тесте ниже я открываю один объект запроса HTTP GET, который для моего "сеанса" является постоянным и используется для всего запроса.
Это означает, что у системы заканчиваются FD для пользователя, выполняющего этот процесс. Это происходит, когда слишком много открытых сокетов или FD. В целом с HTTP настоятельно рекомендуется, чтобы HTTP-запросы отправлялись постоянным образом, то есть у вас есть одно HTTP-соединение для всего сеанса, а не открытие нескольких HTTP-соединений, а затем их закрытие для каждого запроса. Чаще всего вы не получаете затяжных связей.
Я закрываю "closeable" CloseableHttpClient, и не думаю, что у меня должен быть только один. Я должен добавить, что у "Я" ничего не заканчивается, служба. Поставщик, кажется, говорит, что сервис идеален, как и ОС. Что еще можно сделать, чтобы изолировать проблему?
ОБНОВЛЕНИЕ 2: (Я отправил файл журнала из службы поставщику, и у них было следующее: Stalemate?)
Похоже, проблема заключается в том, что слишком много соединений остается открытым вашим интерфейсом. Я включил файл журнала из сеанса Firefox. Вы можете увидеть, как я могу сделать несколько HTTP-запросов по одному и тому же соединению с помощью браузера.
Существует только одна строка, в которой выполняется начальное соединение
HTTP-соединение из [127.0.0.1]... РАЗРЕШЕНИЕ
последующие запросы GET связаны с одним и тем же соединением.
... в вашем файле журнала показано: HTTP-соединение из [192.168.20.123]... РАЗРЕШЕНИЕ
для каждого запроса GET, который вы делаете, и эти соединения не закрыты.
ОБНОВЛЕНИЕ 3: У меня есть доступ к журналу, который генерирует служба, хотя и не имеет доступа к источнику. Java выдает соединение и запросы GET как один пакет в ответ на строку:
CloseableHttpResponse response2 = httpclient.execute(oRestyGet);
Я выдаю httpclient.close(), который не генерирует записи в журнале, поэтому я подозреваю, что служба просто не отвечает на это.
Поскольку я не знаком с механиками другого конца, возможно, служба просто реагирует на события, и проблема заключается в том, что CENTOS неправильно обрабатывает вызов close(). В любом случае, используя этот метод, проблема не моя. Доказательство - это еще одна история. Альтернативой является какое-то другое решение, которое правильно освобождает ресурсы.
Том G был прав в своем ответе, что проблема была на стороне поставщика, но причина, по которой я создал другой ответ, заключается в том, что, хотя поставщик не закрыл дескриптор файла, который был открыт, стресс-тест по-прежнему разбился.
Мне пришлось переключиться на Джерси, который решил "httpclient.execute()" выполнить операцию "открыть/закрыть" с каждым запросом GET, а затем поставщик должен был дать мне сборку, которая исправила проблему на их конце, а значит, и две проблемы.
Рамки apache, похоже, имеют проблемы, по крайней мере, с моей реализацией, в то время как среда Sun (Jersey) прекрасно работала в моем стресс-тесте.
Теперь мне нужно протестировать с помощью реального кода.
Если вы получаете 500 Internal Server Error
HTTP 500 Internal Server Error
, это не имеет ничего общего с вашим клиентским кодом или как управлять HTTP-соединениями. Проблема полностью связана с производителем.
Я бы использовал lsof, чтобы посмотреть, какие файлы хранятся в открытом доступе. Вы также можете посмотреть netstat -n -a, чтобы увидеть все открытые соединения. Вы пытались поднять лимит открытых файлов, чтобы увидеть, можете ли вы решить проблему таким образом?