基于Docker容器的高并发Web系统架构设计与实现
2023-09-24欧阳习彪徐宝林
欧阳习彪,徐宝林
(广东白云学院大数据与计算机学院,广州 510450)
0 引言
高并发系统是当今互联网时代的关键技术之一。随着互联网用户数量的不断增加,社交、媒体以及电商、游戏等Web 网站用户数量越来越大,并发流量也越来越高,这对于传统Web系统架构设计提出新的挑战,如何构建高效、稳定、可扩展的系统成为了互联网企业必须面对的问题[1]。高并发系统架构作为解决这一问题的核心技术,已经成为了各大互联网企业竞争的重要因素。本文将从架构设计和技术选型及实现等方面,对高并发系统架构进行深入研究。探讨如何通过分布式架构、缓存技术、负载均衡等手段来提高系统的性能和可用性,从而为用户提供更好的服务体验。
1 Docker部署
对传统虚拟机技术下LAMP架构部署的Web应用资源消耗大、部署速度较慢等问题,使用Docker 可更快地打包、测试以及部署应用程序,过去需要用数天乃至数周的任务,在Docker 容器的处理下,只需要数秒就能完成,提供持续集成和持续部署的服务。同时Docker 容器包含了运行环境和可执行程序,可以跨平台和主机使用,也避免了开发环境、测试环境、生成环境不一致的问题[2]。在本系统中采用dockercompose 编排工具来创建容器和镜像,dockercompose.yml 配置内容如图1 所示,通过dockercompose 命令启动容器,docker images 可查看到系统共创建了php+nginx+mysql+redis 四个镜像以及docker ps-a命令可看到共创建了php+nginx+mysql+redis四个容器,如图2所示。
图2 创建的容器及镜像
2 基于Docker的系统架构设计与实现
面向高并发的Web 系统架构设计的核心思想是降低服务器端对资源调度和使用的程度,除了在程序设计应用高效的算法之外,在系统架构上可以采取分布式架构、缓存技术、负载均衡等技术来降低服务器端的数据处理性能开销[3]。系统架构设计如图3所示。
图3 系统架构
2.1 CDN内容分发
CDN 加速的原理是通过在现有的网络中增加一层网络架构,将目标网站的内容发布到最接近用户的网络“边缘”,使用户可以就近取得所需的内容,提高用户访问网站的响应速度。CDN 主要是用来缓存网站中的静态数据,如:CSS、JS、图片和静态页面等数据。用户发送请求到后端服务器,处理完动态内容后,直接从CDN中获取静态数据,从而加快响应时间[4]。
2.2 负载均衡层
在高并发系统中,需要保证系统的高可用性和负载均衡,而Keepalived LVS(linux virtual server)是一种常见的解决方案。Keepalived LVS通过将请求分发到多个服务器上,来实现负载均衡和高可用性。它使用IP 负载均衡技术将网络流量分发到多个服务器,并使用虚拟IP 地址来屏蔽后端服务器的IP 地址。当一个服务器故障时,Keepalived LVS 会将请求重新路由到其他可用服务器上,从而保证系统的高可用性。
2.3 Web应用层
2.3.1 动静分离
通过中间件将动态请求和静态请求分离,可以减少不必要的请求消耗,同时能减少请求的延时。动静分离后,即使动态服务不可用,静态资源也不会受到影响。
2.3.2 负载均衡
随着网站用户量不断增大,同一时间请求数不断提高,单台服务器已经不能满足需要,此时需要进行服务器扩容,将客户端发过来的请求分摊到其他服务器上,减少每台服务器的压力,进而提高系统的吞吐率;另外如果其中某一台服务器宕机,其他服务器还可以正常提供服务,以此来提高系统的可伸缩性与可靠性。常见的负载均衡算法有轮询、加权轮询和hash。在本游戏系统中由于三台服务器配置一样,故选用加权轮询的策略,nginx 负载均衡主要配置如图4所示。
图4 nginx负载均衡机制示意图
2.4 数据库应用层
2.4.1 分布式数据库
高并发系统中,随着业务的发展,系统用户数越来越多,单表数量达到一定量的时候,可能会导致表中索引失效,查询速度变得非常慢,同时现有的单台数据库服务器满足不了业务需求,需要进行扩容,本系统主要采用数据库分布式部署、负载均衡、分库分表、读写分离的技术来满足高并发场景下数据库服务器的高性能、高可用特性[5]。
(1)读写分离:由于业务中大多数是处理读的操作,数据库的压力主要是由这些读的请求造成的,通过数据库读写分离,能有效减少数据库的压力,提高查询响应速度。
(2)主从复制:对系统进行读写分离后,主服务器负责写入操作,从服务器负责读操作,由于读和写操作不是同一个表,会导致数据不一致的问题。因此,需要通过主从复制的方式来同步数据,保证主从服务器数据的一致。
(3)数据库负载均衡:在主从部署的数据库集群系统中,从服务器通常有几台,为了分摊系统请求压力,最大化利用每台从服务器,本系统中采用Haproxy+Keepalived 负载均衡技术,通过Haproxy 实现负载均衡,Keepalived 确保即使主服务器宕机,从服务器仍旧可以作为主服务器使用,保证系统的高可用性。
(4)分库分表:在高并发数据量大的系统中,频繁的IO 操作成了数据库的性能瓶颈,最终都会导致数据库的活跃连接数增加,进而逼近甚至达到数据库可承载活跃连接数的阈值,使得可用数据库连接少甚至无连接可用。通过分库分表,将数据分散存储,使得单一数据库/表的数据量变小来缓解单一数据库的性能问题。在本游戏系统中,用户千万级,游戏记录表数据每日新增量非常大,单表已不能满足需要,故采用范围分表的方式,共分为20 个子表,每个子表存放500000 条记录,根据用户ID 对单表最大记录数500000 取商,再加1,以此确定当前用户游戏数据对应保存的子表序号,具体实现代码如下:
2.4.2 数据缓存redis
当表的记录变得非常庞大时,索引失效,查询速度将变得非常慢,影响网站的性能,这种情况下可以将数据缓存起来,每次访问数据的时候先从缓存中读取,如果缓存中没有需要的数据,才去数据库中查找。这样可以极大降低数据库的负载压力,也有效提高了获取数据的速度。常用的缓存技术有redis 和memcache,由于redis 拥有丰富的数据类型,支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。系统中用redis作为缓存数据库,该游戏系统中用户量大、并发高,同一时刻需要更新玩家数据的量非常大,如果直接操作数据库将导致数据库无法承受压力而崩溃,此时可以选用redis 的hash 数据类型,以用户id 作为键,玩家游戏数据作为值,同时将有数据变换的玩家id存放到redis集合中。然后通过定时任务,从redis 集合中获取所有玩家有数据变化的玩家id,并依次取出数据内容插入数据库中,具体实现代码如下:
由于redis 是纯内存操作,内存空间有限,在高并发系统中一台redis 服务器并不能满足系统高可用的要求,本游戏系统中采用一主二从的架构,通过主从复制实现了数据的热备份,当主服务器宕机时,从服务器可以充当主服务器进行使用,同时在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务,分担服务器负载;尤其是在写多读少的情况下,通过多个从节点分担读负载,可以大大提高redis服务器的并发量。
3 结语
对于大流量、高并发系统,任何一个环节到达性能瓶颈都可能导致系统宕机崩溃,进行在进行系统架构设计时,每一层都需要考虑系统的可用性、扩展性、安全性,等等。本文从接入层、应用层、数据存储层三个方面进行了探讨,利用DNS 加速、负载均衡、redis 主从、MySQL 主从复制、MySQL 读写分离等技术实现了系统高并发、高性能、高可用的特性。