侧边栏壁纸
  • 累计撰写 244 篇文章
  • 累计创建 16 个标签
  • 累计收到 0 条评论
隐藏侧边栏

服务器如何提高并发量

kaixindeken
2021-04-20 / 0 评论 / 0 点赞 / 83 阅读 / 1,243 字

我们以 Web 请求为例,介绍如何让服务器同时处理更多请求,提高并发量。Web 请求一般都是 HTTP 请求,而 HTTP 协议又是基于 TCP 的,所以,我们主要探讨如何让服务器同时处理更多 TCP 连接请求。

服务器通常固定在某个本地端口上监听,等待客户端的连接请求。服务器端 TCP 连接四元组中只有对端 IP 和对端端口(即客户端IP和端口)是可变的,因此,最大 TCP 连接数 = 客户端 IP 数 × 客户端端口数。对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。

当然,服务端最大并发 TCP 连接数远不能达到理论上限。首先主要是文件描述符限制,按照前面介绍的原理,Socket 都是文件,所以首先要通过 ulimit 配置文件描述符的数目;另一个限制是内存,按上面的数据结构,每个 TCP 连接都要占用一定内存,操作系统是有限的。

为了尽可能多的让服务器提供更多连接,处理更多请求,通常有以下几种解决方案:

1、多进程

当有新的请求进来,fork出一个子进程,让子进程处理该请求,提高并发量。

2、多线程

进程开销太大,线程则轻量级的多,所以我们还可以通过在进程中创建新的线程来处理请求。

上面基于进程或线程的模型还是有问题,因为每新进来一个 TCP 连接请求,就需要分配一个进程或线程,从而引发著名的 C10K 问题(一台机器要维护 1 万个连接,就要创建 1 万个进程或者线程,操作系统是无法承受的。如果维持 1 亿用户在线需要 10 万台服务器,成本也太高了),为此,又诞生了一种新的技术 —— 多路 IO 复用。

3、多路IO复用

所谓多路 IO 复用可以简单理解为一个线程维护多个 Socket(前面多进程或多线程都是一个进程或线程维护一个 Socket),这也有两种实现方式:轮询和事件通知。

因为 Socket 在 Linux 系统中以文件描述符形式存在,所以我们把一个线程维护的所有 Socket 叫做文件描述符集合,所谓轮询就是调用内核的 select 函数监听文件描述符集合是否有变化,一旦有变化,就会依次查看每个文件描述符,对那些发生变化的文件描述符进行读写操作,然后再调用 select 函数监听下一轮的变化。

显然,轮询的效率有点低,因为每次文件描述符集合有变化,都要将全部 Socket 轮询一遍,这大大影响了系统能够支撑的最大连接数。如果改成事件通知的方式,情况要好很多。所谓事件通知,就是某个文件描述符发生变化,调用 epoll 函数主动通知。这种方式使得监听的 Socket 数据增加的时候,效率不会大幅度降低,能够同时监听的 Socket 的数目也非常多。上限就为系统定义的、进程打开的最大文件描述符个数。

因此,epoll 被称为解决 C10K 问题的利器。

0

评论区