太坑了!RabbitMQ+PHP开发的辛酸经历

news2024/9/17 7:16:59

博主介绍:全网粉丝10w+、CSDN合伙人、华为云特邀云享专家,阿里云专家博主、星级博主,51cto明日之星,热爱技术和分享、专注于Java技术领域
🍅文末获取源码联系🍅
👇🏻 精彩专栏推荐订阅👇🏻 不然下次找不到哟

大家好,我是小寒,一个热爱编程和分享的开发者。今天我想和大家聊聊我在使用RabbitMQ和PHP进行开发时的一些辛酸经历。如果你也正在或者即将使用RabbitMQ和PHP,希望我的经历能对你有所帮助,避免走一些弯路。

在这里插入图片描述

初识RabbitMQ

刚接触RabbitMQ的时候,我对它的功能和优势充满了期待。作为一个强大的消息中间件,RabbitMQ可以处理高并发的消息传递,支持多种协议和编程语言,对于分布式系统和微服务架构有很大的帮助。

一开始,我兴致勃勃地下载并安装了RabbitMQ,按照官方文档配置了环境。安装过程相对顺利,我还庆幸这次可能不会遇到太多问题。然而,现实总是和想象有很大差距。

初步配置的挫折

RabbitMQ的配置文件非常复杂,参数繁多。我试图按照官方文档进行配置,但文档并不友好,对新手不够友善。尤其是在处理一些高级配置时,文档缺乏详细的解释和实例。

经过一番摸索,我终于成功启动了RabbitMQ服务,但连接时却遇到了问题。无论我怎么修改配置,总是报错。经过数小时的搜索和调试,终于发现是因为防火墙的问题。原来,RabbitMQ使用的端口没有被正确开放,这导致我的客户端无法连接上服务端。

与PHP的整合

解决了RabbitMQ的初步配置问题后,我开始着手将其与PHP进行整合。RabbitMQ提供了多种语言的客户端库,但对于PHP来说,官方推荐的是php-amqplib。这是一个功能强大的库,但文档依然是个大问题。

基本的消息发送和接收

在编写代码时,我遇到了无数的坑。例如,如何正确地处理连接失败、如何确保消息的持久化、如何处理消息的确认机制等。这些问题都需要大量的时间和精力去研究和解决。

以下是一个简单的例子,展示如何使用php-amqplib进行消息发送和接收:

<?php
require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Message\AMQPMessage;

// 建立连接
$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

// 声明队列
$channel->queue_declare('hello', false, false, false, false);

// 发送消息
$msg = new AMQPMessage('Hello World!');
$channel->basic_publish($msg, '', 'hello');

echo " [x] Sent 'Hello World!'\n";

$channel->close();
$connection->close();
?>

上面的代码展示了如何连接RabbitMQ服务器并发送一条消息。尽管看起来很简单,但在实际项目中,我们需要处理更多的细节。

消息接收端

<?php
require_once __DIR__ . '/vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;

$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$channel = $connection->channel();

$channel->queue_declare('hello', false, false, false, false);

echo " [*] Waiting for messages. To exit press CTRL+C\n";

$callback = function ($msg) {
    echo ' [x] Received ', $msg->body, "\n";
};

$channel->basic_consume('hello', '', false, true, false, false, $callback);

while ($channel->is_consuming()) {
    $channel->wait();
}

$channel->close();
$connection->close();
?>

上面的代码展示了如何从队列中接收消息,并使用回调函数处理接收到的消息。

性能调优的挑战

在解决了基本的功能问题后,我开始关注性能调优。毕竟,RabbitMQ的一个重要优势就是高性能。然而,在实际使用中,我发现性能并没有预期的那么好。

使用连接池

首先是连接池的问题。每次请求都重新建立连接会导致性能下降。我尝试使用连接池来复用连接,但在PHP中实现连接池并不是一件容易的事。以下是一个简单的连接池实现示例:

class ConnectionPool
{
    private $connections = [];
    private $maxConnections;

    public function __construct($maxConnections = 10)
    {
        $this->maxConnections = $maxConnections;
    }

    public function getConnection()
    {
        if (empty($this->connections)) {
            return new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
        } else {
            return array_pop($this->connections);
        }
    }

    public function releaseConnection($connection)
    {
        if (count($this->connections) < $this->maxConnections) {
            $this->connections[] = $connection;
        } else {
            $connection->close();
        }
    }
}

消息的处理速度

其次是消息的处理速度。在高并发的情况下,RabbitMQ的性能瓶颈很容易显现出来。我不得不深入研究RabbitMQ的工作原理,尝试各种优化手段,例如调整队列的预取数量、使用消息批量确认等,才最终解决了这个问题。

$channel->basic_qos(null, 10, null); // 设置预取数量

日志和监控的烦恼

在开发和调试过程中,日志和监控是必不可少的工具。然而,RabbitMQ的日志配置和查看也是一个让人头疼的问题。默认的日志级别和格式并不能满足我的需求,我不得不手动修改配置文件,增加自定义的日志记录。

监控方面,RabbitMQ提供了一个管理插件,可以通过Web界面查看各种统计信息。然而,这个插件默认没有启用,需要手动安装和配置。

rabbitmq-plugins enable rabbitmq_management

启用管理插件后,可以通过http://localhost:15672访问RabbitMQ管理界面。

实际项目中的血泪教训

在一个实际项目中,我们需要处理大量的订单消息,这对RabbitMQ和PHP的稳定性和性能提出了很高的要求。刚开始的一段时间,一切似乎都很顺利,但很快问题就暴露出来。

消息的丢失问题

尽管我们启用了消息持久化和确认机制,但在高并发的情况下,仍然有部分消息丢失。经过深入排查,发现是因为网络波动和服务器资源不足导致的。为了解决这个问题,我们不得不增加服务器资源,并对网络进行优化。

$msg = new AMQPMessage('Hello World!', ['delivery_mode' => 2]); // 持久化消息

消息的重复消费

在某些情况下,RabbitMQ会重复发送消息,导致同一个订单被处理多次。这不仅增加了系统的负担,还可能引发数据的一致性问题。为了解决这个问题,我们引入了幂等性设计,确保每条消息只会被处理一次。

$callback = function ($msg) {
    $orderId = $msg->body;
    if (!isProcessed($orderId)) {
        processOrder($orderId);
        markAsProcessed($orderId);
    }
};

性能瓶颈

随着业务量的增加,RabbitMQ和PHP的性能瓶颈逐渐显现出来。为了提高系统的吞吐量,我们进行了多次优化,包括调整RabbitMQ的配置、优化PHP代码、增加服务器资源等。

# 优化RabbitMQ配置
vm_memory_high_watermark.relative = 0.8
disk_free_limit.absolute = 500MB

总结

通过这次RabbitMQ+PHP开发的经历,我深刻体会到开发过程中遇到的种种困难和挑战。尽管RabbitMQ作为一款强大的消息中间件有很多优势,但在实际使用中也有很多需要注意的地方。希望我的经历能对大家有所帮助,避免走一些弯路。

最后,还是要提醒大家,在选择技术方案时一定要充分评估其优缺点,并做好充分的准备。不要盲目跟风,只有选择适合自己项目的技术,才能事半功倍。

我是小寒,感谢大家的阅读。如果你对RabbitMQ和PHP有任何疑问或者经验分享,欢迎在评论区留言,我们一起讨论,共同进步!

大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1957678.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

设计模式:模板方法模式:封装不变,扩展可变

目录 一、模板方法模式的定义与结构 二、模板方法模式的优点 三、模板方法模式的示例 示例一&#xff1a; 示例二&#xff1a; 四、总结 在软件开发中&#xff0c;设计模式是解决常见问题的可复用方案。其中&#xff0c;模板方法模式是一种行为型设计模式&#xff0c;它在不…

lora微调Qwen模型全流程

LoRA 微调 Qwen 模型的技术原理概述 LoRA&#xff08;Low-Rank Adaptation&#xff09;是一种用于大模型高效微调的方法。通过对模型参数进行低秩分解和特定层的微调&#xff0c;LoRA 能在保持模型性能的前提下显著减少训练所需的参数量和计算资源。接下来是对 LoRA 微调 Qwen…

Matlab编程资源库(9)数据插值与曲线拟合

一、一维数据插值 在MATLAB中&#xff0c;实现这些插值的函数是interp1&#xff0c;其调用格式为&#xff1a; Y1interp1(X,Y,X1,method) 函数根据X,Y的值&#xff0c;计算函数在X1处的值。X,Y是两个等长的已知向量&#xff0c;分别描述采样点和样本值&#xff0c;X1是一个向量…

【机器学习基础】初探机器学习

【作者主页】Francek Chen 【专栏介绍】⌈Python机器学习⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;依赖于强大的开…

vue项目引入live2d保姆级教程--web端、多种方法

一、自建live2d运行 1、选择SDK——live2d Cubism SDK &#xff08;1&#xff09;链接&#xff1a;Live2D Cubism SDK | Live2D Cubism 打开网站&#xff0c;它长这样&#xff1a; &#xff08;2&#xff09;选择web &#xff0c;到下个页面 &#xff08;3&#xff09;下…

Power Tower

Problem - D - Codeforces 牛客和codeforce都有 递归处理l,r&#xff0c;终点是lr && mod1 用扩展欧拉定理 // Problem: D. Power Tower // Contest: Codeforces - Codeforces Round 454 (Div. 1, based on Technocup 2018 Elimination Round 4) // URL: https://c…

Linux基础操作指令

Linux的操作特点&#xff1a;纯命令行&#xff08;虽然也有图形化界面&#xff0c;但主要是工程师使用&#xff0c;意义不大&#xff09; windows的操作特点&#xff1a;图形化界面&#xff08;也有纯命令行的形式&#xff0c;但其更贴近大众&#xff0c;命令行学习成本高&…

用Python打造精彩动画与视频1.2 安装Python和基本配置

1.2 安装Python和基本配置 在本章节中&#xff0c;我们将介绍如何在不同操作系统上安装Python&#xff0c;并进行基本配置&#xff0c;以便你能够顺利开始使用Python进行编程和多媒体创作。 1.2.1 Python的安装 Python有多个版本&#xff0c;目前主要使用Python 3版本。以下…

贪心加暴力枚举

数据范围只有 1 0 5 10^5 105所以我们可以直接暴力枚举&#xff0c;然后我们知道假操作一定是在最开始进行&#xff0c;至于加多少次我们可以直接枚举 class Solution { public:int minOperations(int k) {// 只可能先加后叠加if (k 1) return 0;int ans 0x7ffffff;int now…

Windows FreeCAD 导入ODA File Converter 插件

0. 背景 需要打开.dwg 格式的文件&#xff0c;AutoCAD 又要收费&#xff0c;所以使用法国的 FreeCAD&#xff0c; 安装完成打开.dwg 格式的文件时&#xff0c;出现问题如图所示&#xff1a; 1.下载插件 插件 ODA File Converter 网址 windows 插件在最下面&#xff1a; 2…

Android 性能优化(二):LeakCanary【用于分析代码是否存在内存泄漏】程序无响应

目录 1&#xff09;内存相关的五种常见问题 2&#xff09;内存溢出和内存泄漏 3&#xff09;LeakCanary是什么? 4&#xff09;LeakCanary如何使用&#xff0c;如何分析&#xff1f; 5&#xff09;LeakCanary监测的内容 提问&#xff1a;程序有时候很卡&#xff0c;经常会出现…

再论pg归档日志的设置

用过ORACLE的朋友&#xff0c;第一次设置 PG的归档参数&#xff0c;如下&#xff1a; 。。。 wal_level replica archive_mode on archive_command test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f 。。。 对于归档&#xff0c;还要用…

ConvGRU原理与开源代码

ConvGRU 1. 算法简介与应用场景2. 算法原理2.1 GRU基础2.2 ConvGRU原理2.2.1 ConvGRU的结构2.2.2 卷积操作的优点 2.3 GRU与ConvGRU的对比分析2.4 ConvGRU的应用 3. PyTorch代码 仅需要网络源码的可以直接跳到末尾即可 需要ConvLSTM的可以参考我的另外一篇博客&#xff1a;小白…

Halcon Blob分析

斑点分析的思路&#xff1a;在图像中&#xff0c;相关对象的像素可以通过其灰度值来识别。例如下图的组织颗粒。这些颗粒是凉的&#xff0c;而液体是暗的&#xff0c;通过选择明亮像素(阈值)&#xff0c;可以很容易地检测到颗粒。在需要应用中&#xff0c;这种简单的暗像素和亮…

成像光学:LCD的工作原理与结构图解

一、主流显示面板技术&#xff1a;LCD&#xff0c;OLED&#xff0c;MicroLED 二、主流显示屏的发展趋势 三、LCD堆叠结构&#xff08;以比较流行的TFT-LCD为例&#xff09; 沿光路方向介绍&#xff1a;背光&#xff0c;下偏光片&#xff08;polarizer&#xff09;&#xff0c;…

python实现图像分割算法2

python实现随机步行算法 随机步行算法数学模型Python 实现详细解释优缺点应用领域随机步行算法是一种常用于图像分割和图像分析的算法。它通过模拟随机游走来确定图像中每个像素的标签或类别。随机步行算法特别适合用于解决有种子标记的图像分割问题,其中用户提供一些初始标记…

【Python】基础语法(上)

本篇文章讲解以下知识&#xff1a; &#xff08;1&#xff09;初始编码 &#xff08;2&#xff09;输出 &#xff08;3&#xff09;初识数据类型 一&#xff1a;初识编码 在计算机中所有的数据本质上都是以0和1的组合来存储。 比如&#xff1a;在一个文件中有以下内容&am…

力扣SQL50 上级经理已离职的公司员工 一题双解

Problem: 1978. 上级经理已离职的公司员工 Code -- 方法 1 -- select e1.employee_id -- from employees e1 -- left join employees e2 -- on e1.manager_id e2.employee_id -- where e1.salary < 30000 -- and e1.manager_id is not null -- and e2.employee_id is…

SpringBoot 整合 Redis 实现验证码登录功能

一、整合Redis 在pom.xml中添加Redis相关依赖&#xff1b; <!--Spring Data Redis依赖配置--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>…

103.qt qml-最全Table新增下拉复制功能

在上篇文章102.qt qml-最全Table交互之多列固定、行列拖拽、自定义委托、标题交互使用教程_qt 表格控件 拖动列-CSDN博客 我们实现了大部分功能,所以本章实现下拉复制功能。 demo截图如下所示: 支持跨界复制,如果下拉的位置大于Table则会动画向下移动,具体可以参考视频链接…