pheanstalk 简单案例
前言
上一小节,我们介绍了 pheanstalk 的使用。
这一小节,我们使用 pheanstalk 来完成一个小功能。
需求设计

主要是一个注册功能,当用户注册成功之后,会接收到两条信息,分别是邮件和短信。
这里的邮件和短信,我们以消息队列来实现,这样可以加快服务端对用户端的响应,提高体验。
实现规划
1、以 php + mysql + beanstalkd 为基础架构
2、使用 pheanstalk 操作 beanstalkd、使用 medoo 操作 mysql
3、使用 composer 作为包管理工具
4、有三个文件:
- register.php 负责接收注册请求、用户信息入库、生成短信任务和邮件任务
 - sms.php 短信任务消费者
 - email.php 邮件任务消费者
代码实现
包安装
composer require pda/pheanstalkcomposer require catfan/medoo
demo.sql
CREATE TABLE `user` (`id` int(10) unsigned NOT NULL AUTO_INCREMENT,`username` varchar(50) COLLATE utf8_bin NOT NULL,`email` varchar(100) COLLATE utf8_bin NOT NULL,`phone` char(11) COLLATE utf8_bin NOT NULL,`password` varchar(255) COLLATE utf8_bin NOT NULL,PRIMARY KEY (`id`),KEY `user_username` (`username`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
register.php
<?php// +----------------------------------------------------------------------// | register.php// +----------------------------------------------------------------------// | Description: 注册// +----------------------------------------------------------------------// | Time: 2021/1/1 下午1:47// +----------------------------------------------------------------------// | Author: Object,一季樱花落雨殇<1647762341@qq.com>// +----------------------------------------------------------------------require_once "../vendor/autoload.php";use Medoo\Medoo;use Pheanstalk\Pheanstalk;// demo 只为演示如何使用 pheanstalk ,所以不做精细化处理,如注入、加密、字段设计等,只能用于简单测试$param = getopt('u:p:e:m:');$username = $param['u'];$password = $param['p'];$email = $param['e'];$phone = $param['m'];$db = new Medoo(['database_type' => 'mysql','database_name' => 'test','server' => 'mysql','username' => 'root','password' => 'root',// [optional]'charset' => 'utf8','port' => 3306,]);$alreadyIn = $db->has('user', ['OR' => ['username' => $username,'email' => $email,'phone' => $phone,]]);if ($alreadyIn) {echo '用户已存在';die();}// 插入用户$user = ['username' => $username,'email' => $email,'phone' => $phone,'password' => $password];$db->insert('user', $user);$user['id'] = $db->id();$jobData = json_encode($user);$conn = Pheanstalk::create('beanstalkd', 11300, 10);$conn->useTube('register_sms');$smsJob = $conn->put($jobData);$conn->useTube('register_email');$emailJob = $conn->put($jobData);echo '注册成功:<br>';print_r($user);print_r($smsJob);print_r($emailJob);
sms.php
<?php// +----------------------------------------------------------------------// | sms.php// +----------------------------------------------------------------------// | Description:// +----------------------------------------------------------------------// | Time: 2021/1/1 下午1:47// +----------------------------------------------------------------------// | Author: Object,一季樱花落雨殇<1647762341@qq.com>// +----------------------------------------------------------------------include_once "../vendor/autoload.php";use Pheanstalk\Pheanstalk;$conn = Pheanstalk::create('beanstalkd', 11300, 10);$conn->watchOnly('register_sms');function sendSms($user){return random_int(0, 1); // 取随机数,模拟发送成功与失败}while (1) {try {$job = $conn->reserveWithTimeout(1);if ($job === null) {throw new Exception('没有任务');}// 发送邮件if (sendSms($job->getData())) {// 处理成功$conn->delete($job);} else {// 处理失败$conn->release();}} catch (Exception $e) {print_r($e->getMessage());die();}echo "欢迎短信发送成功<br>";usleep(500000);}
email.php
<?php// +----------------------------------------------------------------------// | email.php// +----------------------------------------------------------------------// | Description:// +----------------------------------------------------------------------// | Time: 2021/1/1 下午1:47// +----------------------------------------------------------------------// | Author: Object,一季樱花落雨殇<1647762341@qq.com>// +----------------------------------------------------------------------include_once "../vendor/autoload.php";use Pheanstalk\Pheanstalk;$conn = Pheanstalk::create('beanstalkd', 11300, 10);$conn->watchOnly('register_email');function sendEmail($user){return random_int(0, 1); // 取随机数,模拟发送成功与失败}while (1) {try {$job = $conn->reserve();if ($job === null) {throw new Exception('没有任务');}// 发送邮件if (sendEmail($job->getData())) {// 处理成功$conn->delete($job);} else {// 处理失败$conn->release();}} catch (Exception $e) {print_r($e->getMessage());die();}echo "欢迎邮件发送成功<br>";usleep(500000); // 每 500ms 接收 job}
测试
先确保,你的 php 脚本能正确地连接到 mysql 和 beanstalkd
然后,打开三个 shell 窗口,每个窗口按顺序运行一条命令:php sms.php
php email.php
其中,sms.php 和 email.php 两个窗口,会阻塞运行。php register.php -u username -p password -e email@qq.com -m 15866668888
每当有运行过 register.php 之后,三个窗口就分别会有输出。
大致如下:


 
