Boost :: ASIO:针对最小流量,长连接,小消息进行优化,立即传递

时间:2018-01-01 06:20:53

标签: c++ sockets boost tcp boost-asio

我正在Boost :: ASIO中编写一个协议,它有以下要求:

  1. 连接是持久的,并且尽可能使用最小的开销来“保持活力”。
  2. 消息很小,需要立即传递。
  3. 我应该使用其他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
    

1 个答案:

答案 0 :(得分:16)

TL; DR - 该协议将处理所谓的&#34;精简流&#34; ,并且如果我的答案不是足够。最大的优势应该来自no_delay(true)async读/写(用于正常操作)和dupACK和线性超时(用于故障恢复)。有关更多详细信息(包括静态/服务器TCP选项)和其他备注,请参阅下文。

一般情况下,我会考虑以下因素来选择这些选项:

  1. 我的用例是什么?在你的情况下,一个持久的(多长时间?),连接将通过哪些小消息发送无缓冲。需要一个小的保持活力的足迹。这似乎是经典的&#34;瘦流&#34; 示例。
  2. 使用哪种最佳传输层协议https://en.wikipedia.org/wiki/Transport_layer#Protocols - 每个人都有自己的用例。在这一点上,我认为,你确实需要TCP用于可靠性和面向连接,否则,基于udp的协议可能会更好(例如UDP-lite,它允许在应用层进行部分校验和和底层可靠性决策(或者您作为开发人员将实施的层。
  3. 选择了我想要构建的基础协议 - 调查调整选项 4该协议。对于TCP,这些是:

    • Nagle的算法 - 数据缓冲,你把它正确关闭了。
    • 延迟ACK - 组合ACK,对于类似telnet的应用程序非常有用,在这种情况下,不需要为每个传输的字符发送ACK。 TCP_QUICKACK如果需要相反 - 立即发送ACK。如果您很少发送数据,它可能会有用。
    • Keepalive探测器 - 我看到你使用非常短的值。不确定你是如何决定这些特定的值,但你可以考虑扩展它们,以尽可能保持最小的开销,以及#34;保持活力&#34;。 linux的默认值:7200,75,9。
    • PSH标志 - 对理解很有用,很大程度上未使用/忽略/不相关。
    • URG标志 - 在单独的通道上将紧急数据转发给应用程序,如果您计划在带外接收数据(某些控制数据,如取消),则非常有用。可能在您的情况下没有用,因为在&#34;瘦流&#34;的情况下,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.取自here。选项:sysctl -w tcp_slow_start_after_idle=0
    • TCP快速重传 - tcp_thin_dupack应为ON。它减少了发送者在重新传输丢失的段之前等待的时间。请仔细阅读并试验注意事项(可以在每个插座中指定,请在下面立即查看)。
    • tcp_thin_linear_timeouts - 这样可以更快地恢复数据包丢失,可以为每个套接字指定:https://nnc3.com/mags/LJ_1994-2014/LJ/219/11180.html
    • TFO_FASTOPEN(TFO): - 缩短初始连接建立时间。不太适用于长寿命连接,但可以考虑。
    • 压缩 - 根据我看到的信息,它不应该在您的情况下使用(不是TCP选项,可以添加在TCP之上),因为它会增加我认为您正在避免的延迟。如果它不真实,请添加此选项。
  4. 应用程序应处理的一些基础结构详细信息或协议文档可指定的内容。

    • 对于长期连接,如果它们被服务器端终止,TIME_WAIT状态将很重要。 TIME_WAIT惩罚是由开始连接终止的一方引起的,因此根据您的应用程序/协议使用情况,这可能是一个考虑因素。这取决于您将如何处理连接终止。
    • 短暂的端口 - 可能增加短暂的端口数以适应那些持久的连接将是有用的,不确定。这是您的协议的可能文档要点。
  5. 如果你的协议被调整为telnet之类的通信,你可以看到这个telnet实现。基本上它充满了异步写入和读取: 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 - 获得更多帮助。