陈硕的Blog

Muduo 网络编程示例之六:限制服务器的最大并发连接数

Muduo 网络编程示例之六:限制服务器的最大并发连接数

陈硕 (giantchen_AT_gmail)

Blog.csdn.net/Solstice  t.sina.com.cn/giantchen

这是《Muduo 网络编程示例》系列的第六篇文章。

Muduo 全系列文章列表: http://blog.csdn.net/Solstice/category/779646.aspx

 

本文已以大家都熟悉的 EchoServer 介绍如何限制服务器的并发连接数。

本文的代码见 http://code.google.com/p/muduo/source/browse/trunk/examples/maxconnection/

《Muduo 网络编程示例 系列》计划中的第六篇文章原本是“用于测试两台机器的带宽的 pingpong 程序”,pingpong 协议的程序已经在《muduo 与 boost asio 吞吐量对比》和《muduo 与 libevent2 吞吐量对比》两篇文章中介绍过了,所以我改为写另外一个有点意思的主题。

这篇文章中的“并发连接数”是指一个 server program 能同时支持的客户端连接数,连接系由客户端主动发起,服务端被动接受(accept)连接。(如果要限制应用程序主动发起的连接,则问题要简单得多,毕竟主动权和决定权都在程序本身。)

为什么要限制并发连接数?

一方面,我们不希望服务程序超载,另一方面,更因为 file descriptor 是稀缺资源,如果出现 file descriptor 耗尽,很棘手(跟 “malloc 失败/new() 抛出 std::bad_alloc”差不多同样棘手)。

我在《分布式系统的工程化开发方法》一文中曾谈到 libev 作者建议的一种应对“accept()ing 时 file descriptor 耗尽”的办法。

 

幻灯片35

幻灯片36

Muduo 的 acceptor 正是这么实现的,但是,这个做法在多线程下不能保证正确,会有 race condition。(思考题:是什么 race condition?)

其实有另外一种比较简单的办法:file descriptor 是 hard limit,我们可以自己设一个稍低一点的 soft limit,如果超过 soft limit 就主动关闭新连接,这样就避免触及“file descriptor 耗尽”这种边界条件。比方说当前进程的 max file descriptor 是 1024,那么我们可以在连接数达到 1000 的时候进入“拒绝新连接”状态,这样留给我们足够的腾挪空间。

 

Muduo 中限制并发连接数


Muduo 中限制并发连接数的做法简单得出奇。以在《Muduo 网络编程示例之零:前言》中出场过的 EchoServer 为例,只需要为它增加一个 int 成员,表示当前的活动连接数。(如果是多线程程序,应该用 muduo::AtomicInt32。)

class EchoServer
{
 public:
  EchoServer(muduo::net::EventLoop* loop,
             const muduo::net::InetAddress& listenAddr,
             int maxConnections);

  void start();

 private:
  void onConnection(const muduo::net::TcpConnectionPtr& conn);

  void onMessage(const muduo::net::TcpConnectionPtr& conn,
                 muduo::net::Buffer* buf,
                 muduo::Timestamp time);

  muduo::net::EventLoop* loop_;
  muduo::net::TcpServer server_;
  int numConnected_; // should be atomic_int
  const int kMaxConnections;
};

然后,在 EchoServer::onConnection() 中判断当前活动连接数,如果超过最大允许数,则踢掉连接。

void EchoServer::onConnection(const TcpConnectionPtr& conn)
{
  LOG_INFO << "EchoServer - " << conn->peerAddress().toHostPort() << " -> "
    << conn->localAddress().toHostPort() << " is "
    << (conn->connected() ? "UP" : "DOWN");

  if (conn->connected())
  {
    ++numConnected_;
    if (numConnected_ > kMaxConnections)
    {
      conn->shutdown();
    }
  }
  else
  {
    --numConnected_;
  }
  LOG_INFO << "numConnected = " << numConnected_;
}

这种做法可以积极地防止耗尽 file descriptor。

另外,如果是有业务逻辑的服务,可以在 shutdown() 之前发送一个简单的响应,表明本服务程序的负载能力已经饱和,提示客户端尝试下一个可用的 server(当然,下一个可用的 server 地址不一定要在这个响应里给出,客户端可以自己去 name service 查询),这样方便客户端快速 failover。

 

后文将介绍如何处理空闲连接的超时:如果一个连接长时间(若干秒)没有输入数据,则踢掉此连接。办法有很多种,我用 Time Wheel 解决。

posted on 2011-04-27 00:03 陈硕 阅读(4867) 评论(9)  编辑 收藏 引用 所属分类: muduo

评论

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-27 00:52 ouyang

那对于TCP服务器来说,应该限制最大并发连接数为多少合适呢?另外,Muduo是否适合用来开发大并发(单机2万+)、短连接、小流量(整体网络流量不大)的TCP服务器?请指点。谢谢!  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-27 08:20 陈硕

@ouyang
> 限制最大并发连接数为多少合适呢?
看应用的复杂度,看多少个并发连接就把 CPU 或者 Memory 或者 IO 占满,然后设一个比它略小的上限,以保证服务质量。

> Muduo是否适合用来开发大并发(单机2万+)、短连接、小流量(整体网络流量不大)的TCP服务器?
应该可以,可能要为短连接适当优化一下 Acceptor。不过如果是短连接的话,单机并发 2万+ 是指什么?同时有 2 万个连接在线吗?那这不是长连接吗?  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-27 13:12 ouyang

比如说可能有几十万上百万个用户,每个用户都会连接到服务器在很短时间内(10秒内)做些数据交互,估计最大同时在线的并发数在几万(2-3万)左右。不考虑其他因素(出口带宽、服务器的内存大小)等的影响,光TCP服务器这块,如果采用Muduo,需要做些什么特色处理吗?谢谢!  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数[未登录] 2011-04-27 14:54 陈硕

@ouyang
按照你提供的数据,并发数 30000,每个连接存活时间 10 秒,可以计算出至少每秒钟要 accept 3000 个连接,并断开 3000 个旧连接(假设客户端主动断开连接,这样服务器不进入 time-wait 状态)。
对于服务端,每 accept 一个连接需要收两个 packet,发一个 packet。
每断开一个连接需要收两个 packet,发两个 packet。
这样一生一灭,操作系统每秒钟要处理 6~7 * 3000 = 18,000 ~ 21,000 个 packet。你确定你的服务器还有资源处理业务吗?
如果是单线程,平均每个连接的业务处理时间只有 0.3 毫秒,来得及完成任务吗?

对于 muduo,需要做的优化是修改 Acceptor::handleRead(),每次 accept N 个连接,而不是 1 个。N 的值可能是 10。
见下面这篇论文第 5.2 节: http://www.cs.uwaterloo.ca/~brecht/papers/ols-2004.pdf
  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-27 23:02 test

纸上谈兵吧
不会死循环的  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-27 23:10 陈硕

@test
这位名为“test”的网友,您测过吗?  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-27 23:43 test

写过很多类似代码。
超过ulimit maxfile的设置后,打印超出最大连接。 但不死循环  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-27 23:48 陈硕

@test
那你怎么关闭那个 pending connection ?
抑或根本不是 level-trigger reactor?  回复  更多评论   

# re: Muduo 网络编程示例之六:限制服务器的最大并发连接数 2011-04-28 00:15 test

不处理。
现在没有环境 也不好测试, 搜索了下, 有人说和不同内核版本号有关系。  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2011年4月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

随笔分类

随笔档案

相册

搜索

最新评论

阅读排行榜

评论排行榜