Linux(服务器编程):百万并发服务器系统参数调优( 六 )


  • 我们只需要修改客户端的内核参数nf_conntrack_max就可以 , 可以将其修改为1048576
  • 第一步:nf_conntrack_max参数默认是不开启的 , 需要先加载下面的内核模块 , 加载完成之后其值默认为65536
sudo modprobe ip_conntrack
Linux(服务器编程):百万并发服务器系统参数调优文章插图
  • 第二步:然后在客户端的/etc/sysctl.conf配置文件中将nf_conntrack_max设置为1048576

Linux(服务器编程):百万并发服务器系统参数调优文章插图
  • 第三步:调用sysctl命令将/etc/sysctl.conf配置文件的内容更新到/proc/sys/net/nf_conntrack_max中

Linux(服务器编程):百万并发服务器系统参数调优文章插图
备注一下
  • 与第3次测试类似 , 在实际过程中也不会出现这个问题 , 因为不可能有一个客户端程序会发起上万个连接 , 因为此处我们是测试 , 所以程序要发起上万个测试 , 才修改这个参数
  • 修改完成之后进行第4次测试
六、第4次测试测试如下
  • 左侧运行服务端程序reactor(111.229.177.161:8888) , 右侧运行两个客户端程序mul_port_client_epoll去连接服务器
  • 效果如下:
    • 左侧服务端持续接收客户端的连接
    • 右侧两个客户端向服务端发起连接 , 但是当两个客户端都连接到140999个的时候 , 客户端显示无法分配地址 , 从而程序退出
    • 左侧服务端没有报错 , 只是没有客户端再连接进来了

Linux(服务器编程):百万并发服务器系统参数调优文章插图
原因分析
  • 在第2次测试中 , 我们让服务端监听在5个端口上 , 这次错误的原因可能是因为所有分配端口可用的地址都用完了
解决方案
  • 调整服务端reactor.c程序的LISTEN_PORT_COUNT宏 , 使其监听在更多的端口上 , 这样就可以承载更多的客户端 。 例如 , 此处我们将LISTEN_PORT_COUNT宏调整为50
【Linux(服务器编程):百万并发服务器系统参数调优】#define LISTEN_PORT_COUNT 50
  • 相应的 , 客户端mul_port_client_epoll.c中的MAX_PORT也要调整为50 , 因为要连接50种服务端
#define MAX_PORT 50
  • 修改完成之后进行下面第5次测试
七、第5次测试测试如下
  • 左侧运行服务端程序reactor(111.229.177.161:8888) , 右侧运行两个客户端程序mul_port_client_epoll去连接服务器
  • 效果如下:
    • 左侧服务端持续接收客户端的连接
    • 右侧两个客户端向服务端发起连接 , 每个客户端都连接二十多万的时候程序阻塞(加起来就是五十多万)
    • 左侧服务端接收到五十多万客户端的时候就阻塞了

Linux(服务器编程):百万并发服务器系统参数调优文章插图
原因分析
  • 在第1次测试的时候 , 我们将服务端程序reactor.c中的MAX_EPOLL_EVENTS设置为1024*512=524288个 , 此处可以看到刚好服务端在接收到五十多万客户端的时候阻塞 。 因此分析应该是MAX_EPOLL_EVENTS宏达到上限 , 也就是epoll_wait()处理的事件数组达到上限
解决方案
  • 增加reactor.c中的MAX_EPOLL_EVENTS , 使其可以处理的epoll事件数组变多 , 例如修改为1024*1024=1048576个
  • 因为第1次测试的时候 , 我们的MAX_EPOLL_EVENTS设置不能过大 , 如果过大程序运行时会显示内存不足 , 现在想到一个办法 , 那就是使用posix_memalign()函数来创建epoll的事件数组 , posix_memalign()函数是专门用来分配大内存的
  • 修改完成之后下面进行第6次测试
八、第6次测试
  • 下面我们不再测试了 , 也不再寻找客户端或服务端的错误 , 而是来分析一下如何使客户端更多的去连接服务端
  • 在前面的测试中 , 我们的几台机器都是在局域网内的 , 每连接1000个客户端约耗时3秒 。 如果是在局域网之外 , 那么耗时更长
一种加快连接的思路
  • 服务是调用accept()函数来接收客户端的连接的 , 因此如果想要加快客户端的连接 , 那么可以在accept()函数上下手
  • 提供的思路有:
    • 1.多个accept()放在一个线程中
    • 2.多个accept()分配在不同的线程
    • 3.多个accept()分配在不同的进程(Nginx为多进程服务器 , 它就是这样做的 , 每个进程都有自己独立的资源)