phprabbitmq的开发体验(代码片段)

您所在的位置:网站首页 rabbitmq消息一直unacked phprabbitmq的开发体验(代码片段)

phprabbitmq的开发体验(代码片段)

2023-04-09 17:40| 来源: 网络整理| 查看: 265

phprabbitmq的开发体验(代码片段) 日期:2022-11-29     来源:贽殿遮那    作者:贽殿遮那    浏览:681    java教程

本文目录

1、phprabbitmq的开发体验(代码片段)

2、swift开发快速体验

一、前言

在上一篇rabbitmq开发体验(二),我们正式的用我们php来操作消息队列的生产和消费,并利用的rabbitmq的高级特性来进行ack确认机制,幂等性,限流机制,重回机制,ttl,死信队列(相当于失败消息的回收站)。已经可以正常的使用,但消息消费异常问题罗列以下。

1、自动ack机制会导致消息丢失的问题;

简要代码如下,设置消息自动ack,这种情况下,MQ只要确认消息发送成功,无须等待应答就会丢弃消息,这会导致客户端还未处理完时,出异常或断电了,导致消息丢失的后果。解决方法就是把代码里的true,改成false,并在消息处理完后发ack响应。注:自动ack还有个弊端,只要队列不空,RabbitMQ会源源不断的把消息推送给客户端,而不管客户端能否消费的完。

$this->channel->basic_consume( $this->query_name, \'\', //customer_tag false, //no_local true, //no_ack 消息自动ack false, //exclusive 排他消费者,即这个队列只能由一个消费者消费.适用于任务不允许进行并发处理的情况下.比如系统对接 false, //nowait

2、自动ack机制会导致消息丢失的问题;

为了解决问题1,做了改进,简要代码如下:

$this->channel->basic_consume( $this->query_name, \'\', //customer_tag false, //no_local false, //no_ack 关闭自动ack,手工发送ack false, //exclusive 排他消费者,即这个队列只能由一个消费者消费.适用于任务不允许进行并发处理的情况下.比如系统对接 false, //nowait

 

$msg->delivery_info[\'channel\']->basic_ack($msg->delivery_info[\'delivery_tag\']); //手动在成功消费后发送ack

先处理消息,完成后,再做ack响应,失败就不做ack响应,这样消息会储存在MQ的Unacked消息里,不会丢失,看起来没啥问题,但是有一次,callback触发了一个bug,导致所有消息都抛出异常,然后队列的Unacked消息数暴涨,导致MQ响应越来越慢,甚至崩溃的问题。原因是如果MQ没得到ack响应,这些消息会堆积在Unacked消息里,不会抛弃,直至客户端断开重连时,才变回ready;如果Consumer客户端不断开连接,这些Unacked消息,永远不会变回ready状态,Unacked消息多了,占用内存越来越大,就会异常了。解决办法就是及时去ack消息了。

3、启用nack机制后,导致的死循环;

为了解决问题2,再调整一下代码,简要代码如下:

catch (Exception $e) $this->writeLog(\'runtime/vm_exception.log\',$e->getMessage()); //发送nack信息应答当前消息处理异常 第三个参数是否重回队列 默认false不重回队列 $msg->delivery_info[\'channel\']->basic_nack($msg->delivery_info[\'delivery_tag\'],false,true);

嗯,改成这模样总没问题了吧,正常就ack,不正常就nack,并等下一次重新消费。果然,又出问题了,这回又是callback出异常了,但是故障现象是Ready的消息猛增,一直不见减少。原因是出异常后,把消息塞回队列头部,下一步又消费这条会出异常的消息,又出错,塞回队列……进入了死循环了,当然新的消息不会消费,导致堆积了……

我的解决方案:

 

$retry = $this->getRetryCount($msg); try $routingKey = $this->getOrigRoutingKey($msg); $subMessage = new SubMessage($msg, $routingKey , [ \'retry_count\' => $retry, // 重试次数 ]); $this->subscribe($subMessage); catch (\\Exception $ex) $this->writeLog(\'runtime/vm_consume_failed.log\', \'消费失败!\' . $ex->getMessage() . $msg->getBody()); if ($retry > 3) // 超过最大重试次数,消息无法处理 $publishFailed($msg); return; // 消息处理失败,稍后重试 $publishRetry($msg); /** * 获取消息重试次数 * @param AMQPMessage $msg * @return int */ protected function getRetryCount($msg) $retry = 0; if ($msg->has(\'application_headers\')) $headers = $msg->get(\'application_headers\')->getNativeData(); if (isset($headers[\'x-death\'][0][\'count\'])) $retry = $headers[\'x-death\'][0][\'count\']; return (int)$retry; // 发起延时重试 $publishRetry = function ($msg) use ($queueName,$exchangeRetryName) /** @var AMQPTable $headers */ if ($msg->has(\'application_headers\')) $headers = $msg->get(\'application_headers\'); else $headers = new AMQPTable(); $headers->set(\'x-orig-routing-key\', $this->getOrigRoutingKey($msg)); $properties = $msg->get_properties(); $properties[\'application_headers\'] = $headers; $newMsg = new AMQPMessage($msg->getBody(), $properties); $this->channel->basic_publish( $newMsg, $exchangeRetryName, $queueName ); //发送ack信息应答当前消息处理完成 $msg->delivery_info[\'channel\']->basic_ack($msg->delivery_info[\'delivery_tag\']); ; /** * 声明重试队列 */ private function declareRetryQueue() $this->channel->queue_declare($this->query_retry_name, false, true, false, false, false,new AMQPTable(array( \'x-dead-letter-exchange\' => $this->exchange_name, \'x-dead-letter-routing-key\' => $this->query_name, \'x-message-ttl\' => 3 * 1000, ))); $this->channel->queue_bind($this->query_retry_name, $this->exchange_retry_name, $this->query_name);

 

swift开发快速体验

相关文章>

开发者体验:如何更好的呈现错误?(代码片段)

{在年初的那一篇《开发者体验——内部工具的“最后一公里”文档体验的设计开始之前,先让我们转换一下视角,让我们思考一下开发者是如何处理错误的?开发者如何处理错误?经典玩笑场景下,一旦开发...}

程序开发初体验(代码片段)

{程序开发初体验一、预估与实际PSP2.1PersonalSoftwareProcessStages预估耗时(分钟)实际耗时(分钟)Planning计划2010?Estimate?估计这个任务需要多少时间2010Development开发370380?Analysis?需求分析(包括学习新技术)3020?DesignSpec?生成设计文档6020?...}

阿里云开发者体验平台--html入门(代码片段)

{阿里云开发者体验平台–HTML入门👉体验网址:https://developer.aliyun.com/adc/scenario/exp/bd1410dc7f5a42119cd3d0f9bad19c25文章目录阿里云开发者体验平台--HTML入门创建资源登录windowsserver连接成功安装并配置vscode创建HTML文件体验结束创建资...}

开发实践丨昇腾cann的推理应用开发体验(代码片段)

{...从而快速熟悉并掌握ACL(AscendComputingLanguage)基本开发流程。本文分享自华为云社区《基于昇腾CANN的推理应用开发快速体验(Python)》,作者:Tian}

flutter学习-flutter开发初体验(代码片段)

{Flutter学习-flutter开发初体验1.flutter项目的创建1.1创建方式1.2默认程序分析2.编写flutter代码2.1helloworld的实现2.2代码分析2.2.1runApp和Widget2.2.2Material设计风格2.3代码改进2.3.1改进界面样式2.3.2改进界面结构2.3.3进阶案例实现2.4代码重构2....}

haas700开发动手体验指南(代码片段)

{步骤一:断开开发板与PC的USB连接线,以启动或重启设备。 步骤二:在HaaS-Studio集成开发环境页面,按照下图所示的步骤创建测试体验工程。请注意,“工程名字”栏请按照test_demo的格式提供...}

.net客户端开发“粗体验”(代码片段)

{一、背景最近有个.net的sdk的开发功能,将之前java开发的迁移进去…好久没有写c#这个玩意,大学也没有类似的经历,而且是mac环境开发起来不是很舒畅,快捷键不是很熟悉…开发工具下载开发工具:https://docs....}

c#web开发之blazor体验(代码片段)

{前言先说结论:blazor做Web开发绝对好东西。对于我个人来说,有两个重要的原因:特别喜欢C#;特别不喜欢JavaScript;在了解到blazor居然可以使用c#做Web开发且完全可以不用编写JavaScript代码时,第一感受是...}

教您如何集成nearbyservice提升游戏体验,减少开发难度(代码片段)

{HMSNearbyService是HMSCore的一个重要特性,基于Wi-Fi/蓝牙底层技术,帮助游戏玩家快速发现周边的人,并在设备间自动建立低延时、高可靠、零流量的数据传输通道,提升游戏体验。一、NearbyService可以在以下方面为您的游戏提供更好...}

鸿蒙3.0应用开发体验(代码片段)

{鸿蒙os3.0发布以来,华为官方开始主推ets+arkui开发模式,逐渐抛弃java,为以后去安卓化做铺垫,但目前在笔者体验来看,仍需要大力完善,还有很长的路要走!什么是ets?ts是js的超集,而ets...}



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3