Подтвердить что ты не робот

Boost:: ASIO: оптимизируйте минимальный трафик, длительное соединение, небольшие сообщения, мгновенно переданные

Я пишу протокол в Boost:: ASIO, который имеет следующие требования:

  • Соединения являются долговечными и должны использовать минимальные накладные расходы, чтобы "продолжать жить".
  • Сообщения небольшие, и их необходимо передать мгновенно.

Существуют ли дополнительные флажки сокета TCP или настройки Boost:: ASIO?

socket_.set_option(boost::asio::ip::tcp::no_delay(true));   // enable PSH
socket_.set_option(boost::asio::socket_base::keep_alive(true)); // enable SO_KEEPALIVE
socket_.set_option(boost::asio::detail::socket_option::integer<SOL_TCP, TCP_KEEPIDLE>(120)); // secs before keepalive probes
socket_.set_option(boost::asio::detail::socket_option::integer<SOL_TCP, TCP_KEEPINTVL>(10)); // interval between keepalive
socket_.set_option(boost::asio::detail::socket_option::integer<SOL_TCP, TCP_KEEPCNT(5)); // failed keepalive before declaring dead
4b9b3361

Ответ 1

TL; DR - протокол будет обрабатывать то, что называется "тонкие потоки" , и они достаточно хорошо документированы, если моего ответа будет недостаточно. Наибольшее преимущество должно быть от no_delay(true) и async чтения/записи (для нормальной работы) и двойных и линейных тайм-аутов (для восстановления после сбоев). Более подробную информацию (включая параметры статического/серверного TCP) и дополнительные замечания см. Ниже.

В общем, я бы выбрал эти опции, рассмотрев следующее:

  • Что такое usecase? В вашем случае длительный (как долго?), Соединение, по которому будут отправляться небольшие сообщения без буферизации. Необходим небольшой объем следа. Это похоже на классический "тонкий поток" .
  • Каким будет лучший протокол транспортного уровня? https://en.wikipedia.org/wiki/Transport_layer#Protocols - есть куча, каждая из которых имеет свои собственные варианты использования. На данный момент, я полагаю, вам действительно нужен TCP для надежности и ориентации на соединение, в противном случае протоколы на основе udp могут быть лучше (примером может быть UDP-lite, который позволяет выполнять частичные контрольные суммы и базовое решение надежности на уровне приложения (или слой, который вы, как разработчик, будет реализовывать).
  • Выбрав базовый протокол, который я хочу построить, исследуйте параметры настройки 4, этот протокол. Для TCP это:

    • Алгоритм Nagle - буферизация данных, вы правильно отключили его.
    • Delayed ACK - объединяет ACK, полезный для telnet-подобных приложений, где нет необходимости отправлять ACK для каждого переданного символа. TCP_QUICKACK, если вам нужно обратное - ACK отправляется немедленно. Если вы отправляете данные очень редко, это может быть полезно.
    • Keepalive probes - я вижу, вы используете довольно короткие значения. Не уверен, как вы определились с этими конкретными значениями, но вы можете рассмотреть возможность их расширения, чтобы "минимальные накладные расходы, чтобы" поддерживать ". По умолчанию для linux: 7200, 75, 9.
    • Флаг PSH - полезный для понимания, в основном неиспользованный/игнорируемый/нерелевантный.
    • Флаг URG - пересылает срочные данные на отдельный канал в приложение, полезно, если вы планируете получать данные вне диапазона (некоторые управляющие данные, например, аннулирование). Вероятно, это не полезно в вашем случае, поскольку для данных OOB мало места для "тонких потоков".
    • TCP Windows (RWND/CWND) - неприменимо для небольших, редко отправленных сообщений. Окна должны быть достаточными для размещения данных.
    • Размер окна после простоя (SSR) - Not surprisingly, SSR can have a significant impact on performance of long-lived TCP connections that may idle for bursts of time — e.g., due to user inactivity. As a result, it is generally recommended to disable SSR on the server to help improve performance of long-lived HTTP connections. Взято из здесь. Опция: sysctl -w tcp_slow_start_after_idle=0
    • Быстрая пересылка TCP - tcp_thin_dupack должна быть включена. Это уменьшает время ожидания отправителя перед повторной передачей потерянного сегмента. Будьте осторожны, чтобы читать и экспериментировать с мерами предосторожности (может быть указано для каждого сокета, см. Пункт сразу ниже).
    • tcp_thin_linear_timeouts - это позволяет быстрее восстанавливать потери пакетов, их можно указать для каждого сокета: https://nnc3.com/mags/LJ_1994-2014/LJ/219/11180.html
    • TFO_FASTOPEN (TFO): - сокращает первоначальное установление соединения. Не очень подходит для долгоживущих соединений, но может быть рассмотрен.
    • Сжатие - в соответствии с информацией, которую я вижу, она не должна использоваться в вашем случае (а не параметр TCP, который можно добавить поверх TCP), поскольку она добавит латентность, которая, как я считаю, вы избегаете. Добавление этих параметров в случае, если это неверно.
  • Некоторые детали инфраструктуры, которые должно обрабатывать приложение, или документация протокола.

    • Для длительных соединений, если они завершены на стороне сервера, состояние TIME_WAIT будет иметь важное значение. Задержка TIME_WAIT берет на себя сторона, которая запускает завершение соединения, поэтому в зависимости от использования вашего приложения/протокола это может быть предметом рассмотрения. Это зависит от того, как вы будете обрабатывать завершение соединения.
    • Эфемерные порты - возможно, увеличение количества эфемерных портов для размещения этих долговременных соединений будет полезно, но не обязательно. Это возможная точка маркера документации для вашего протокола.

Если ваш протокол настроен для telnet, как связь, вы можете увидеть эту реализацию telnet. В основном это полный async пишет и читает: https://lists.boost.org/boost-users/att-40895/telnet.cpp

Некоторые хорошие чтения:

https://www.extrahop.com/company/blog/2016/tcp-nodelay-nagle-quickack-best-practices/ https://sourceforge.net/p/asio/mailman/asio-users/?page=257 - для дополнительной помощи.