1. 概述
本文先在普通场景下生产者发送一条消息,消费者接受此条消息,然后通过wireshark进行抓包,对抓的包进行详细的分析。
2. 背景
3.1. 本文测试的环境
RabbitMQ的IP地址是10.240.89.147 生产者和消费者的IP地址都是10.240.80.99
3.2. 测试的代码
本文的代码和之前博客的代码相似,这里略
相关的代码内容如下:
生产者代码:NoPublisherConfirmSend.java
消费者代码:PublisherConfirmRecv.java
测试代码:
PublisherConfirmTest.java
发送端先发送1条消息,消费者接收消息
// 发送端
executorService.submit(() -> {
NoPublisherConfirmSend.execute(rabbitmq_host, rabbitmq_user, rabbitmq_pwd, routingKey,1);
});
Thread.sleep(5* 100);
// 接收端
executorService.submit(() -> {
PublisherConfirmRecv.execute(rabbitmq_host, rabbitmq_user, rabbitmq_pwd, routingKey);
});
Thread.sleep(5* 100);
4. 生产者发送消息的包分析
4.1. 所有包的截图
下方对包进行详细描述
4.2. 109-110帧 : TCP的建立连接的三次握手
TCP的建立连接的三次握手,关于TCP的基本信息可以参考之前的文章
4.3. 112-113帧:RabbitMQ的客户端告诉RabbitMQ自己使用的协议及版本
112帧:RabbitMQ的客户端告诉RabbitMQ自己使用的协议及版本
113帧:TCP应答信令:表示服务端告诉发送端已经收到这之前的包
4.4. 114 - 122:RabbitMQ服务端和客户端建立连接,并约定参数
114帧 Connection.Start:RabbitMQ告诉客户端通信的协议和版本、SASL认证机制(详细见)、语言环境以及RabbitMQ的版本信息和支持能力
117帧 Connection.Start-Ok :客户端带上连接使用的帐号和密码、认证机制、语言环境、客户的信息以及能力
118帧 Connection.Tune:RabbitMQ服务端和客户端开始进行参数协商
119帧 Connection.Tune-Ok: 客户端要么接受服务端过来的参数,要么将这些值变低,在发送给服务端
120帧 Connection.Open vhost=/ :RabbbitMQ客户端打开一个连接,并请求设置vhost值
121帖 TCP应答
122帖 Connection.Open-Ok:RabbitMQ服务端对vhost进行验证,如果成功,则返回如下此信息
4.5. 123 - 124:创建通道
123帧 Channel.Open:客户端打开一个新通道
124帧Channel.Open-Ok:RabbitMQ服务端回复新通道准备完毕
4.6. 125 - 126帧: 创建Exchange
125帧 Exchange.Declare 客户端向RabbitMQ声明一个Exchange
126帧 Exchange.Declare-Ok:RabbitMQ收到请求后,如果发现同名的exchange存在且属性相同,则返回如下包,否则抛出异常
4.7. 127帧 Basic.Publish 客户端开始发送消息
在这里客户端只管发送消息,而不关心消息是否正确到达RabbitMQ
4.8. 128 - 132 帧:关闭通关,关闭连接,回收 资源
128 帧 Channel.Close:客户端请求关闭通道
129帧 ACK应答
130帧 Channel.Close-Ok:RabbitMQ关闭通关,并应答
131帧 Connection.Close:客户端请求关闭连接
132帧 Connection.Close-Ok:RabbitMQ关闭连接,并应答
4.9. TCP四次挥手关闭连接
最后是TCP四次挥手关闭连接,但是这里不是标准的四次挥手,可能是会话双方关闭顺序异常引起的问题
4.10. 总结如下
5. 消费者接收消息的包分析
5.1. 所有包的截图
和生产者通话大部分相同,以下部分不同
消费者比生产者少了发送消息部分
消费者比生产者多了声明队列、队列绑定到交换机、消费消息部分
下面只列出不同的地方
5.2. 367 - 368帧 声明队列
367帧Queue.Declare: 客户端向RabbitMQ服务端声明队列
368帧 Queue.Declare-Ok:RabbitMQ创建队列成功并返回信息给客户端
5.3. 369-370:队列绑定到交换机
369帧Queue.Bind: 客户端向RabbitMQ服务端要求将队列绑定到指定交换机
370帧 Queue.Bind-Ok:RabbitMQ绑定成功并返回信息给客户端
5.4. 371-372帧: 消费者接收消息
371帧 Basic.Consume 客户端设置要消费的队列
372帧 Basic.Consume-Ok RabbitMQ服务端向客户端推送消息
以上是一次接收一个消息,也可以同一个包同时接收多个消息
5.5. 整个流程如下
代码
上文的详细代码主要如下:
生产者代码: NoPublisherConfirmSend.java
消费者代码:PublisherConfirmRecv.java
测试代码:PublisherConfirmTest.java的方法 publisherconfirm_noPublisherConfirmSend()
所有的详细代码见
github代码,请尽量使用tag v0.14,不要使用master,因为master一直在变,不能保证文章中代码和github上的代码一直相同