Skip to content

添加队列

liaofei edited this page Jan 20, 2021 · 1 revision

消息队列中间件是分布式系统中重要的组件,主要解决应用耦合、异步消息、流量削锋等问题。实现高性能、高可用、可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。

对于不太理解使用队列异步处理优点的开发者我以两张图为例,以便大家理解,在二开业务的时候能对业务作出更好的处理逻辑。

场景

场景说明:用户注册后,需要发送注册邮件和发送注册信息,传统的做法有两种:串行方式、并行方式

串行方式

将注册信息写入数据库成功后,发送注册邮件,然后发送注册短信,而所有任务执行完成后,返回信息给客户端

输入图片说明

并行方式

将注册信息写入数据库成功后,同时进行发送注册邮件和发送注册短信的操作。而所有任务执行完成后,返回信息给客户端。同串行方式相比,并行方式可以提高执行效率,减少执行时间。

输入图片说明

上面的比较可以发现,假设三个操作均需要50ms的执行时间,排除网络因素,则最终执行完成,串行方式需要150ms,而并行方式需要100ms。

因为cpu在单位时间内处理的请求数量是一致的,假设:CPU每1秒吞吐量是100此,则串行方式1秒内可执行的请求量为1000/150,不到7次;并行方式1秒内可执行的请求量为1000/100,为10次。

由上可以看出,传统串行和并行的方式会受到系统性能的局限,那么如何解决这个问题? 我们需要引入消息队列,将不是必须的业务逻辑,异步进行处理,由此改造出来的流程为

输入图片说明

根据上述的流程,用户的响应时间基本相当于将用户数据写入数据库的时间,发送注册邮件、发送注册短信的消息在写入消息队列后,即可返回执行结果,写入消息队列的时间很快,几乎可以忽略,也有此可以将系统吞吐量提升至20QPS,比串行方式提升近3倍,比并行方式提升2倍。


上面的例子只是队列其中一点优点,也是为了让开发者更好的了解队列,下面我们就讲一下,在我们系统中如何去添加一个队列服务类,并在具体的业务中如何调用。

一,队列配置文件config/queue.php

输入图片说明

二,业务队列服务类

具体的介绍参考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

Clone this wiki locally