深圳市建网站公,高端网站建设 房产,百度信息流推广教程,最近新闻头条2023业务场景
场景一
用户完成注册后需要发送欢迎注册的问候邮件、同时后台要发送实时消息给用户对应的业务员有新的客户注册、最后将用户的注册数据通过接口推送到一个营销用的第三方平台。
遇到两个问题#xff1a;
由于代码是串行方式#xff0c;流程大致为#xff1a;开…业务场景
场景一
用户完成注册后需要发送欢迎注册的问候邮件、同时后台要发送实时消息给用户对应的业务员有新的客户注册、最后将用户的注册数据通过接口推送到一个营销用的第三方平台。
遇到两个问题
由于代码是串行方式流程大致为开启数据库事务回滚-数据入库准备-发邮件-发实时消息-推送第三方平台-提交写入数据库。但是后续的3个步骤任意一个流程出了问题都会影响用户的注册结果。发送邮件使用的不是成熟的第三方产品而是利用phpmaile自写代码实现的然而这个过程耗时相对较长且偶尔有失败的情况另外通过接口推送注册用户数据到的第三方平台是一个国外的产品接口通讯时间很长且一样有失败的情况。
以上两个问题就会导致用户的注册交互流程时间很长产品体验感非常差且发送邮件、发送消息、推送数据任意一个步骤由于特殊情况导致执行失败都不能终止用户注册这样就只能通过日志捕获相应的失败情况。
场景二
用户在Shopify平台(一个跨境电商平台)付款下单后商家会将订单同步到我的系统中在我的系统中完成询价、报价、付款后我需要再将订单数据推送到第三方配货发货的平台。平台发货完成后通过设置好的回调地址通知我的系统发货的物流信息数据我需要将物流信息数据存入到我的数据库后再将物流信息同步给Shopify平台用以展示给真实下单用户查看物流轨迹。
遇到一个问题
正常情况下的回调代码逻辑是将物流信息写入数据库再同步物流数据给Shopify。但是由于各种原因后者同步物流数据给Shopify有一定概率会失败。
这样就出现了我系统内成功展示了物流信息而Shopify反馈没有成功同步物流轨迹的订单出现。而回调又是一次性的我只能自查数据库进行回补。
英雄登场消息队列Redis 官方介绍消息队列中间件是大型系统中的重要组件已经逐渐成为企业系统内部通信的核心手段。它具有松耦合、异步消息、流量削峰、可靠投递、广播、流量控制、最终一致性等一系列功能已经成为异步RPC的主要手段之一。 Redis安装
我用的宝塔安装的方便快捷软件商品搜索Redis然后点击系统对应php版本的立即前往 再后续弹窗中安装redis扩展即可 后续Redis中的队列数据也可以通过宝塔进行查看
thinkphp/queue
扩展这个内置了 Redis、Database、Topthink、Sync四种驱动这里我用的Redis。think-queue 队列消息可以进行任务的发布、获取、执行、删除、重新发布、延迟发布、超时控制等操作。
thinkphp/queue引入扩展
composer require topthink/think-queuethinkphp/queue配置文件
我使用的是TP5要再application/extra目录下新增queue.php文件文件内容如下视各自情况调整哈
return [connector Redis, // 驱动类型expire 60, // 任务的过期时间默认为60秒; 如果任务执行时间超过此时间将会被认为是过期将不会被执行default default, // 默认的队列名称host 127.0.0.1, // Redis 主机地址port 6379, // Redis 端口password , // Redis 密码select 0, // 使用哪一个 Redis 数据库timeout 0, // 连接超时时间persistent false, // 是否长连接
];解决方案注册部分
引入消息队列后就是将原来串行方式改为并行用户注册逻辑代码中关于后三个步骤只要单纯的推送队列即可。而后三者采用并行方式也就是异步执行对应的逻辑。这样既提高了注册的速度又可以通过队列将出错的数据多次执行提高成功率
注册逻辑代码 public static function doSaveRegister($postParam){db()-startTrans();try {$first_name trim(outputstr($postParam, first_name));$last_name trim(outputstr($postParam, last_name));$email trim(outputstr($postParam, email));$password trim(outputstr($postParam, password));//注册部分就展示部分代码了$info new UserModel();$info-id Uuid::uuid4();$info-number createUserNumber();$info-short_name substr($email, 0, strripos($email, ));$info-email $email;if ($info-save() false) {throw new Exception(Operation error!);}//发送用户注册成功的问候邮件将要发送邮件的邮箱推送到消息队列$result RedisUtils::redisQueueSendForSendRegisterWelcomeEmail(common\job\UserRegisterJobsendRegisterSuccessWelcomeEmail, $email);if ($result[success] false) {throw new Exception(redis queue error!);}//这里只展示发送邮件的代码示例其他都是一样的道理db()-commit();$result result_success(Register successful!);} catch (Exception $e) {db()-rollback();$result result_error($e-getMessage());}return $result;}推送发送邮件消息队列生产者 /*** 用户注册成功需要发送问候邮件的用户数据加入队列* param string $job 处理该任务的任务名* param string $data 加入队列的数据-邮箱号* param string $queue_name 队列名可以不写*/public static function redisQueueSendForSendRegisterWelcomeEmail($job, $data, $queue_name user_register_email){//此处做了延时推送原因是邮件服务是自己写程序实现的避免高并发导致发送失败所以延时推送一下$isPushed Queue::later(5, $job, $data, $queue_name);if ($isPushed ! false) {$result result_success(队列加入成功);} else {$result result_error(队列加入失败);}return $result;}消息队列处理逻辑消费者
?phpnamespace common\job;use common\utils\email\EmailUtils;
use common\utils\gateway\GatewaysUtils;
use common\utils\log\LoggerUtils;
use common\utils\systemMessage\SystemMessageUtils;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\ClientException;
use think\queue\Job;/*** 处理所有用户注册方面的队列数据代码逻辑写在这里运行方式是命令行执行的* Class UserRegister* package common\job*/
class UserRegisterJob
{/*** 处理发送用户注册成功邮件的队列* param Job $job* param string $data 要发送邮件的邮箱*/public function sendRegisterSuccessWelcomeEmail(Job $job, $data){$result EmailUtils::sendUserRegisterSuccessEmail($data);if ($result[success] false) {//判断一下发送失败的次数超过3次剔除队列$attempts $job-attempts();if ($attempts 3) {//发送失败写进日志邮件通知开发者$message 新用户注册发送问候邮件失败程序错误内容 . $result[msg] . ,数据源 . $data;LoggerUtils::systemErrorLog()-info($message);EmailUtils::sendSystemErrorEmailToDeveloper($message);$job-delete();}} else {//发送成功剔除队列$job-delete();}}
}启动队列监听
进入项目根目录执行
php think queue:work --queue 队列名1,队列名2多个队列可以用逗号拼接一次性监听
这个进行一般都要后台运行且开机自启动自己写的脚本如下
#!/bin/bash
#启动Redis队列监听
cd /www/wwwroot/english-e-commerce/ php think queue:listen --queue user_register_email,user_register_workman_message,sync_user_to_tidio,order_sync_mabang_track,fulfillment_shopify_order 开机启动方法根据不同linux系统有很多种此处不做记录
不喜勿喷也是初学。记录一下方便后面查找
参考链接
ThinkPHP 使用 think-queue 实现 redis 消息队列超详细消息队列使用的四种场景介绍