当前位置:   article > 正文

限制并发连接数_如何测试运营商是否做了连接数限制

如何测试运营商是否做了连接数限制
  1. 不希望服务程序超载
  2. file descriptor 是稀缺资源, fd 耗尽是一件麻烦事

若accpet(2) 返回 EMFILE 该如何应对?这意味着本进程的文件描述符已经到达上限,无法为新连接创建 socket 文件描述符。但是,既然没有 socket 文件描述符来表示这个连接,我们就无法 close(2)它。程序继续运行,回到epoll_wait处 。这时 epoll_wait 会马上返回,因为新连接还在等待处理,listening fd 还是可读的。这样程序就陷入了 busy loop,CPU 占用率接近 100%,这既影响同一 eventloop 上的连接,也影响同一机器上的其他服务。

陈硕的 《linux多线程服务端编程》中提到了以下几种做法:

  1. 调高进程的文件描述符数目。治标不治本
  2. 死等。鸵鸟算法
  3. 退出程序。不可取
  4. 关闭 listenning fd. 那么什么时候再打开呢?
  5. 改用 edge trigger。如果漏掉一次 accept(2),程序再也不会接受新连接(这会出现客户端无响应的情况)
  6. 准备一个空闲的文件描述符。
    准备一个空闲的文件描述符。遇到这种情况,先关闭这个空闲文件,获得一个文件描述符地名额;再accept(2)拿到新socket 连接的描述符;随后立刻close(2)它,这样就优雅地断开了客户端连接;最后重新打开一个空闲文件,把"坑"占住,以备再次出现这种情况时使用
  7. 自己设置一个低一点的soft limit.

muduo网络库中使用的是,第6种,代码如下:

void Acceptor::handleRead()
{
  loop_->assertInLoopThread();
  InetAddress peerAddr;
  //FIXME loop until no more
  int connfd = acceptSocket_.accept(&peerAddr);
  if (connfd >= 0)
  {
    // string hostport = peerAddr.toIpPort();
    // LOG_TRACE << "Accepts of " << hostport;
    if (newConnectionCallback_)
    {
      newConnectionCallback_(connfd, peerAddr);
    }
    else
    {
      sockets::close(connfd);
    }
  }
  else
  {
    LOG_SYSERR << "in Acceptor::handleRead";
    // Read the section named "The special problem of
    // accept()ing when you can't" in libev's doc.
    // By Marc Lehmann, author of libev.
    if (errno == EMFILE)
    {
      // 描述符用尽
      ::close(idleFd_);
      idleFd_ = ::accept(acceptSocket_.fd(), NULL, NULL);
      ::close(idleFd_);
      // 再次打开占位
      idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC);
    }
  }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/229995
推荐阅读
相关标签
  

闽ICP备14008679号