草庐IT

c++ - Boost::ASIO:优化以最小的流量,长连接,小消息,立即传递

coder 2023-05-31 原文

我正在Boost::ASIO中编写一个协议(protocol),该协议(protocol)具有以下要求:

  • 连接是持久的,应该使用最少的开销来“保持 Activity ”。
  • 消息很小,需要立即传递。

  • 我应该使用其他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
    

    最佳答案

    TL; DR -该协议(protocol)将处理所谓的“细流” ,如果我的回答还不够的话,它们将被很好地记录下来。最大的优势应该来自no_delay(true)async读/写(用于正常操作)以及dupACK和线性超时(用于故障恢复)。有关更多详细信息(包括静态/服务器TCP选项)和其他说明,请参见下文。

    通常,我会考虑以下因素来选择这些选项:

  • 我的用例是什么?在您的情况下,持续时间长(多长时间?),将通过该连接发送不带缓冲的小消息。需要一个很小的保持 Activity 空间。这在经典的“稀薄流” 例子中看来。
  • 最佳使用传输层协议(protocol)是什么? https://en.wikipedia.org/wiki/Transport_layer#Protocols-每个都有自己的用例。在这一点上,我认为您确实需要TCP来实现可靠性和面向连接,否则,基于udp的协议(protocol)可能会更好(例如UDP-lite,它可以在应用程序层实现部分校验和和基础的可靠性决策(或您作为开发人员将要实现的层)。
  • 选择了要构建的基础协议(protocol)-研究该协议(protocol)的调优选项 4。对于TCP,这些是:
  • Nagle的算法-数据缓冲,您已正确将其关闭。
  • 延迟的ACK-组合ACK,对于类似telnet的应用程序很有用,在这种应用程序中不必为每个传输的字符发送ACK。如果需要,则使用TCP_QUICKACK-立即发送ACK。万一您很少发送数据,它可能会很有用。
  • Keepalive探针-我看到您使用的值很短。不确定如何确定这些特定值,但可以考虑扩展它们,以保持“最小开销以保持”。Linux的默认值:7200、75、9。
  • PSH标志-有助于理解,在很大程度上未使用/忽略/不相关。
  • URG标志-将紧急数据通过单独的 channel 转发到应用程序,如果您打算接收带外数据(某些控制数据,例如取消),则很有用。在您的情况下可能没有用,因为在“精简流”的情况下,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之上添加),因为它会增加延迟,我相信您可以避免。如果此选项不正确,请添加此选项。
  • 应用程序应处理或协议(protocol)文档可以指定的一些基础结构详细信息。
  • 对于持久连接,如果它们被服务器端终止,则TIME_WAIT状态将很重要。启动连接终止的一方会受到TIME_WAIT的罚款,因此,可能要考虑根据您的应用程序/协议(protocol)的使用情况。这取决于您如何处理连接终止。
  • 临时端口-也许增加临时端口数量以容纳那些持久的连接将很有用,但不确定。这是您的协议(protocol)可能的文档要点。

  • 如果您的协议(protocol)针对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-获得其他帮助。

    关于c++ - Boost::ASIO:优化以最小的流量,长连接,小消息,立即传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48047579/

    有关c++ - Boost::ASIO:优化以最小的流量,长连接,小消息,立即传递的更多相关文章

    1. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

      我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

    2. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

      我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

    3. ruby - rails 3 redirect_to 将参数传递给命名路由 - 2

      我没有找到太多关于如何执行此操作的信息,尽管有很多关于如何使用像这样的redirect_to将参数传递给重定向的建议:action=>'something',:controller=>'something'在我的应用程序中,我在路由文件中有以下内容match'profile'=>'User#show'我的表演Action是这样的defshow@user=User.find(params[:user])@title=@user.first_nameend重定向发生在同一个用户Controller中,就像这样defregister@title="Registration"@user=Use

    4. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

      我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

    5. ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么? - 2

      我的工作要求我为某些测试自动生成电子邮件。我一直在四处寻找,但未能找到可以快速实现的合理解决方案。它需要在outlook而不是其他邮件服务器中,因为我们有一些奇怪的身份验证规则,我们需要保存草稿而不是仅仅发送邮件的选项。显然win32ole可以做到这一点,但我找不到任何相当简单的例子。 最佳答案 假设存储了Outlook凭据并且您设置为自动登录到Outlook,WIN32OLE可以很好地完成此操作:require'win32ole'outlook=WIN32OLE.new('Outlook.Application')message=

    6. Ruby - 如何将消息长度表示为 2 个二进制字节 - 2

      我正在使用Ruby,我正在与一个网络端点通信,该端点在发送消息本身之前需要格式化“header”。header中的第一个字段必须是消息长度,它被定义为网络字节顺序中的2二进制字节消息长度。比如我的消息长度是1024。如何将1024表示为二进制双字节? 最佳答案 Ruby(以及Perl和Python等)中字节整理的标准工具是pack和unpack。ruby的packisinArray.您的长度应该是两个字节长,并且按网络字节顺序排列,这听起来像是n格式说明符的工作:n|Integer|16-bitunsigned,network(bi

    7. ruby - 在 Ruby 中按名称传递函数 - 2

      如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

    8. ruby - 使用 `+=` 和 `send` 方法 - 2

      如何将send与+=一起使用?a=20;a.send"+=",10undefinedmethod`+='for20:Fixnuma=20;a+=10=>30 最佳答案 恐怕你不能。+=不是方法,而是语法糖。参见http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_expressions.html它说Incommonwithmanyotherlanguages,Rubyhasasyntacticshortcut:a=a+2maybewrittenasa+=2.你能做的最好的事情是:

    9. ruby-on-rails - 在 Flash 警报 Rails 3 中显示错误消息 - 2

      如果我在模型中设置验证消息validates:name,:presence=>{:message=>'Thenamecantbeblank.'}我如何让该消息显示在闪光警报中,这是我迄今为止尝试过的方法defcreate@message=Message.new(params[:message])if@message.valid?ContactMailer.send_mail(@message).deliverredirect_to(root_path,:notice=>"Thanksforyourmessage,Iwillbeintouchsoon")elseflash[:error]

    10. ruby - 获取数组中的值并最小化某个类属性的最优雅的方法是什么? - 2

      假设我有以下类(class):classPersondefinitialize(name,age)@name=name@age=ageenddefget_agereturn@ageendend我有一组Person对象。是否有一种简洁的、类似于Ruby的方法来获取最小(或最大)年龄的人?如何根据它对它们进行排序? 最佳答案 这样做会:people_array.min_by(&:get_age)people_array.max_by(&:get_age)people_array.sort_by(&:get_age)

    随机推荐