-
Notifications
You must be signed in to change notification settings - Fork 1.6k
添加队列
消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。
对于不太理解使用队列异步处理优点的开发者我以两张图为例,以便大家理解,在二开业务的时候能对业务作出更好的处理逻辑。
场景说明:用户注册后,需要发送注册邮件和发送注册信息,传统的做法有两种:串行方式、并行方式
将注册信息写入数据库成功后,发送注册邮件,然后发送注册短信,而所有任务执行完成后,返回信息给客户端
将注册信息写入数据库成功后,同时进行发送注册邮件和发送注册短信的操作。而所有任务执行完成后,返回信息给客户端。同串行方式相比,并行方式可以提高执行效率,减少执行时间。
上面的比较可以发现,假设三个操作均需要50ms的执行时间,排除网络因素,则最终执行完成,串行方式需要150ms,而并行方式需要100ms。
因为cpu在单位时间内处理的请求数量是一致的,假设:CPU每1秒吞吐量是100此,则串行方式1秒内可执行的请求量为1000/150,不到7次;并行方式1秒内可执行的请求量为1000/100,为10次。
由上可以看出,传统串行和并行的方式会受到系统性能的局限,那么如何解决这个问题? 我们需要引入消息队列,将不是必须的业务逻辑,异步进行处理,由此改造出来的流程为
根据上述的流程,用户的响应时间基本相当于将用户数据写入数据库的时间,发送注册邮件、发送注册短信的消息在写入消息队列后,即可返回执行结果,写入消息队列的时间很快,几乎可以忽略,也有此可以将系统吞吐量提升至20QPS,比串行方式提升近3倍,比并行方式提升2倍。
上面的例子只是队列其中一点优点,也是为了让开发者更好的了解队列,下面我们就讲一下,在我们系统中如何去添加一个队列服务类,并在具体的业务中如何调用。
具体的介绍参考Jobs服务队列,其中对各个服务队列已做详细介绍。
任务类需要继承消息队列基类crmeb/basic/BaseJob.php,如果这个类只有一个任务,那么就只需要提供一个doJob方法就可以了,如果有多个小任务,就写多个方法,在具体的业务控制器调用发布任务的时候会有区别,每个方法会传入两个参数 think\queue\Job $job(当前的任务对象) 和 $data(发布任务时自定义的数据)。所有创建任务队列类都应放在crmeb/jobs目录下
第一,单任务
1,创建Job1.php任务
<?php
namespace crmeb\jobs;
use crmeb\basic\BaseJob;
use crmeb\utils\Queue;
class Job1 extends BaseJob
{
/**
* 执行方法
* @param $order
* @return bool
*/
public function doJob($data)
{
//具体任务逻辑
}
}
2,调用发布Job1任务
use crmeb\utils\Queue;
Queue::instance()->job(\crmeb\jobs\Job1::class)->data($data)->push();
第二,多任务
1,创建Job2.php任务
<?php
namespace crmeb\jobs;
use crmeb\basic\BaseJob;
use crmeb\utils\Queue;
class Job2 extends BaseJob
{
/**
* 执行方法1
* @param $order
* @return bool
*/
public function action1($data)
{
//具体任务逻辑
}
/**
* 执行方法2
* @param $order
* @return bool
*/
public function action2($data)
{
//具体任务逻辑
}
}
2,调用发布Job2任务
use crmeb\utils\Queue;
Queue::instance()->do('action1')->job(Job2 ::class)->data($data)->push();
以上代码全部准备完毕之后,就需要再服务器开启任务队列的监听了 执行以下命令即可
php think queue:listen --queue CRMEB