排队:针对关键路径进行优化

最大的性能破坏因素之一就是在应用程序的关键路径上执行的不必要的动作。 让我们来看一个简单的注册示例:

  router.post('/ register ',function(req,res){ 
var user = new User(req.body);
user.save(function(err){
如果(!err){
user.savePreferences(req.pref);
user.sendWelcomeEmail();
res.render('first_time_welcome',
{title:' Welcome '+ user.name,错误:[err]}
);
}
});
});

该代码看起来很简单。 用户提交注册表格,代码保存使用过的详细信息和首选项,发送欢迎电子邮件,并向用户显示“欢迎”页面。

针对用户体验进行优化-您希望尽快显示确认页面,以便用户可以开始购物/张贴/进行对您的业务最有利的活动。 因此,您要确保注册过程快速而轻松。 因此,让我们为其计时,并确保它是正确的。 平均而言,以上代码在2.7秒内返回了所需的“欢迎”页面偶尔出现尖峰最多需要10秒 。 并非完全在可接受的性能范围内,尤其是由于代码非常苗条,因此需要进行两次快速的数据库插入(针对user.saveuser.savePreferences ),并且没有进行任何user.savePreferences逻辑计算。

将时间添加到单个操作中,似乎占用最多周期的功能是user.sendWelcomeEmail

  User.sendWelcomeEmail = function(callback){ 
如果(!do_not_email(user.email){
var email = new Email();
email.subject =“ Welcome ” + user.firstname;
email.cta = getDealoftheDay();
email.secondary = getOffers(用户);
email.generateBody(user,function(){
email.send();
});
}
};

答对了! user.sendWelcomeEmail从数据库检索信息,进行实时定位,并调用立即发送出去。 可以对代码进行一些优化以加快处理速度(使用缓存,预处理和其他技术),但是任何开发人员都应该问自己的真正问题是: 我们为什么在此期间发送欢迎电子邮件?注册过程

现在必须要做吗?

要回答这个问题,您必须了解“现在”对您的业务意味着什么。 注册后是否应将欢迎电子邮件发送给新用户? 是。 在向用户显示“欢迎”页面之前是否应该发送欢迎电子邮件? 可能不会。

任何与即时业务 成果无关的事情都不应该成为关键之路

近期目标是将用户带入网站。 从业务回报的角度来看,欢迎电子邮件虽然可能同样有价值,但它是基于时间安排的次要目标。 这意味着user.sendWelcomeEmail函数不属于注册过程。 这适用于任何其他无助于实现主要目标的功能。 任何与即时业务 成果无关的事情都不应走关键路线。 这意味着所有其他过程都需要移出关键路径。

输入排队

排队也是排队许多可以以比实时用户体验慢的速度处理的动作的好方法。 应用程序会将一个条目添加到您的队列中,并且外部作业将按照出现顺序(FIFO)拾取这些条目。

实现队列的方法有很多种,但是最常用的是MQ特定的工具和数据库。

邮件队列工具

有一些工具可以用作队列的基础。 如果您依赖开放源代码工具,那么RabbitMQ可能是最受欢迎和易于设置的工具。 如果您对亚马逊生态系统投入了大量资金,则可能需要研究SQS。

数据库

您还可以使用任何数据库来实现自己的队列。 传统上,您将创建一个队列表并让cronjob经常(根据您的等待时间要求)提取新数据并进行处理。 此外,某些现代数据库实现了排队功能,允许作业订阅您的队列表并等待新条目,而不是传统的定期拉取。

正确的方式

回到注册码,将需要对流程进行较小的更改。

  router.post('/ register ',function(req,res){ 
var user = new User(req.body);
user.save(function(err){
如果(!err){
user.savePreferences(req.pref);
sendToQueue( 'welcome email' user );
res.render('first_time_welcome',
{title:' Welcome '+ user.name,错误:[err]}
);
}
});
});

另外,您的cronjob只需要遍历队列中的新条目并调用以前在我们注册过程的关键路径中的同一user.sendWelcomeEmail函数。

  while(var user = readFromQueue(' welcome email ')){ 
user.sendWelcomeEmail();
}

现在,由于“欢迎”页面的时间已减少到300毫秒 ,因此欢迎电子邮件在用户注册后的1到5分钟内就会消失,这是可以接受的延迟