Почему значение Recv-Q в netstat равно невыполненной работе сокета + 1?

Когда я выполняю netstat -tulnp, вывод выглядит следующим образом:

Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.11:43043        0.0.0.0:*               LISTEN      -
tcp        0      0 127.0.0.1:8005          0.0.0.0:*               LISTEN      1/java
tcp        0      0 0.0.0.0:2021            0.0.0.0:*               LISTEN      1/java
tcp        0      0 0.0.0.0:22222           0.0.0.0:*               LISTEN      1/java
tcp        0      0 0.0.0.0:8719            0.0.0.0:*               LISTEN      1/java
tcp      101      0 0.0.0.0:80              0.0.0.0:*               LISTEN      1/java
tcp       51      0 0.0.0.0:1234            0.0.0.0:*               LISTEN      1/java
tcp        0      0 0.0.0.0:20891           0.0.0.0:*               LISTEN      1/java
udp        0      0 127.0.0.11:55285        0.0.0.0:*                           -

Ценность Recv-Q привлекла мое внимание. После моего расследования я обнаружил, что OOM произошел в приложении JVM, и в журнале можно найти, что поток http-nio-80-Acceptor-0, отвечающий за мониторинг порта 80, вышел, и поток, отвечающий за диспетчеризацию порта 1234. запросы вышли. Соответствующие журналы следующие:

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "http-nio-80-Acceptor-0"
Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "Thread-5"

Конфигурация по умолчанию, используемая tomcat, то есть отставание равно 100, а исходный код находится по адресу tomcat/AbstractEndpoint.java в 8.5.59 · apache/tomcat · GitHub:

/**
  * Allows the server developer to specify the acceptCount (backlog) that
  * should be used for server sockets. By default, this value
  * is 100.
  */
private int acceptCount = 100;
public void setAcceptCount(int acceptCount) { if (acceptCount > 0) this.acceptCount = acceptCount; }
public int getAcceptCount() { return acceptCount; }

Прослушивание порта 1234 инициируется и создается HTTPServer, и созданный код HttpServer.create(new InetSocketAddress(PROMETHEUS_SERVER_PORT), 0);, отставание исправлено до 50 в ServerSocket.java, исходный код находится по адресу jdk/ServerSocket.java в jdk8-b120 · openjdk/jdk · GitHub:

public void bind(SocketAddress endpoint, int backlog) throws IOException {
    if (isClosed())
        throw new SocketException("Socket is closed");
    if (!oldImpl && isBound())
        throw new SocketException("Already bound");
    if (endpoint == null)
        endpoint = new InetSocketAddress(0);
    if (!(endpoint instanceof InetSocketAddress))
        throw new IllegalArgumentException("Unsupported address type");
    InetSocketAddress epoint = (InetSocketAddress) endpoint;
    if (epoint.isUnresolved())
        throw new SocketException("Unresolved address");
    if (backlog < 1)
      backlog = 50;
    try {
        SecurityManager security = System.getSecurityManager();
        if (security != null)
            security.checkListen(epoint.getPort());
        getImpl().bind(epoint.getAddress(), epoint.getPort());
        getImpl().listen(backlog);
        bound = true;
    } catch(SecurityException e) {
        bound = false;
        throw e;
    } catch(IOException e) {
        bound = false;
        throw e;
    }
}

Из netstat(8) — справочная страница Linux мы знаем, что Recv-Q указывает текущий отставание синхронизации, когда сокет находится в состоянии Listening, что меня смущает, так это то, почему Recv-Q на один больше, чем значение отставания, которое мы установили?

Итак, у вас закончилась память, поэтому ваш принимающий поток перестал принимать, поэтому очередь невыполненных работ выросла до максимального размера. Здесь нужно решить OOM, а не невыполненную очередь.

user207421 31.03.2022 12:43

@user207421 user207421 Мой вопрос в том, почему значение Recv-Q на единицу больше, чем предустановленное невыполненное задание, а не равно невыполненному. Почему значения Recv-Q равны 101 и 51 вместо 100 и 50?

Poison 31.03.2022 14:22

Я смог воспроизвести это поведение в программе на C и используя ss вместо telnet. присматриваюсь к нему дальше...

Liam Kelly 07.04.2022 15:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
42
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

TL;DR netstat/ss сообщает о полных и незавершенных соединениях, в то время как отставание касается только завершенных соединений.

we know, Recv-Q indicates current syn backlog when socket is in Listening state,

Да, это подтверждено на странице sock_diagчеловек. Похоже, что netlink берет это значение из структуры ядра следующий:

rql.udiag_rqueue = sk->sk_receive_queue.qlen;

Глядя на qlen больше, похоже, что это не то же самое, что отставание. qlen включает полные и незавершенные соединения, в то время как отставание относится только к завершенным соединениям. Страница руководства listen отмечает это:

The behavior of the backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number of incomplete connection requests.

Что касается того, почему очередь приема заботится о незавершенных соединениях, я могу только предположить, что она пытается обработать пограничный случай освобождения невыполненной работы, в то время как рукопожатие TCP все еще происходит.

Ответ принят как подходящий

A backlog value of N really does mean allow "N + 1" connections to queue to a listening socket. This allows one to specify "0" as the backlog and still get 1 connection.

Ссылка: NET: отмените неправильные изменения невыполненной очереди приема. · Торвальдс/Linux@64a1465 · GitHub

Другие вопросы по теме