随着移动互联网的快速普及,越来越多的人进入网络直播行业。在看到网络直播市场的潜力后,各大门户网站开始发力,投入巨资建设。
直播需要使用尽可能少的服务器来承载尽可能多的用户,以节省企业成本。根据直播的应用场景,探讨高并发网络编程技术,研究高并发网络模型和软件架构,理清各I/O类型的能力、局限和区别,分析多进程模型的优点和限制,实现了高并发实时直播系统并应用到企业生产运营中去,为企业节省服务器成本和运维人力。
一、操作系统与网络架构选型
Linux是一套可以自由传播和免费使用的类Unix操作系统,被大多数IT企业广泛使用。它是一种基于POSIX和UNIX的多用户多任务、多线程、多CPU的操作系统,具有稳定可靠、功能强大、安全、价格低廉及开源等优点。
Linux为TCP/IP参考模型提供了良好支持,该模型分为4层:链路层、网络层、传输层和应用层。
链路层处理与电缆的物理接口细节;网络层处理网络中数据包的活动,例如数据包路由;传输层为二台主机中的应用提供端到端通信;应用层负责处理特定应用程序细节。
直播系统是在Linux操作系统下基于TCP/IP参考模型实现的,并使用套接字进行相关编程。套接字是介于应用层和传输层之间的抽象层,它将TCP/IP层的复杂操作抽象为几个简单的接口供调用,实现网络进程通信。
二、I/O模型选择
I/O模型大体划分为阻塞式I/O、非阻塞式I/O、I/O复用、异步I/O和信号驱动I/O。
1、阻塞式I/O
应用程序调用I/O函数,导致应用程序阻塞并等待数据准备就绪。如果数据没有准备好,程序会等待,当数据准备好并从内核复制到用户空间时,IO函数返回一个成功指示。使用阻塞模式的Socket,网络程序的开发相对简单,易于实现。但是,当要同时处理大量套接字时,就无法适用,扩展性很差,不适合直接应用于高并发的程序开发。
2、非阻塞式I/O
当进程将套接字设置为非阻塞时,它会通知内核,当请求的I/O操作必须使进程休眠才能完成时,不要让进程休眠,而是返回错误。非阻塞模式可以避免程序死锁,但应用程序不断轮询内核来检查I/O操作是否准备就绪是一种极其浪费CPU资源的操作,因此很少在实际应用中使用,通常是在专门提供某种功能的系统中使用。
3、I/O复用
主要是SELECT/POLL和EPOLL,它们可以同时阻塞多个I/O操作,并且可以同时检测多个读取和写入操作,直到有数据要读或写,才真正调用I/O操作函数。EPOLL是Linux独特的I/O多路复用函数,是SELECT/POLL的增强版本,内核对其进行了改进。
当大量并发连接中只有少量活动时,可以显著提高系统的CPU利用率。在获取事件时,不必遍历整个被侦听的描述符集,只需遍历由内核IO事件异步唤醒并添加到就绪队列的描述符集。EPOLL具有以下优点:支持一个进程打开大量目的套接字描述符;使用mmap加速用户空间和内核之间的消息传递;IO效率不会随着FD数量的增加而线性下降。
水平触发是默认的工作模式,在这种模式下,内核告诉进程文件描述符是否就绪,然后进程可以对就绪的FD进行IO操作。如果进程不执行任何操作,内核将继续通知。此模式比较成熟稳定,传统的SELECT/POLL就是这种模式的代表。边缘触发是一种高速工作模式,在该模式下,当描述符从未就绪变成就绪时,内核通过EPOLL通知进程。
然后,它假设该进程知道文件描述符已准备好,并且不会再发送该文件描述符的任何就绪通知,直到该进程执行某些操作使该文件描述符不再是就绪为止。结合EPOLL的特点,服务器采用EPOLL模型,并采用水平触发方式。其他模型在文中不作探讨。
三、系统架构设计与实现
总体架构图如图1所示。
1、多进程模型
进程是具有一定独立功能的程序关于某数据集的单次运行活动,是操作系统动态执行的基本单元。在编写高并发程序时,通常使用两种模型:多进程单线程模型(简称多进程)和单进程多线程模型(简称多线程)。与多线程相比,多进程编程相对简单,不必考虑锁和同步资源等问题,容错能力更强,后期维护也相对简单。
结合聊天服务程序使用EPOLL管理连接的特点,采用多进程模型来实现系统。Linux对单个进程可以打开的文件描述符有数量限制,使用ulimit-a命令查看,通常是1024个,这远远不够。但可以使用ulimit-n进行临时更改(永久生效需进行系统设置),比如100000,这样单个进程就可以连接到九万多个用户。
2、Socket长连接
TCP提供面向连接的可靠字节流服务。两个使用TCP的应用必须先建立TCP连接,然后客户端才能连续向服务器发送请求,如发送聊天消息、给主播送礼物、点歌等。服务器将执行一系列复杂的处理操作,并在处理完成后响应客户端。此过程花费的时间如不考虑网络延迟可达到微秒级。创建TCP连接需要客户端和服务器进行3次握手,而断开连接需要4次握手。
在Linux操作系统中,通过套接字编程,可以在客户端和服务器之间建立TCP长连接。套接字是介于应用层和传输层之间的抽象层。它将TCP/IP层的复杂操作抽象为几个简单的接口提供应用层调用来实现网络通信。在这里,服务器端进程可以接受九万多个客户端(如3.1所述)进行连接,并且基于EPOLL建立和维护这些连接所需的开销很小。
3、敏感词过滤技术
根据实际情况,运营人员收集了一份敏感词列表,列出一批不能出现的敏感词,而具体的过滤需要由服务器程序来执行。过滤聊天内容会大大降低程序的执行效率,这是造成服务器程序性能瓶颈的主要因素,需要高效的算法加以避免。可以使用散列算法、树形算法和中文分词技术,这些算法的具体实现比较复杂。主要采用散列算法,实现代码用纯C语言编写,内存占用很小,过滤速度很快。
4、分布式高性能数据存取技术
NoSQL数据库是一种非关系型高速访问数据库,技术成熟稳定。与传统关系数据库相比它具有扩展简单、读写速度快、部署灵活和成本低等优点。主流的NoSQL数据库有ongoDB、Bigtable、HBase及Redis等。
Redis具有复制特性和为解决问题而生的数据模型,它提供了5种不同类型的数据结构:string、list、set、zset和hash,可以将各种问题映射到这些结构。它们支持push/pop、dd/remove、交集并集和差集及更丰富的原子操作。结合直播系统的特点,选择REDIS作为系统的数据库,服务器与REDIS之间也通过长连接进行通信。
5、用户行为限制
系统安全性是服务器程序必须考虑的问题,应该从系统设计之初就开始考虑。常见的限制有两个:
(1)需要限制同一个IP的最大连接数,避免同一用户打开多个浏览器窗;
(2)需要限制同一用户每秒可以发言的次数,避免用户使用一些脚本工具进行刷屏聊,这不仅会让服务器承受额外的负担,还会破坏正常的聊天环境。
高并发网络服务器技术将其应用于主播直播系统。直播系统的设计目标围绕高并发的要点展开,通过确定操作系统、网络模型,进一步分解和细化了相关实现技术,采用多进程、epoll、哈希算法和NoSQL数据库等技术进行具体的实现,这些技术为高并发实现提供了可靠的保证。