(描述不对的地方望包涵指正)任务队列是讲要处理的任务放在队列中按顺序执行,可以将耗时的或者是不需要前端知道的任务与业务分离开来,在我看来主要有2个方面的好处
1.增强了界面的友好型,就是用户感觉也操作起来更快了,下面会有详细的介绍
2.增强了后端应用服务器的吞吐量,假如我们的前端服务器是nginx,一个牛逼的服务器,大家可以自行了解它的机制,在我看来它是一个很厉害的吃货,它不会管你的胃(应用服务器)是否很能不能装食物,只要有食物到嘴边它就吃(我发现了一个冷笑话,尼玛吃起东西来感觉像是异步的)。nginx是单进程的,生成环境中根据cpu来看2个或者多个进程,如果有2个很耗时的操作同时暂用了这2个进程,那么其它的进程就会阻塞了(所有的食物都堵在了食管,胃还在分泌胃酸消化这个2坨东西),所以可以考虑将这部分耗时操作写成异步代码,但是异步代码只能提高吞吐量而不能给用户非一般的操作体验而且异步代码不容易驾驭(考虑tornado),看可不可以使用redis的队列吧
目前项目中在2个地方用到了redis得队列
1.用户注册激活邮件发送
我们具体分析一下这个需求,发送邮件这个需求对于用户来说不需要那么强的实时性,因为用户还要去打开邮件或者登录邮件,等待几秒钟都是可以接受的,但用户注册之后完全可以在前端提示用户“邮件已发送”,不需要等待邮件真正发送之后再去提示,而是发到任务队列中去处理,文字有点多 上代码
sessiondb.lpush("mailQueue",i["phoneNum"]+":"+i["mail"])
前面大家不要纠结只要注意lpush的函数就可以了(我用的是Python的redis的模块),lpush(redis也是lpush)也是操作队列,顾名思义,向列表的左侧push一个任务到redis中去,mailQueue就是这样的了["137222":"88@qq.com"]
然后单独启动一个python实例来处理队列任务
def handlerMailQueue():
toMail = sessionDB.brpop("mailQueue",timeout=0)
toMail = toMail[1].split(":")
try:
sendMail(toMail[0],toMail[1])
handlerMailQueue()
except Exception as e:
raise ""
if __name__ =="__main__":
handlerMailQueue()
同样大家不用关心sessionDB或者sendmail这些东西,自己写。注意brpop,从mailQueue的左侧取出任务来,timeout=0表示会一直阻塞住,直到队列中有数据了才结束,发送完邮件再接着阻塞监听。
你也可以写死循环来监听,或者有什么更好的办法来处理 我只能用笨办法了,如果大家对服务器要求高 可以做分布式的
2.调用php脚本执行相关函数,实现同步注册
在这里调用php主要是为了让我们的网站与discuz做同步实现单点登录,会有一篇文章专门讲解如何利用ucenter实现不同网站(nodejs,java,python)与discuz的单点登录,我们分析一下同步注册,同步注册就是在我们网站如果完成了注册,同时调用php脚本把数据存到discuz的mysql数据库中去,对于这一步也是不用与前端交互的 存完了没有和用户没有关系。
这里的过程和上述方式一样最终监听取出,执行php脚本,把username,password,email存到discuz数据库
os.popen('php /usr/local/developer-wf/uc_client/php_pro/register.php '+bbs_user["username"]+' '+bbs_user["password"]+' '+bbs_user["email"])