Java HttpGet, слишком много открытых файлов в сервисной ошибке

1

Я использую службу 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(). В любом случае, используя этот метод, проблема не моя. Доказательство - это еще одна история. Альтернативой является какое-то другое решение, которое правильно освобождает ресурсы.

Теги:
httpclient
rest

3 ответа

0
Лучший ответ

Том G был прав в своем ответе, что проблема была на стороне поставщика, но причина, по которой я создал другой ответ, заключается в том, что, хотя поставщик не закрыл дескриптор файла, который был открыт, стресс-тест по-прежнему разбился.

Мне пришлось переключиться на Джерси, который решил "httpclient.execute()" выполнить операцию "открыть/закрыть" с каждым запросом GET, а затем поставщик должен был дать мне сборку, которая исправила проблему на их конце, а значит, и две проблемы.

Рамки apache, похоже, имеют проблемы, по крайней мере, с моей реализацией, в то время как среда Sun (Jersey) прекрасно работала в моем стресс-тесте.

Теперь мне нужно протестировать с помощью реального кода.

1

Если вы получаете 500 Internal Server Error HTTP 500 Internal Server Error, это не имеет ничего общего с вашим клиентским кодом или как управлять HTTP-соединениями. Проблема полностью связана с производителем.

  • 0
    Я согласен с вами, однако приму ответ, что проблема на стороне продавца. Я должен быть в состоянии создать / уничтожить объект HTTP GET-запроса, ну да ладно, может быть, просто есть. Приведенный выше код стресс-теста выглядит завершенным и должен работать. Есть или нет альтернативные решения - это другая тема. Я попытаюсь захватить журнал и отправить поставщику.
  • 0
    Проблема возникает прежде, чем служба / ОС исчерпает файловые дескрипторы (FD). Проблема заключается в освобождении соединения, когда-то созданного, что не происходит. Я проверил доступные мне свойства, и close () из httpclient - единственный, который я вызываю. Вполне возможно, что, возможно, у httpclient есть проблема. Многое зависит от техники слоев ниже моего вызова.
0

Я бы использовал lsof, чтобы посмотреть, какие файлы хранятся в открытом доступе. Вы также можете посмотреть netstat -n -a, чтобы увидеть все открытые соединения. Вы пытались поднять лимит открытых файлов, чтобы увидеть, можете ли вы решить проблему таким образом?

Слишком много открытых файлов (ulimit уже изменен)

  • 0
    Я не знал о команде lsof. Спасибо. Команда lsof показывает 1006 одинаковых строк. Это мои запросы на стресс-тест. Служба взорвалась в 1007, так что это правильно. «netstat -n -a» не показал ничего интересного, что я видел. Общее количество выходных данных для всей команды было 512, так что все в порядке. Я предполагаю, что lsof списки FD, что соответствует тому, что говорит поставщик. Что мне делать с этой информацией?
  • 0
    Я не увеличил лимит открытых файлов, пришлось бы исследовать, как это сделать, но это не принесло бы пользы, так как проблема возникла бы чуть позже. Один запрос равен одному дескриптору файла, оставленному открытым, пока я не закрою службу или не перезапущу ОС.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню