基础
AMQP
AMQP,即Advanced Message Queuing Protocol
,一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。
基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。
消息队列
MQ 全称为Message Queue
, 消息队列。是一种应用程序对应用程序的通信方法。应用程序通过读写出入队列的消息(针对应用程序的数据)来通信,而无需专用连接来链接它们。
消息传递指的是程序之间通过在消息中发送数据进行通信,而不是通过直接调用彼此来通信。队列的使用除去了接收和发送应用程序同时执行的要求。
在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。
安装
在使用 RabbitMQ 之前,你需要在你的本地安装 RabbitMQ Server 端,但是在安装 RabbitMQ Server 之前,你还需要安装 erlang 。
我的本地系统是 Windows 10,所以你只需要去 erlang 官方下载对应的安装包即可。
在安装完成后,还需要配置环境变量到 PATH 中,验证安装成功命令:
1 | erl |
版本简介
RabbitMQ 3.8.8
Windows 10
erlang V11.0
RabbitMQ 介绍
基础概念介绍
- Message
消息由消息头和消息体组成。消息体是不透明的,而消息头则由一系列的可选属性组成,这些属性包括routing-key(路由键)、priority(相对于其他消息的优先权)、delivery-
该消息可能需要持久性存储)等。 - Publisher
消息的生产者,也是一个向交换器发布消息的客户端应用程序。 - Exchange
交换器,用来接收生产者发送的消息并将这些消息路由给服务器中的队列。
Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型的Exchange转发消息的策略有所区别 - Queue
消息队列,用来保存消息直到发送给消费者。它是消息的容器,也是消息的终点。一个消息可投入一个或多个队列。消息一直在队列里面,等待消费者连接到这个队列将其取走。 - Binding
绑定,用于消息队列和交换器之间的关联。一个绑定就是基于路由键将交换器和消息队列连接起来的路由规则,所以可以将交换器理解成一个由绑定构成的路由表。Exchange 和Queue的绑定可以是多对多的关系。 - Connection
网络连接,比如一个TCP连接。 - Channel
信道,多路复用连接中的一条独立的双向数据流通道。信道是建立在真实的TCP连接内的虚拟连接,AMQP 命令都是通过信道发出去的,不管是发布消息、订阅队列还是接收消息,这些动作都是通过信道完成。因为对于操作系统来说建立和销毁 TCP 都是非常昂贵的开销,所以引入了信道的概念,以复用一条 TCP 连接 - Consumer
消息的消费者,表示一个从消息队列中取得消息的客户端应用程序。 - Virtual Host
虚拟主机,表示一批交换器、消息队列和相关对象。虚拟主机是共享相同的身份认证和加
密环境的独立服务器域。每个 vhost 本质上就是一个 mini 版的 RabbitMQ 服务器,拥有
自己的队列、交换器、绑定和权限机制。vhost 是 AMQP 概念的基础,必须在连接时指定,
RabbitMQ 默认的 vhost 是 / 。 - Broker
表示消息队列服务器实体
消息流程
AMQP模型中,消息在producer中产生,发送到MQ的exchange 上,exchange 根据配置的路由方式发到相应的Queue 上,Queue 又将消息发送给consumer ,消息从queue 到consumer 有push 和pull 两种方式。
消息队列的使用过程大概如下:
- 客户端连接到消息队列服务器,打开一个channel 。
- 客户端声明一个exchange ,并设置相关属性。
- 客户端声明一个queue ,并设置相关属性。
- 客户端使用routing key ,在exchange 和queue 之间建立好绑定关系。
- 客户端投递消息到exchange 。
exchange 接收到消息后,就根据消息的key 和已经设置的binding ,进行消息路由,将消息投递到一个或多个队列里。
exchange 也有几个类型,完全根据key 进行投递的叫做Direct 交换机,例如,绑定时设置了routing key 为”abc” ,那么客户端提交的消息,只有设置了key 为”abc” 的才会投递到队列。
常用命令
启动监控管理器:rabbitmq-plugins enable rabbitmq_management
关闭监控管理器:rabbitmq-plugins disable rabbitmq_management
启动rabbitmq:rabbitmq-service start
关闭rabbitmq:rabbitmq-service stop
查看所有的队列:rabbitmqctl list_queues
清除所有的队列:rabbitmqctl reset
关闭应用:rabbitmqctl stop_app
启动应用:rabbitmqctl start_app
用户和权限设置
添加用户:rabbitmqctl add_user username password
分配角色:rabbitmqctl set_user_tags username administrator
新增虚拟主机:rabbitmqctl add_vhost vhost_name
将新虚拟主机授权给新用户:rabbitmqctl set_permissions -p vhost_name username “.*” “.*” “.”(后面三个””代表用户拥有配置、写、读全部权限)
Exchange类型
RabbitMQ目前共四种交换器类型:direct、fanout、topic、headers。headers 交换器和 direct 交换器完全一致,但性能差很多,用的比较少,所以只介绍三种类型
Direct Exchange:
这种模式根据路由键(routing key)去匹配Bindings中的 binding key,如果完全一致,就发送消息到对应QueueFanout Exchange:
这种模式是常见的发布订阅模式,发消息方式类似于子网广播,队列只要绑定到对应的Exchange,生产者发送消息过来,有绑定的队列都能接收消息Topic Exchange:
这种模式和Direct exchange有点像,不过Direct exchange是完全匹配,这种匹配方式是,先将路由键、bindings键根据点号隔开,# 表示匹配 0 个或多个单词, *表示匹配一个单词
Demo 展示
https://github.com/vgbhfive/SpringBootDemo/tree/master/rabbitmqdemo
基础组态
基础参数配置
RabbitMQ 基本上都带有默认的内置设置,所以在一些基础的场景下就已经够用了,所以当你需要在一些特别的场景下使用时,需要更改RabbitMQ 的配置。
大多数配置都是在rabbitmq.conf 文件中配置,大多数都是位于/etc/rabbitmq/rabbitmq.conf 位置。
如果你实在是找不到对应的位置时,可以使用 rabbitmq-diagnostics status 命令。
在rabbitmq.conf 配置文件之外,你还会遇见另一个配置文件就是advanced.config ,这个配置文件采用的Erlang 经典配置,仅在必要的时候可以使用,一般建议都是使用rabbitmq.conf 配置文件。
文件位置
每个RabbitMQ 节点都有许多的文件和目录来加载配置,然而这些文件和目录的位置是可以修改的。
在配置环境变量和目录时,尽量不要使用特殊字符,比如、?、、!、[、]、{}、} 等字符。
另外在修改了对应的文件和目录后,请求包RabbitMQ 节点还依旧拥有权限访问对应的资源。
日志
日志在检查问题或者检查系统的运行状态时是非常重要的。
日志文件名称:
1 | log.file=Rabbit.log |
日志文件目录:
1 | log.dir=/data/log/rabbit.log |
日志级别:
1 | log.level=info |
禁用日志文件:
1 | log.file=false |
日志写入
RabbitMQ节点始终会附加到日志文件,因此会保留完整的日志历史记录。默认情况下,Loger 不会执行日志文件轮换。
设置控制文件输出的日志文件旋转:
1 | log.file.rotation.date # 旋转时间 |
日志写入到控制台:
1 | log.console=true |
服务日志
在基于systemd 的Linux 发行版上,可以使用journalctl –system 检查系统服务日志。
1 | journalctl --system | grep Rabbitmq |
模式的导入与导出
定义存储在内部数据库中,并在所有群集节点之间复制。集群中的每个节点都有其自己的所有定义副本。当定义的一部分更改时,将在单个事务中的所有节点上执行更新。这意味着在实践中,可以从任何群集节点导出定义并获得相同的结果。因此可以将定义导出到文件中,然后导入到另一个集群中或用于模式备份。
使用rabbitmqctl 导出模式:
1 | #不需要启用管理插件,RabbitMQ 3.8.2中的新增功能 |
导入模式:
1 | #不需要启用管理插件,RabbitMQ 3.8.2中的新增功能 |
在版本3.8.6 之后不需要再导入模式,只需要在配置文件中配置好对应的配置之后,重新启动即可。
1 | #RabbitMQ 3.8.6中的新功能。 |
虚拟主机
RabbitMQ 是一个多用户的系统,在你说知道的连接、交换、连接、绑定、用户权限、策略等一系列的东西都是属于虚拟主机,你可以将它理解为Nginx 中的服务模块。另外还有不同的一点在于RabbitMQ 的虚拟主机是通过Rabbitmqctl 或者HTTP API 创建或者删除的。
创建虚拟主机
使用Rabbitmqctl 创建虚拟主机five1,示例:
1 | rabbitmqctl add_vhost five1 |
使用HTTP API 创建虚拟主机five2:(这里使用了curl 进行发送链接)
1 | curl -u userename:pa$sw0rD -X PUT http://rabbitmq.local:15672/api/vhosts/five2 |
删除虚拟主机
使用Rabbitmqctl 删除虚拟主机five1,示例:
1 | rabbitmqctl delete_vhost five1 |
使用HTTP API 删除虚拟主机five2:(这里使用了curl 进行发送链接)
1 | curl -u userename:pa$sw0rD -X DELETE http://rabbitmq.local:15672/api/vhosts/five2 |
限制虚拟主机
设置最大连接数:
1 | rabbitmqctl set_vhost_limits -p vhost_name '{"max-connections": 256}' |
正值:限制次数。0: 无限制。 负值:取消限制。
配置最大队列数:
1 | rabbitmqctl set_vhost_limits -p vhost_name '{“ max-queues”:1024}' |
正值:限制次数。负值:取消限制。
心跳机制
如果消费者进程挂掉了(channel关闭, connection关闭,或者tcp连接丢失), 没有发回确认信息, RMQ将认为消息没有被处理完, 将重新排队等待分配。
网络故障很多种,有时很微妙(比如,丢包比率和高)。 分布式的tcp连接采取适中的时间(比如Linux默认配置大约11分钟),方便操作系统检测。AMQP 0-9-1提供heartbeat(心跳)特性来确保应用服务层及时发现已崩溃的连接(和完全无相应的peers)。 心跳机制也能保证进程不被某些网络设备给杀掉。心跳包每半个超时时间发送一次。 丢失了两个心跳包, 连接被认为不可抵达。 不同的客户端有不同的提示, 但tcp连接都会被关闭。 当客户端检测到RMQ节点不可抵达(根据心跳判定), 它需要重新连接(到服务器)。
认证和授权
监控
在我经历的大多数系统中,都不是很重视关于中间件的监控这块的内容,因此在生产出现问题时,很难及时、有效的找到问题。
RabbitMQ 在3.8 版本之前,都是依赖自己的管理监控页面来实现的,这对于生产环境来说,有很大的不便行并且存在一定的安全隐患。
但是在RabbitMQ 3.8 版本之后,官方强烈推荐使用Prometheus 和 Grafana 来搭建一套监控系统。
基础架构和内核指标
运行在RabbitMQ 节点或应用的所有主机上应收集以下指标:
- CPU 统计信息
- 内存使用情况
- 虚拟内存统计信息
- 磁盘I/O
- 挂载上用于节点数据目录的可用磁盘空间
- beam.smp 中文件描述符和最大系统限制
- TCP 连接状态
- 网络吞吐量
- 网络延迟
监测频率
许多监视系统会定期轮询其监视的服务。这样做的频率因工具而异,但通常是由管理员配置的。同时频繁的轮询可能会对受监视的系统产生负面影响。
在开发、测试、UAT 环境中,建议的度量标准间隔为15 秒,如果需要接近实时的监测效果,也请不要将时间设置为小于5 秒,这样轮询监测条件的影响会小一点。
但是在生产环境下,建议将度量标准间隔为30 ~ 60 秒之间,其中Promethues 对于API 的设置有效时间为15 秒一次。
管理界面和外部监控软件
RabbitMQ 有自带的管理界面和HTTP API ,这些API 公开了许多的信息,主要是关于节点、连接、队列、消息速率等的指标信息。
安装RabbitMQ Prometheus Plugin
将下载的插件拷贝到RabbitMQ的插件目录,rpm形式安装的RabbitMQ的插件目录位于/usr/lib/rabbitmq/plugins下。1
2
3
4
5accept-0.3.3.ez
prometheus-3.4.0.ez
prometheus_httpd-2.1.4.ez
prometheus_process_collector-1.1.0.ez
prometheus_rabbitmq_exporter-v3.6.12.1.ez同时启用插件:
1
2
3
4
5rabbitmq-plugins enable accept
rabbitmq-plugins enable prometheus
rabbitmq-plugins enable prometheus_httpd
rabbitmq-plugins enable prometheus_rabbitmq_exporter
rabbitmq-plugins enable prometheus_process_collector重启RabbitMQ,访问 http://localhost:15672/api/metrics 可以得到RabbitMQ Exporter 暴露的metrics 了。
配置Promethues
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15- job_name: 'rabbitmq'
metrics_path: /api/metrics
static_configs:
- targets:
- 192.168.1.3:15672
labels:
instance: s3
- targets:
- 192.168.1.4:15672
labels:
instance: s4
- targets:
- 192.168.1.5:15672
labels:
instance: s5Grafana配置
下载Grafana Dashboard
https://raw.githubusercontent.com/deadtrickster/prometheus_rabbitmq_exporter/master/priv/dashboards/RabbitMQErlangVM.json。
将上面的dashboar 导入后需要做一些修改,加入host 变量,并修改各个图表的PromQL 加入host 变量作为查询条件,通过下拉列表选择查看不同rabbitmq 节点的Dashboard 。
Rabbitmqadmin HTTP API命令行工具
这个命令行管理工具需要Rabbitmqadmin 插件的支持,使用这个可以执行一些基于WebUI 的相同操作,并且这个插件可能对于自动化任务比较方便。同时这只是一个专门的HTTP 客户端,尽量不要用自己从自己的程序中调用Rabbitmqadmin 。
Rabbitmqadmin 不能替代rabbitmqctl 或者rabbitmq-plugins 。
rabbitmqadmin和RabbitMQ HTTP API 的兼容性一致,需要相同的版本才可以适配!
通过Rabbitmqadmin 可以获取的内容:
- 列出交换,队列,绑定,虚拟主机,用户,权限,连接和通道
- 显示概述信息
- 声明和删除交换,队列,绑定,虚拟主机,用户和权限
- 发布并获取消息
- 关闭连接并清除队列
- 导入和导出配置
示例
exchanges 列表:
1
rabbitmqadmin -V test list exchanges
获取队列列表,其中包含详细信息
1
rabbitmqadmin -f long -d 3 list queues
用其他用户连接其他虚拟主机
1
rabbitmqadmin -H myserver -u simon -p simon list vhosts
定义一个交换exchange
1
rabbitmqadmin declare exchange name=my-new-exchange type=fanout
连接
渠道是RabbitMQ 中一个很重要的概念,所以这部分我们有必要了解一下。
RabbitMQ支持多种协议:
- 具有扩展功能的AMQP 0.9.1
- AMQP 1.0 (尽管和上面的协议名称一致,但是他两确实是不同的协议)
- MQTT 3.1.1
- STOMP 1.0 ~ 1.2
基础
RabbitMQ支持的所有协议都是基于TCP的,并假定存在长期连接(每个协议操作不会打开新连接)以提高效率。一个客户端库连接使用单个TCP连接。为了使客户端成功连接,目标RabbitMQ节点必须允许在特定协议特定端口上的连接。
客户端连接并成功通过RabbitMQ节点进行身份验证之后,它可以发布和使用消息,定义拓扑并执行协议中提供的,由客户端库和目标RabbitMQ节点支持的其他操作。
由于连接本来就应该长期存在,所以客户端通常通过注册订阅并传递(推送)消息给他们而不是轮询来消耗消息。
当不再需要连接时,应用程序必须关闭它们以节省资源。未能做到这一点的应用程序有最终耗尽其目标资源节点的风险。
操作系统对单个进程可以 同时打开多少个TCP连接(套接字)有一个限制。该限制对于开发和某些QA环境通常是足够的。 必须将生产环境配置为使用更高的限制,以支持更多的并发客户端连接。
协议的区别
具有扩展功能的AMQP 0.9.1
AMQP 0.9.1 提供了一种通过单个TCP 连接进行多路复用的方法,这意味可以在同一个连接之上打开多个“轻量级连接”的通道,通过这些通道就可以进行对应的协议操作。
一个具有相同ID(编号)的通道被多次打开,向客户端发送错误后,连接将关闭。AMQP 1.0
AMQP 1.0 提供了一种通过单个TCP 连接进行多路复用的方法,这样应用程序可以在单个连接上打开多个称为会话的“轻量级连接”。然后,应用程序设置一个或多个链接来发布和使用消息。
在AMQP 1.0中,大多数错误属于会话错误或链接错误。会话错误是不可恢复的,导致检测到该错误的对等方接收的所有操作都将被丢弃,直到会话终止。链接错误仅限于特定链接。由于可以在不影响链接会话的情况下附加和重新附加链接,因此实际上,应用程序可以在更正根本原因后(如果可能)重试失败的操作。MQTT 3.1.1
MQTT 3.1.1 连接遵循上述流程。MQTT 支持可选身份验证。使用它时,RabbitMQ 使用一组预配置的凭据。
在MQTT 3.1中,服务器使用有限的方式将错误传达给客户端。主要方法是关闭客户端的TCP连接。这为开发人员提供了很少的上下文和有限的可见性。这是MQTT 3.1设计的基本限制。STOMP 1.0 ~ 1.2
STOMP连接遵循下面流程。
在STOMP中,服务器通过发送错误帧 并关闭TCP连接来传达错误。该框架将在消息字段中包含一条错误消息。
连接生命周期
客户端连接RabbitMQ,必须首先打开连接。此过程涉及多个步骤:
- 应用程序配置它使用的客户端库以使用某个连接端点(例如主机名和端口)。
- 该库将主机名解析为一个或多个IP 地址。
- 该库将打开与目标IP地址和端口的TCP 连接。
- 服务器接受TCP 连接后,执行特定于协议的协商过程。
- 然后,服务器对客户端进行身份验证。
- 客户端现在可以执行操作,每个操作都涉及服务器的授权检查。
监控
当前打开的客户端连接数和连接打开/关闭率是应监视的系统的重要指标。常见的问题主要有:
- 连接泄漏
- 高连接率
连接泄露是指应用程序反复打开连接而不关闭它们,或者至少仅关闭其中一些连接的情况。
连接泄漏最终会耗尽文件句柄的节点(或多个目标节点),这意味着任何新的入站客户端,同级或CLI 工具连接都将被拒绝。并发连接数量的增加也增加了节点的内存消耗。
当一个系统的新打开连接率始终很高并且其关闭连接率始终很高时,据说该系统具有很高的连接交换率。这就说明应用程序使用的连接都是非常的短暂,连接交换率比较高的情况下,还是需要去检查一下TCP 堆栈,避免资源耗尽。
资源使用
每个连接都会消耗目标RabbitMQ节点上的内存和一个文件句柄。
连接的TCP 缓冲区使用了大部分内存。它们的大小可以随着减小,从而以显著降低连接吞吐量为代价,从而节省每个连接的内存消耗。
RabbitMQ节点可以打开的最大文件句柄数受内核限制,并且必须提高以支持大量连接。
支持大量连接
由于连接消耗资源,因此要维持大量并发连接,就需要减少资源消耗或提供更多的资源或节点。实际上,这两个选项可以结合使用。
1 | #将间隔设置为60秒 |
TLS
客户端连接可以使用TLS加密。TLS也可以用作身份验证客户端的其他或主要方式。
流量控制
发布消息的连接可能会超过系统的极限,这很可能是繁忙的队列和执行复制的队列。发生这种情况时,将流控制应用于发布连接。这样仅使用消息的连接不受应用于发布者的流控制的影响。
对于使用自动确认消息的模式,很有可能在连接和通道写入TCP 连接时就会得到流量控制。
通道Channel
前面有写连接的部分,所以建议应该先学会连接的部分,再来学通道,毕竟没有连接就没有通道。
某些程序需要与服务器进行多个连接,但是又不希望有多个TCP 连接,所以AMQP 0.9.1 协议可以在同一个TCP 连接上进行多通道复用。
客户端执行的每个协议操作都在通道上发生。特定通道上的通信与另一通道上的通信完全分开,因此每种协议方法还带有一个通道ID(又称通道号),该整数是代理和客户端都使用该整数确定该方法用于哪个通道的。
通道仅存在于连接的上下文中,而不是单独存在的。关闭连接后,其上的所有通道也将关闭。
对于使用多个线程/进程进行处理的应用程序,很常见的是为每个线程/进程打开一个新通道,而不在它们之间共享通道。
渠道生命周期
应用程序在成功连接后会立即打开通道,然后会自动分配一个通道ID给新建的通道。
但通道不在需要使用时,应该及时关闭通道,并将资源回收。
通道异常
常见错误示例:
- 重新生命队列或者将不匹配的属性进行交换,将会抛出406 PRECONDITION_FAILED 异常。
- 用户访问权限不足的资源,将会抛出403 ACCESS_REFUSED 异常。
- 绑定不存在的队列或者不存在的交互,将会抛出404 NOT_FOUND 异常。
- 使用不存在的队列或者使用不存在的交换,将会抛出404 NOT_FOUND 异常。
- 从声明连接之外的连接使用独占队列,将会抛出405 RESOURCE_LOCKED 异常。
通道监测常见问题:
- 通道泄漏,通道泄漏是指应用程序重复打开通道而不关闭通道,或者至少关闭其中一些通道的情况。
- 高渠道流失率,当一个系统的新打开通道的速率始终很高,而关闭通道的速率始终很高时,则据说该系统具有较高的通道流失率。这通常意味着应用程序使用寿命短的通道,或者由于通道级异常而经常关闭通道。
最大连接数
客户端和服务器在连接时协商可以同时在一个连接上打开的最大通道数。该值对于RabbitMQ和客户端库都是可配置的。
1 | #同一连接上不能再打开100个通道 |
CLI Tools
消费者连接服务器的连接及通道数
1
2
3
4rabbitmqctl list_connections name channels -q
# => name channels
# => 127.0.0.1:52956 -> 127.0.0.1:5672 10
# => 127.0.0.1:52964 -> 127.0.0.1:5672 33查看通道信息
1
2
3
4
5
6
7
8
9rabbitmqctl list_channels -q
# => pid user consumer_count messages_unacknowledged
# => <rabbit@mercurio.3.815.0> guest 0 0
# => <rabbit@mercurio.3.820.0> guest 0 0
# => <rabbit@mercurio.3.824.0> guest 0 0
# => <rabbit@mercurio.3.828.0> guest 0 0
# => <rabbit@mercurio.3.832.0> guest 0 0
# => <rabbit@mercurio.3.839.0> guest 0 0
# => <rabbit@mercurio.3.840.0> guest 0 0
事件交换插件(event exchange plugin)
客户端连接服务器、使用通道、使用队列等,使用者和系统的其他部分进行交互都会生成事件。而这些对于监控和监测来说,是一个很好的切入点。
rabbitmq-event-exchange 是一个插件,使用内部事件并将其重新发布到主题交换,从而将事件公开给客户端(应用程序)。
激活rabbitmq-event-exchange ,不需要配置,直接激活即可。
1 | rabbitmq-plugins enable rabbitmq_event_exchange |
事件Events
- 队列、交换和绑定事件
- queue.deleted
- queue.created
- exchange.created
- exchange.deleted
- binding.created
- binding.deleted
- 连接和通道事件
- connection.created
- connection.closed
- channel.created
- channel.closed
- 消费者事件
- consumer.created
- consumer.deleted
- 策略、参数事件
- policy.set
- policy.cleared
- parameter.set
- parameter.cleared
- 虚拟主机事件
- vhost.created
- vhost.deleted
- 用户相关事件
- user.authentication.success
- user.authentication.failure
- user.created
- user.deleted
- user.password.changed
- user.password.cleared
- user.tags.set
- 权限事件
- permission.created
- permission.deleted
- 插件事件
- shovel.worker.status
- shovel.worker.removed
- 联盟事件
- federation.link.status
- federation.link.removed
使用Wireshark流量捕获
Wireshark 2.0 包含对AMQP 流量检查和分析的增强支持。可以剖析(解析,可视化,过滤)AMQP 0-9-1 和AMQP 1.0 流量,包括AMQP 0-9-1 Errata 和RabbitMQ Extensions。
Wireshark 2.0 与tcpdump、libpcap 具有相同的基础内容,可用于检查在服务器环境中获取的pcap 流量捕获文件。
网络
分布式
个人备注
此博客内容均为作者学习所做笔记,侵删!
若转作其他用途,请注明来源!