一种大并发量请求的处理方法及处理系统
本发明专利申请是申请日为2012年6月29日、申请号为201210225752.9、名称为“一种大并发量请求的处理方法及处理系统”的中国发明专利申请的分案申请。
技术领域
本发明涉及计算机网络领域,具体涉及一种提高网络服务器在处理大并发请求时的处理能力的方法及处理系统。
背景技术
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库,随着信息技术和市场的发展,数据管理不再仅仅是存储和管理数据,而转变成用户所需要的各种数据管理的方式。数据库有很多种类型,从最简单的存储有各种数据的表格到能够进行海量数据存储的大型数据库系统都在各个方面得到了广泛的应用。
Redis(Remote Dictionary Server)是一种key-value的消息存储系统。Redis提供了一些丰富的数据结构,包括string,list,sets,ordered sets以及hashes。Redis性能极高,能支持超过100K+每秒的读写频率。并且Redis所有的操作都是原子性的,同时Redis还支持对几个操作合并后的原子性执行。Redis提供各种语言的客户端支持,包括php、c等。Redis存储的数据放在内存中使用,因此读写性能比mysql等数据库高很多。Nginx是一款通用、开源、高效的HTTP服务器。Nginx现在市场份额占有12.18%,Nginx最为显著的特色是它的高性能、稳定性和丰富的第三方模块,Nginx对于高并发性有很好的表现,它可以同时容纳约100万的连接数。因此对于有高并发的系统需求来说,Nginx+Redis的结合是一个很好的选择。
轮询结构由于需要对服务器进行不断和持续的请求,所以对服务器的请求压力很大。现有技术中一般使用Redis+php+Nginx作为请求轮询的结构,Redis提供了各种客户端C、C++、PHP和JAVA等。Nginx以php作为服务端脚本语言,php和Nginx的连接是使用php-fpm,而php-fpm是单线程工作方式,因此在Nginx中,一个php-fpm进程只能处理一个请求,但是单台服务器开启1000+的php-fpm,最乐观情况下也只能有1万请求/秒的性能表现,对于再多的php-fpm请求,Nginx只能延迟处理和响应,这样不但花费的时间长效率低,而且导致了Nginx和Redis这两个在高并发下表现很好的产品的性能浪费过多。
此外现有技术中也有单独使用Webdis+Redis来实现轮询的,Webdis可以接受一些参数来对Redis进行操作,但是Webdis的参数功能缺少变化,不能实现一些特定的转化和判定功能(比如权限判定),因此Webdis也不能直接完成某些用户的要求。
现有技术中,上述结构在利用消息系统向用户发送一个消息的时候,常规的做法就是对所有的用户都发送一个消息,此时登录的用户会收到消息,而未登录的用户只有在下次登录的时候才会收到消息,对于未接收的消息只能存储在数据库中,等待用户进行轮询,因此这样的作法是非常消耗资源的,而且是不必要的。
发明内容
为解决现有技术中服务器处理高并发请求效率低下,而导致服务器和数据库性能不能完全发挥的问题,本发明提供一种大并发量请求的处理方法,其特征在于,访问步骤如下:
步骤1、服务器批量接收客户端发送的HTTP请求,然后将HTTP请求直接进行反向代理后转送到HTTP代理;
步骤2、HTTP代理接收到HTTP请求后转换成数据库语言后再发送到数据库;
步骤3、数据库在各客户端与其请求的数据之间建立对应关系,再根据HTTP请求按对应关系将相关数据返回给HTTP代理;
步骤4、HTTP代理对接收到的数据进行反向转换后再返回给服务器;
步骤5、服务器接到HTTP代理返回的数据后再转化为轻量级数据交换格式返回给相应的客户端。
优选的:所述步骤1中,服务器对接收的HTTP请求负载均衡到不同的HTTP代理上。
优选的:所述步骤2和步骤4中,HTTP代理是根据预定义的HTTP URL语义对HTTP请求和数据库语言进行相互转化的。
优选的:所述步骤3中,数据库在各客户端与其请求的数据之间建立对应关系的步骤如下:
步骤41、设置记录注册用户信息的用户队列;
步骤42、配置由待分发消息构成的消息队列,对待分发消息根据其不同优先级设定不同的权重后加入到消息队列中;
步骤43、建立用户队列内的用户和消息队列内的待分发消息之间的映射关系;
步骤44、接收HTTP代理转送的已经转化为数据库语言的HTTP请求,根据所述映射关系查找对应所述登录用户的待分发消息;
步骤45、从查找到的待分发消息中将权重最高的待分发消息发送给HTTP代理。
优选的:所述步骤42中设定不同的权重是通过在数据库中创建的类函数实现的。
优选的:所述类函数包括了两个公开函数和一个私有函数;所述公开函数实现获取消息队列中权重最小的元素或权重最大的元素;所述私有函数用于保证公开函数调用的自身原子性。
优选的:所述步骤43中的映射关系是依据用户ID与待分发消息的Value值相对应建立,并将所述映射关系保存到数据库中。
优选的:对用户已经接收过的待分发消息,将其Value由该用户的映射关系中删除。
优选的:所述步骤45中,待分发消息仅发送给用户队列中的登录用户。
优选的:服务器随时将新登录的用户ID加入到用户队列中,随时将新的待分发消息加上权重后加入到消息队列中,并随时将新的待分发消息与用户队列中的用户ID建立映射关系。
一种大并发量请求的处理系统,其特征在于,包括
服务器,适于批量接收客户端发送的HTTP请求,然后将HTTP请求直接进行反向代理后转送到HTTP代理;
HTTP代理,适于接收到HTTP请求后转换成数据库语言再发送到数据库,同时对接收到的数据库数据进行反向转换后再返回给服务器;
数据库,适于在各客户端与其请求的数据之间建立对应关系,再根据HTTP请求按对应关系将相关数据返回给HTTP代理;
服务器:还适于接到HTTP代理返回的数据后再转化为轻量级数据交换格式数据返回给相应的客户端。
优选的:所述服务器进一步包括将接收的HTTP请求负载均衡到不同的HTTP代理上。
优选的:所述HTTP代理是根据预定义的HTTP URL语义对HTTP请求和数据库语言进行相互转化的。
优选的:所述数据库进一步包括如下模块:
用户队列模块,设置记录注册用户信息的用户队列;
消息队列模块,配置由待分发消息构成的消息队列,对待分发消息根据其不同优先级设定不同的权重后加入到消息队列中;
映射模块,建立用户队列内的用户和消息队列内的待分发消息之间的映射关系;
查询模块,接收登录用户的请求消息,根据映射模块中的对应关系查找对应的待分发消息;
发送模块,从查找到的待分发消息中将权重最高的待分发消息发送给HTTP代理。
优选的:所述消息队列模块中设定不同的权重是通过在数据库中创建的类函数实现的。
优选的:所述类函数包括了两个公开函数和一个私有函数;所述公开函数实现获取消息队列中权重最小的元素或权重最大的元素;所述私有函数用于保证公开函数调用的自身原子性。
优选的:所述映射模块中的映射关系是依据用户ID与待分发消息的Value值相对应建立,并将所述映射关系保存到数据库中。
优选的:所述消息队列模块中,对用户已经接收过的待分发消息,将其Value由该用户的映射关系中删除。
优选的:所述查询模块中,待分发消息仅发送给用户队列中的登录用户。
优选的:用户队列模块随时将新登录的用户ID加入到用户队列中,消息队列模块随时将新的待分发消息加上权重后加入到消息队列中,映射模块随时将新的待分发消息与用户队列中的用户ID建立映射关系。
本发明利用HTTP代理调用数据库命令实现一种高效的消息分发机制,在消息分发机制中,将消息接收用户区分为登录用户和非登录用户,以在线用户的数量作为消息分发对象,取消了未登录用户的消息分发,大大减少了分发量。本发明利用权重的大小来区分不同优先级的消息,在取出待分发消息时,能够根据权重的大小优先取出重要消息,实现了消息的优先分发。本发明在登录用户与需分发消息之间建立相互映射关系,由登录用户的客户端轮询时获取相应消息,减少了服务器的负担。本方案的消息分发机制使单台服务器能保证每秒超过几万的消息分发量,对拥有大量登录用户的消息推送系统需求的产品来说能提供较为稳定的消息推送服务。
附图说明
图1本发明中客户端与服务器之间的请求处理流程图。
图2本发明中服务器处理大并发请求的流程图。
图3本发明中处理系统中模块工作流程图。
图4本发明中消息推送与客户端之间的优化步骤流程图。
图5本发明中消息推送与客户端登录用户之间的优化过程示意框图。
具体实施方式
如图1所示,本发明中服务器仅作为HTTP请求的转送者,具体处理过程交给Webdis代理进行处理,Webdis代理将服务器转发的HTTP请求转化成数据库语言,同时对数据库回传的数据进行反向转换,再发送给服务器,这样服务器在减轻自身处理量的情况下,还利用Webdis代理代替了PHP的单线程工作方式,提高了服务器处理客户端轮询请求的处理速度,本发明通过Nginx服务器和Redis数据库的组合操作,使得原本没有权重队列操作的Redis数据库有了这个功能,在消息队列方面,本发明改进点着重于消息的取出,而在用户队列方面,本发明利用登录用户和未登录用户的划分来减少同时接收消息的用户群,利用PHP和Redis数据库的函数在消息队列和用户队列之间建立映射关系,从而建立一套快速且能够实现消息优先级分发的消息分发机制。如图2所示,具体步骤如下:
101、服务器批量接收客户端发送的HTTP请求,然后将HTTP请求直接进行反向代理后转送到HTTP代理;
其中服务器对接收的HTTP请求负载均衡到不同的HTTP代理上。
102、HTTP代理接收到HTTP请求后转换成数据库语言后再发送到数据库;
HTTP代理是根据预定义的HTTP URL语义对HTTP请求和数据库语言进行相互转化的。这里Nginx服务器与Webdis代理之间是内部请求,因此网络延迟消耗可以忽略。
服务器为每个Redis数据库配置一个Webdis代理,其中Nginx服务器、Redis数据库和Webdis代理的组合在Nginx服务器的配置文件中包括如下步骤:
(1)、将所有客户端的msg/sort的请求配置进入location/msg/sort中;
(2)、将每个请求转化为Webdis代理的的http请求格式;
(3)、使用反向代理将请求传送到Webdis代理_ccc_01上;
(4)、配置Webdis代理的服务器地址和端口号。
103、数据库在各客户端与其请求的数据之间建立对应关系,再根据HTTP请求按对应关系将相关数据返回给HTTP代理;
104、HTTP代理对接收到的数据库数据进行反向转换后再返回给服务器;
105、服务器接到HTTP代理返回的数据后再转化为轻量级数据交换格式返回给相应的客户端。
如图4所示,其中103中,数据库在各客户端与其请求的数据之间建立对应关系的步骤如下:
401、设置记录注册用户信息的用户队列;
新用户登录客户端后,客户端发送HTTP请求usr/login告知Nginx服务器该用户已经登录,Nginx服务器在Redis数据库上建立一个由注册用户构成的用户队列,用户队列随时记录新登录的用户,Nginx服务器利用PHP调用Redis数据库自带的rPush命令将新登录用户插入用户队列。
402、配置由待分发消息构成的消息队列,对待分发消息根据其不同优先级设定不同的权重后加入到消息队列中;
PHP利用Redis数据库的zAdd命令进行有权重的由待分发消息构成的消息队列的组建,脚本语言使用PHP,核心操作步骤实现了一个具体的类,代码示例如下:
上述代码利用了zSet结构实现消息队列中有权重的待分发消息的操作,其中这个类利用了两个公开函数和一个私有函数,其中公开函数zPop实现获取权重最小的元素,公开函数zRevPop实现了获取权重最大的元素,这两个公开函数都调用了私有函数zSetPop,zSetPop使用watch和exec来保证这个函数的原子性,在watch和exec中间的所有操作会被看成是一个原子操作。在核心操作步骤中使用zSetPop取出需要的元素(按权重最小或者权重最大确定取出的元素),当元素不存在,行为结束;当元素存在,返回这个元素,并且删除这个元素。上述代码中zSetPop先是取出需要的元素(按权重最小或者权重最大确定取出的元素),当元素不存在,行为结束;当元素存在,返回这个元素,并且删除这个元素。
待分发消息加入到消息队列中是Nginx服务器通过PHP调用Redis数据库的zAdd命令,而取出待分发消息是Nginx服务器通过PHP调用Redis数据库的zPop命令,本发明中待分发消息取出顺序是按权重从大到小的顺序进行的。
在程序执行过程中,zPop每次取出权重最大的元素,如果有权重相同的则依次取出同一级别的,如zPop返回为空,表示没有待分发消息,程序直接此步骤而转到下一步骤。
前面公开的类实现了消息队列的pop操作,关于消息队列的push操作我们通过PHP调用Redis数据库本身的zAdd操作来实现,具体代码如下:
403、建立用户队列内的用户和消息队列内的待分发消息之间的映射关系;
在每一个注册用户与所有的待分发消息之间建立一张映射表,映射表主要包括用户ID和待分发消息的Value。其中用户ID是Nginx服务器通过PHP调用Redis数据库的rPop命令取出的,如rPop返回为空,表示没有新登录用户,则直接结束消息分发流程。此时Redis数据库的zSet结构,将用户ID作为key,消息ID作为Value,在zSet中多个消息ID的Value构成一个集合,因此映射构造是一个用户ID映射一个消息ID的集合。注册用户是一个不断增加的过程,而且登录的用户也是随时在变化的,因此用户队列中只包括那些已登录和新登录的用户,服务器随时将新登录的用户ID加入到当前的用户队列中。而待分发消息也是随时在增加的,所有的消息都保存在数据库中,而每个注册用户的映射表中仅保留各消息的Value,服务器随时将新消息保存到数据库中,在从数据库中取出待分发消息时,对每个待分发消息根据其优先级加上权重后加入到消息队列中,并随时将新的待分发消息与用户队列中的用户ID建立映射关系,即随时针对在线用户ID在其映射表中添加待分发消息的Value,同时对已经分发给此用户ID的消息,将其Value由映射表中删除。
404、接收登录用户的请求信息,根据所述映射关系查找对应所述登录用户的待分发消息;
在客户端轮询的时候,服务器根据此用户ID去数据库中查找其映射表,根据映射表中的映射关系确定当前是否有需要发送给此用户的待分发消息。
405、从查找到的待分发消息中将权重最高的待分发消息发送给所述登录用户。
此时如果此用户有需要发送的待分发消息,由服务器根据映射表中各待分发消息的Value记录的权重大小,依次由数据库中取出各待分发消息发送给登录用户。
本发明为了保证原子性,在所有操作之前都使用了watch命令,在操作之后都使用exec命令。这两个命令都是Redis数据库自带的,组合后的作用就是将watch和exec之间的命令统一打包而看成一个操作来进行。
本发明中的Nginx服务器使用Linux操作系统,但不限于linux操作系统,对服务器适用的类型也没有专门的限定。
如图5所示,实现消息推送的优先级过程为:程序开始10,首先以登录用户12为目标,在数据库上建立一个用户队列13,新登录的用户插入到用户队列13中,获取新登录用户并同时进行是否有新登录用户14的判断,如果没有则直接结束18程序,否则获取登录用户15;同时在数据库中建立一个由待分发消息构成的消息队列20,从消息队列中读取待分发消息并进行是否有待分发消息21的判断,如果没有则直接结束18程序,否则按待分发消息权重22的大小将待分发消息取出,在登录用户与待分发消息之间建立映射16关系,在客户端轮询时按映射关系进行分发消息17,分发完毕后结束18程序。
如图3所示,本发明大并发量请求的处理系统,包括下述模块;
服务器:适于批量接收客户端发送的HTTP请求,然后将HTTP请求直接进行反向代理后转送到HTTP代理;同时服务器将接收的HTTP请求负载均衡到不同的HTTP代理上。
HTTP代理:适于接收到HTTP请求后转换成数据库语言再发送到数据库,同时对接收到的数据库数据进行反向转换后再返回给服务器;其中HTTP代理是根据预定义的HTTPURL语义对HTTP请求和数据库语言进行相互转化的。
数据库:适于在各客户端与其请求的数据之间建立对应关系,再根据HTTP请求按对应关系将相关数据返回给HTTP代理,
服务器:还适于接到HTTP代理返回的数据后再转化为轻量级数据交换格式返回给相应的客户端。
其中的数据库中进一步包括如下模块:
用户队列模块,设置记录注册用户信息的用户队列;
消息队列模块,配置由待分发消息构成的消息队列,对待分发消息根据其不同优先级设定不同的权重,加入到消息队列中;消息队列模块中设定不同的权重是通过在数据库中创建的类函数实现的,类函数包括两个公开函数和一个私有函数;公开函数实现获取消息队列中权重最小的元素或权重最大的元素;私有函数用于保证公开函数调用的自身原子性。对用户已经接收过的待分发消息,将其Value由该用户的映射关系中删除。
映射模块,建立用户队列内的用户和消息队列内的待分发消息之间的映射关系;其中的映射关系是依据用户ID与待分发消息的Value值相对应建立,并将所述映射关系保存到数据库中。
查询模块,接收HTTP代理的请求消息,根据映射模块中的对应关系查找对应的待分发消息;
发送模块,从查找到的待分发消息中将权重最高的待分发消息发送给HTTP代理。待分发消息仅发送给用户队列中的登录用户。
上述模块在客户端轮询时的工作过如下:客户端向服务器发送轮询请求,服务器接收HTTP请求后直接转送到HTTP代理,具体方式是所有HTTP请求利用Nginx服务器自带的upstream模块转化为HTTP请求并进行反向代理传送到HTTP代理,HTTP代理将接收的HTTP请求转换为数据库语言再发送给数据库,同时接收数据库发送模块返回的数据,并对数据进行反向转换成HTTP格式再发送给服务器,Nginx服务器接收HTTP代理返回的数据并发送给相应客户端,其中Nginx服务器是以json形式将各客户端的请求返回给相应客户端的。数据库在客户端代表的用户和其相应请求的数据之间建立对应关系,以加快处理速度,其中数据库中各模块的工作过程如下:用户队列模块随时将新登录的用户ID加入到用户队列中,消息队列模块随时将新的待分发消息加上权重后加入到消息队列中,映射模块随时将新的待分发消息与用户队列中的用户ID建立映射关系,然后查询模块根据HTTP代理接到的请求进行处理,并将相应用户请求的数据通过发送模块返回给HTTP代理。
本发明整合使用了Nginx、Redis和Webdis的消息轮询结构,建立起的消息推送系统架构能支持千万级用户同时在线轮询查询消息的需求规模,本发明中的服务器不直接处理HTTP请求,而是转送到Webdis代理中进行语言转换,减少了服务器自身的负担,同时利用Webdis代理均衡所有的客户端请求,且每个Webdis代理能够进行多线程处理,大大提高了整个请求的处理过程。本发明为每个Redis数据库配置一个Webdis代理,使得每个Redis数据库都可以使用HTTP进行访问,实现了客户端直接使用HTTP协议根据session凭证进行高效的Redis数据库查询的结构。Nginx服务器作为查询的Web server,接受请求,并将请求负载均衡到不同的Webdis代理上,Webdis代理收取到客户端查询请求的时候,根据Webdis代理制定的HTTP url的语义化将它转化成为对Redis数据库的查询语句,并将Redis数据库的查询结构以json格式返回,由Nginx服务器返回给客户端,完成了一次消息查询。这套消息轮询查询消息的结构整合使用能抵抗高并发请求的Nginx、Webdis、Redis等技术,因此在1分钟内能接受超过1000w的查询请求。
以上所述仅是本发明的较佳实施例而已,并非对本发明作任何形式上的限制,虽然本发明已以较佳实施例揭露如上,然而并非用以限定本发明,任何熟悉本专利的技术人员在不脱离本发明技术方案范围内,当可利用上述提示的技术内容作出些许更动或修饰为等同变化的等效实施例,但凡是未脱离本发明技术方案的内容,依据本发明的技术实质对以上实施例所作的任何简单修改、等同变化与修饰,均仍属于本发明方案的范围内。