高性能服务器C10K到C1000K到C10M的转变路程

大耗子 2020年06月26日 154次浏览

文章链接:https://codemouse.online/archives/2020-06-26-17-51-36

网络五元组

五元组标识一个网络fd的唯一
网络fd --> 五元组(sip,dip,sport,dport,proto)

c1000k服务器的并发量条件(百万并发)

  1. 服务器能够承载的客户端数量。(最基本条件)
  2. 5w以上的应供应操作。(也就是客户端的5%)
  3. 对数据库的操作。
  4. 磁盘的操作。(日志,文件。。)
  5. CPU占用率60%。(留下40%用来应付突发情况)
  6. 内存占用率80%。

系统限制并发的地方

  1. open_files 的值,这个值代表了一个进程可以打开的文件的数量。当然这个值不能超过file-max,超出file-max的部分是无效的。
# 方法一:重启后无效
ulimit -HSn 1048576 
# 方法二:重启后依旧生效
# 将方法一内容写到/etc/profile中,因为每次登录终端时,都会自动行/etc/profile

# 方法三:重启后生效
vim /etc/security/limits.conf  
* soft nofile 1048576 
* hard nofile 1048576 
  1. fs.file-max的值,这个值代表了所有进程一共可以打开的文件数量。一些程序可以通过setrlimit调用,设置每个进程的限制。这项参数是系统级别的。
# 方法一:重启后无效
echo  1048576 >> /proc/sys/fs/file-max  
# 方法二:重启后无效
sysctl -w "fs.file-max=1048576"
# 方法三:重启后生效
vim /etc/sysctl.conf
fs.file-max = 1048576 

ulimit命令

-H 使用硬资源控制
-S 使用软资源控制
-a 查看所有的当前限制
-n 能打开的最大文件描述符数
-t 限制最大的 CPU 占用时间(每秒)
-u 限制最大用户进程数
-v 限制虚拟内存大小(kB)
例子:
#硬资源和软资源同时限制为最大打开文件描述符数65546
ulimit -HSn 1048576 
#将虚拟内存限制改为无限制
ulimit -v ulimited  

reactor的核心

  • reactor将网络IO转化为了事件。
    因为每一个网络IO在某一时刻只有一个事件,所以网络IO等同于了事件。

客户端发起连接只能发起6w多个连接的原因

执行sudo sysctl -p 查看
看net.nf_conntrack_max的值,这个值默认65535,限制了发起数量
系统默认不加载的,需要加载一下,因为客户端发起超大量请求才会出现这个问题。

# 开启:
sudo modprobe ip_conntrack
# 方法一:重启后无效
echo  1048576 >> /proc/sys/net/nf_conntrack_max
# 方法二:重启后无效
sysctl -w "net.nf_conntrack_max=1048576"
# 方法三:重启后生效
vim /etc/sysctl.conf
net.nf_conntrack_max = 1048576 

单个客户端可发起连接数已经修改,还是连上不去的原因

报错:cannot assign requested address
解决方式:

  • 如果单个客户机子往服务器发送超过最大端口个链接,只能让服务器多开端口,否则无解,因为他需要五元组进行fd标识。
  • 由于源ip和目的ip固定,源端口最大数量也固定,那么能改变的也只有目的端口了,所以服务器多开端口可以解决同一个机子发起大量链接的问题。
  • 网络五元组(sip,dip,sport,dport,proto)

如何把客户端链接的耗时变短???

限制原因:服务器的accept的限制,一个accept可处理的事件太少太慢。
解决办法:增加accept。

多个accept如何配合多个线程或者进程

配合方式:

  1. 多个accept放在一个线程。(无法解决问题)
  2. 多个accept分配在不同的线程。
  3. 多个accept分配在不同的进程(nginx的做法)

多线程与多进程的区别???

  1. 多进程不需要加锁。
  2. fd的上限比多线程多。(参考fs.file-max的定义)

在c10k的时候,当时无法突破到c100K的限制在哪??

当时没有epoll这种获取监听事件机制,用的是select/poll等轮询机制

为什么select/poll等机制慢?

select每次去监听等待的时候,需要把用户的fd集合复制到内核中,并且是以遍历的方式带出来给应用程序。

为什么epoll快??

这个方式不在需要每次都将用户的fd集合复制一份到内核,而是将要用到的IO通过epoll_ctl的方式加入到内核里面,内核里面有一颗红黑树存储这些IO,一旦某个结点活跃有数据,就将结点通过链表的方式连接成一个队列(注意:加入队列但并没有移出红黑树)。而epoll_wait所做的事情,就说将就绪队列从内核中复制出来。此时就只需要复制有数据的结点,且不需要拷贝大量数据到内核,所以快。

想从C1000K提升到C10M要怎么办??

在数据到应用程序的过程中,要经过网卡->协议栈->应用。这时候可以选择将协议栈放弃,直接应用与网卡进行交互,减少了协议栈这一层,提升速度。
用mmap将网卡映射到内存中,应用与网卡交互,也就是所谓的用户协议栈的方式。
网络协议栈

影响服务器的性能的五元组

  1. CPU
  2. 内存
  3. 网络带宽
  4. 操作系统
  5. 应用程序

测试代码

测试代码下载请点击