Modnar's Zone

聊天室服务器设计与实现

字数统计: 1.5k阅读时长: 5 min
2020/04/20

问题来源

        事实上,这是我的“腾讯一面”面试官(下文简称 leader,手动滑稽)在一面结束时留给我的作业。由于我大学期间的 Linux 功底比较表面(这是我发自内心的自我评价),所以对一些技术没有很好的深入理解与实践经历。

        当时我的 leader 推荐给我一本书,希望我能通过这本书学习一下 Linux 服务器编程的一些知识,并实现一个如题的聊天室服务器,具体要求重点在于并发压力可以至少支持10个用户同时在线聊天,此外可以针对性地添加一些必要功能,比如支持查询用户历史消息。

        leader 给我预约的二面时间是十天之后,当然如果提前完成了这个作业,可以提前与他联系,他会 check 一下我的作业结果,以便将二面时间稍稍提前。所以,拿到了这个作业,是真的投入很多精力去学习。现在看来,可能作业内容并不复杂,逻辑也很清晰,但这可能对于经验不多的我来说,算是一个编程实践挑战。

实现过程

        通过对《Linux高性能服务器编程》这本书的阅读理解,找到了实现的方式:通过采用 IO 复用技术以实现对 socket 通信文件描述符的监听,从而实现高性能的并发。

        起初,我的实现思路是服务器端采用一个主线程进行监听用户连接请求,每当用户发来一个连接,即服务器端有一个事件发生,就创建一个新的线程来进行处理。后来,在和 leader 交流的过程中,明确了各种并发技术的适用场景,多进程 / 线程往往适用于需要一定量 IO 处理,这种场景下可以采用这样的处理模式;而对于聊天室这样的简单处理流程,直接采用 IO 复用就可以很好地进行处理。

        关于“IO 复用”,不得不说的就是 Linux 2.6 之后提供的 epoll 函数,以及 selectpoll 函数,后两者在很多场景下往往表现不如 epoll 更好,下面简单说一下我对这三者的理解:

概述

        首先,三者都是用于监听文件描述符的系统调用,区别在于三者的逻辑以及表现不同,进而决定了三者的应用场景不同。

select

        select 函数更多地像是直接轮询操作系统,对于用户事先注册的一组文件描述符,逐个向操作系统询问,并在轮询完毕后,将准备就绪的文件数作为返回值返回。

        因而可知,这种方式的时间复杂度为 O(n),也就是注册文件描述符的规模。因而这个函数往往适用于待监听的文件个数不多的情况。此外,select 实际上是有监听文件个数上限的,这也是在实际应用中需要注意的问题。

poll

        poll 函数引入了 event 这个类型(一种系统定义的结构体),在 poll 中,对于发生的事件(即监听的文件描述符上有读写事件),会对注册的事件表进行修改,然后返回准备就绪的文件描述符个数。然而实际上,poll 的实现还是采用了轮询的方式,因而本质上来说时间复杂度依旧是 O(n) 级别的。但是相比 select 来说,poll 支持监听的文件个数极大增加了。尽管如此,其应用场景往往和 select 相似。

epoll

        epoll 函数则在 event 的基础上,进一步进行优化。使得函数在调用时,可以直接返回准备就绪的文件描述符,其时间复杂度是 O(1) 的。因而对于大规模的待监听的文件描述符来说,使用 epoll 系统调用可以很快地得到准备就绪的文件描述符,其效率较前二者有极大的提升。然而,并不是任何场景都适合直接使用 epoll,比如待监听的文件个数较少,这种场景往往采用前二者即可,这是因为 epoll 的内部采用了大量的系统调用,因而此时往往会因为函数调用使得效率较低。

        此外,由于上述内容均是系统级调用,因而在细节上会有一些差异。此外,上述的 epoll 是 Linux 所独有的 IO 复用系统调用,所以 Mac 并不支持。但 Mac 下可以使用 Unix 提供的 kqueue,其用法以及效果与 epoll 十分相似,这里不展开叙述。

        在做这个作业的过程中,重点就放在了 IO 复用这一块,此外,对于如何管理用户历史数据、如何在 server 仅保存最近的 N 条历史消息数据。有兴趣的读者可以看一下我在 GitHub 上提交的 作业代码

题外话

        实际上,鹅厂一直是我大学期间最向往的公司,因为鹅厂内的员工,往往更有一种书生气,这种氛围更适合自身去成长发展。所以,拿到这个作业之后,是非常想要表现一下自己的,因此把 leader 推荐的这本书,前后读了三遍左右。当然,可能阅读过程没能做到面面俱到,更多地是有针对性地阅读理解,因为这是比较贴切我自身的“学习方法”。终于,我靠着自己的计算机功底以及学习能力,拿到了腾讯 2020-IEG 春季校园招聘的 offer,这段经历,也成了我 2020 年的一段激动人心的回忆。

CATALOG
  1. 1. 问题来源
  2. 2. 实现过程
    1. 2.1. 概述
    2. 2.2. select
    3. 2.3. poll
    4. 2.4. epoll
  3. 3. 题外话