内容简介:在上一节中我们介绍了使用Swoole发送单个邮件,那么如果是大量的邮件需要发送,比如给2万个用户发送优惠活动邮件,这是一个比较耗时的过程,而PHP本身不适合处理这种耗时多任务场景。本节为给大家介绍使用Swoole+Redis来实现发送批量邮件的例子。
在上一节中我们介绍了使用Swoole发送单个邮件,那么如果是大量的邮件需要发送,比如给2万个用户发送优惠活动邮件,这是一个比较耗时的过程,而 PHP 本身不适合处理这种耗时多任务场景。本节为给大家介绍使用Swoole+Redis来实现发送批量邮件的例子。
建立任务
接上一节代码,编辑src/App/Mail.php文件代码,在 public function onTask()
方法中增加批量队列发送邮件的代码:
public function onTask(swoole_server $serv, $task_id, $from_id, $data) { $res['result'] = 'failed'; $req = json_decode($data, true); $action = $req['action']; echo date('Y-m-d H:i:s')." onTask: [".$action."].\n"; switch ($action) { case 'sendMail': //发送单个邮件 $mailData = [ 'emailAddress' => 'abc@example.com', //接收方,改成自己的邮箱可以测试接收邮件 'subject' => 'swoole实验室', 'body' => '测试This is the HTML message body.', 'attach' => '/home/swoole/public/a.jpg' ]; $this->sendMail($mailData); break; case 'sendMailQueue': // 批量队列发送邮件 $this->sendMailQueue(); break; default: break; } }
建立 Redis 队列
由于发送的邮件比较多,我们把邮件列表事先保存在Redis队列中。我们知道Redis的使用场景很多,其中就可以用它来做简单的队列。
我们在任务中调用了 sendMailQueue()
方法,继续在Mail.php中添加:
// 邮件发送队列 private function sendMailQueue() { $redis = new \Redis(); $redis->connect('127.0.0.1', 6379); $password = '123'; $redis->auth($password); swoole_timer_tick(1000, function($timer) use ($redis) { // 启用定时器,每1秒执行一次 $value = $redis->lpop('mailerlist'); if($value){ //echo '获取redis数据:' . $value; $json = json_decode($value, true); $start = microtime(true); $rs = $this->sendMail($json); $end = microtime(true); if ($rs) { echo '发送成功!'.$value.', 耗时:'. round($end - $start, 3).'秒'.PHP_EOL; } else { // 把发送失败的加入到失败队列中,人工处理 $redis->rpush("mailerlist_err", $value); } }else{ swoole_timer_clear($timer); // 停止定时器 echo "Emaillist出队完成"; } }); }
上述代码中,先尝试连接Redis,然后使用Swoole的 swoole_timer_tick()
函数,它是个定时器,这个函数跟js的interval()函数一样,意思是每隔一定时间执行一次,它可以定义毫秒级粒度。很显然,上述代码中,每隔1000毫秒(1秒)从Redis队列mailerlist中取出一条,即一个邮件对象,然后执行发送邮件 sendMail()
,当发送完所有邮件后,使用 swoole_timer_clear()
关闭定时器即可。定时器的间隔时间可以调整。
客户端
在客户端,我们先往Redis队列里添加邮件内容,然后向服务端发起 sendMailQueue
批量发邮件指令。
<?php class Client { private $client; public function __construct() { $this->client = new swoole_client(SWOOLE_SOCK_TCP); } public function connect() { if( !$this->client->connect("127.0.0.1", 9502 , 1) ) { echo "Error: {$this->client->errMsg}[{$this->client->errCode}]\n"; } $action = 'sendMailQueue'; $time = time(); $key = 'MYgGnQE33ytd2jDFADS39DSEWsdD24sK'; $token = md5($action.$time.$key); $data = [ 'action' => $action, 'token' => $token, 'timestamp' => $time ]; $msg = json_encode($data); $this->client->send( $msg ); $message = $this->client->recv(); echo "Get Message From Server:{$message}\n"; } } $redis = new Redis(); $redis->connect('127.0.0.1', 6379); $password = '123'; $redis->auth($password); $arr = []; $arr[0] = [ 'subject' => '国庆大酬宾,全场1折', 'emailAddress' => 'axxxx@example.com', 'body' => '您好,国庆期间大酬宾,全场所有商品统统1折甩卖。' ]; $arr[1] = [ 'subject' => '注册会员送100金币', 'emailAddress' => 'bxxxx@example.com', 'body' => '邮件内容' ]; $arr[2] = [ 'subject' => '国庆大酬宾,全场1折', 'emailAddress' => 'cxxxxx@example.com', 'body' => '邮件内容2' ]; foreach ($arr as $k=>$v) { $redis->rpush("mailerlist", json_encode($v, JSON_UNESCAPED_UNICODE)); } $client = new Client(); $client->connect();
验证
根据上一节内容,我们应该先启动服务端,看到Swoole服务端启动好了,我们再运行客户端:
php mailClient.php
然后你可以去查看对方邮箱是否收到相关邮件。
本文中使用了redis作为简单队列,你也可以使用复杂点的队列rabbitmq。你也可以使用Crontab来做定时任务,不过它最小粒度是分钟级别的。当然对于批量发送邮件,如果你不用php的话,可以用 Python 或者Java,它们都有相当成熟的解决方案。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Swoole实验室:2-使用Swoole发送邮件
- Ceph实验室:第四课:Ceph监控
- Ceph实验室:第四课:Ceph监控
- 2018Android实验室CV培训总结
- 复旦NLP实验室NLP上手教程
- Ceph实验室:第三课:Ceph服务管理
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beginning XSLT 2.0
Jeni Tennison / Apress / 2005-07-22 / USD 49.99
This is an updated revision of Tennison's "Beginning XSLT", updated for the new revision of the XSLT standard. XSLT is a technology used to transform an XML document with one structure into another ......一起来看看 《Beginning XSLT 2.0》 这本书的介绍吧!