RabbitMQ高可用架构涉及常用功能整理

news2024/9/24 3:28:00

RabbitMQ高可用架构涉及常用功能整理

  • 1. rabbitmq的集群模式
  • 2. 镜像模式高可用系统架构和相关组件
  • 3. rabbitmq的核心参数
    • 3.1 镜像策略
    • 3.2 新镜像同步策略
    • 3.3 从节点晋升策略
    • 3.4 主队列选择策略
  • 4. rabbitmq常用命令
    • 4.1 常用基础命令
      • 4.1.1 服务管理
      • 4.1.2 用户管理
      • 4.1.3 角色管理
      • 4.1.4 Vhost管理
      • 4.1.5 权限管理
      • 4.1.6 查看插件
      • 4.1.7 监控管理器
      • 4.1.8 应用管理
      • 4.1.9 队列管理
      • 4.1.10 集群管理
  • 5. 镜像队列原理
    • 5.1 镜像队列的数据流
      • 5.1.1 客户端连接主节点
      • 5.1.2 客户端连接从节点
    • 5.2 镜像队列的实现原理
      • 5.2.1 普通队列结构
      • 5.2.2 镜像队列结构
      • 5.2.3 GM(Guaranteed Multicast)
      • 5.2.4 消息的广播
  • 6. 疑问和思考
    • 6.1 broker 离线后重新上线表现
    • 6.2 队列的同步阻塞问题
  • 7. 参考文档

探讨rabbitmq的系统架构以及以及整体常用的命令和系统分析,本文主要探讨高可用版本的rabbitmq集群,并基于日常工作中的沉淀进行思考和整理。更多关于分布式系统的架构思考请参考文档关于常见分布式组件高可用设计原理的理解和思考


1. rabbitmq的集群模式

rabbitmq不同于kafka,rabbitmq的集群部署一共有3种模式

  • 单机模式(通常不会应用于生产)
    单机模式就比较简单了,就是我们当最初要接触RabbitMQ的时候,为了快速了解到它的使用方式和特性,可以从官网下载一个RabbitMQ包安装到本机,在线上环境中,是不会采用这种方式的。也根本不存在高可用性了。

  • 普通模式
    在普通模式中,会在N台机器上部署N个RabbitMQ,但是创建的Queue只会在其中的一台机器上,然后N个RabbitMQ直接同步Queue的元数据信息,通过这个元数据信息,就可以找到创建了Queue的那台机器的MQ实例,当有消费者要消费消息的时候,如果请求到了没有Queue的那个实例,那么它会通过Queue的元数据信息将请求转发到Queue所在的那个实例,并将数据拉取出来。
    这种方式其实并不是真正的分布式,因为每次随机请求到N个RabbitMQ实例上,最终都是需要从Queue所在的实例上获取数据,如果这个实例挂掉了,那么就出现了单点故障,使得整个普通集群模式无法对外提供服务。

那么这种方案并不会提升MQ的高可用性,但是可以比单机模式提高一定的吞吐量。不过Queue所在的MQ实例会是最终的性能瓶颈。

在这里插入图片描述

  • 镜像模式
    镜像集群模式跟普通集群模式相同的点就是N台机器上部署N个RabbitMQ实例。但是,与其不同的是,Queue和元数据信息都会存在于这N个RabbitMQ实例上,也就是说,每个RabbitMQ的节点上面都会存在全量的数据。当生产者每次发送消息到MQ集群的时候, 这个消息都会被同步到多个RabbitMQ实例上。
    这种模式的好处可以提高集群的高可用性,并且即使有机器宕机了,那么由于其他RabbitMQ的实例依然都保存有全量的数据,所以,也不会有什么问题。
    但是缺点是,由于MQ每次接收到消息后,都需要同步给其他实例节点,造成了很大的性能损耗,而且网络带宽的压力也会比较大。其次,由于每个节点都保存了全量的数据,所以,即使扩展机器,新加入的机器依然要保存全量数据,如果数据量很大的话,依然会存在超出机器所能承受的最大容量。

在这里插入图片描述

2. 镜像模式高可用系统架构和相关组件

rabbitmq的整体架构如下
在这里插入图片描述

相关核心的组件和角色作用如下

组件部署模式组件作用备注
producer客户端部署生产者创建消息消息一般可以包含 2 个部分: 消息体和标签
broker多机部署它负责接收、存储和管理消息数据接收和存储消息数据:rabbitmq broker接收来自producer发送的消息,并将这些消息存储在自己的磁盘上。
consumer客户端部署消费者连接到 RabbitMQ 服务器,订阅到队列。消费者消费一条消息时,只消费消息的消息体(payload)在消息路由的过程中,消息的标签会丢弃,存入到队列中的消息只有消息体,消费者只会消费到消息体,也就不知道消息的生产者是谁,当然消费者也不需要知道

镜像镜像队列本质上是一个HA模式的集群

  • Leader提供读写服务,数据写入需要从Leader开始,而后同步到Follower节点
  • Follower提供读服务

普通模式配置镜像模式,只需要进行如下配置即可。

# 所有队列exchangess都为镜像模式
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
Setting policy "ha-all" for pattern "^" to "{"ha-mode":"all"}" with priority "0" for vhost "/" ...

# # 所有队列queue都为镜像模式
rabbitmqctl set_policy --priority 0 --apply-to queues mirror_queue "^" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'

在这里插入图片描述

3. rabbitmq的核心参数

3.1 镜像策略

ha-modeha-params结果
exactlycount集群中队列副本的数量(主队列加上镜像)。count值为1表示一个副本:只有主节点。如果主节点不可用,则其行为取决于队列是否持久化。count值为2表示两个副本:一个队列主队列和一个队列镜像。换句话说:“镜像数=节点数-1”。如果运行队列主服务器的节点变得不可用,队列镜像将根据配置的镜像提升策略自动提升到主服务器。如果集群中的可用节点数少于count,则将队列镜像到所有节点。如果集群中有多个计数节点,并且一个包含镜像的节点宕机,那么将在另一个节点上创建一个新镜像。使用’ exactly ‘模式和’ ha-promot-on-shutdown ': ’ always '可能是危险的,因为队列可以跨集群迁移,并在停机时变得不同步。
all不设置队列跨集群中的所有节点镜像。当一个新节点被添加到集群中时,队列将被镜像到该节点。这个设置非常保守。建议设置的副本值为大多数节点N / 2 + 1。镜像到所有节点会给所有集群节点带来额外的负担,包括网络I/O、磁盘I/O和磁盘空间的使用。
nodes节点名称队列被镜像到节点名中列出的节点。节点名是在rabbitmqctl cluster_status中出现的Erlang节点名;它们的形式通常是“rabbit@hostname”。如果这些节点名中有任何一个不是集群的一部分,则不构成错误。如果在声明队列时列表中的节点都不在线,则将在声明客户机连接的节点上创建队列

3.2 新镜像同步策略

ha-sync-mode说明
manual这是默认模式。新队列镜像将不接收现有消息,它只接收新消息。一旦使用者耗尽了仅存在于主服务器上的消息,新的队列镜像将随着时间的推移成为主服务器的精确副本。如果主队列在所有未同步的消息耗尽之前失败,则这些消息将丢失。您可以手动完全同步队列,详情请参阅未同步的镜像部分。
automatic当新镜像加入时,队列将自动同步。值得重申的是,队列同步是一个阻塞操作。如果队列很小,或者您在RabbitMQ节点和ha-sync-batch-size之间有一个快速的网络,那么这是一个很好的选择。

3.3 从节点晋升策略

镜像队列主节点出现故障时,最老的从节点会被提升为新的主节点。如果新提升为主节点的这个副本与原有的主节点并未完成数据的同步,那么就会出现数据的丢失,而实际应用中,出现数据丢失可能会导致出现严重后果。
rabbitmq 提供了 ha-promote-on-shutdown,ha-promote-on-failure 两个参数让用户决策是保证队列的可用性,还是保证队列的一致性;两个参数分别控制正常关闭、异常故障情况下从节点是否提升为主节点,其可设置的值为 when-synced 和 always。

ha-promote-on-shutdown/ha-promote-on-failure说明
when-synced从节点与主节点完成数据同步,才会被提升为主节点
always无论什么情况下从节点都将被提升为主节点

这里要注意的是ha-promote-on-failure设置为always,插拔网线模拟网络异常的两个测试场景:当网络恢复后,其中一个会重新变为mirror,具体是哪个变为mirror,受cluster_partition_handling处理策略的影响。

例如两台节点A,B组成集群,并且cluster_partition_handling设置为autoheal,队列的master位于节点A上,具有全量数据,mirror位于节点B上,并且还未完成消息的同步,此时出现网络异常,网络异常后两个节点交互决策:如果节点A节点成为赢家,此时B节点内部会重启,这样数据全部保留不会丢失;相反如果B节点成为赢家,A需要重启,那么由于ha-prromote-on-failure设置为always,B节点上的mirror提升为master,这样就出现了数据丢失。

3.4 主队列选择策略

RabbitMQ中的每个队列都有一个主队列。该节点称为队列主服务器。所有队列操作首先经过主队列,然后复制到镜像。这对于保证消息的FIFO排序是必要的。通过在策略中设置 queue-master-locator 键的方法可以定义主队列选择策略,这是常用的方法。

queue-master-locator说明
min-masters选择承载最小绑定主机数量的节点
client-local选择客户机声明队列连接到的节点
min-masters随机选择一个节点

4. rabbitmq常用命令

4.1 常用基础命令

4.1.1 服务管理

启动: systemctl start rabbitmq-server 或 rabbitmq-service start
关闭: systemctl stop rabbitmq-server 或 rabbitmq-service stop
重启: systemctl restart rabbitmq-server
状态: rabbitmqctl status

4.1.2 用户管理

新增账号: rabbitmqctl add_user user-xx passwd-xx
删除用户: rabbitmqctl delete_user user-xx
所有用户: rabbitmqctl list_users
修改密码: rabbitmqctl change_password user-xx passwd-xx2
清除密码: rabbitmqctl clear_password {user-xx}

4.1.3 角色管理

用户角色分为5中类型:
none:无任何角色。新创建的用户的角色默认为 none。
management:可以访问web管理页面。
policymaker: 包含managerment所有权限,并且可以管理策略(Policy)和参数(Parameter)
monitoring: 包含management所有权限,并且可以看到所有链接、信道及节点相关的信息
administartor:包含monitoring所有权限,并且可以管理用户、虚拟机、权限、策略、参数等。(最高权限)
设置用户角色: rabbitmqctl set_user_tags zhaojigang administrator
设置多个角色: rabbitmqctl set_user_tags hncscwc monitoring policymaker
查看用户角色: rabbitmqctl list_users

4.1.4 Vhost管理

所有虚拟主机: rabbitmqctl list_vhosts
添加虚拟主机: rabbitmqctl add_vhost vhostname
删除虚拟主机: rabbitmqctl delete_vhost vhostname

4.1.5 权限管理

命令格式如下:rabbitmqctl set_permissions [-p vhost] {user} {conf} {write} {read}
查询所有权限:rabbitmqctl list_permissions  [-p  VHostPath]
查看用户权限:rabbitmqctl list_user_permissions user-xx
清除用户权限:rabbitmqctl clear_permissions [-p VHostPath] user-xx

4.1.6 查看插件

rabbitmq-plugins list

4.1.7 监控管理器

rabbitmq-plugins enable rabbitmq_management #启动
rabbitmq-plugins disable rabbitmq_management #关闭

4.1.8 应用管理

关闭应用:rabbitmqctl stop_app
启动应用:rabbitmqctl start_app

4.1.9 队列管理

查看所有队列:rabbitmqctl list_queues
清除所有队列:rabbitmqctl reset #需要先执行rabbitmqctl stop_app
强制清除队列:rabbitmqctl force_reset

4.1.10 集群管理

查看集群状态: rabbitmqctl cluster_status

查看集群报告:rabbitmqctl report
摘除节点: rabbitmqctl forget_cluster_node [--offline]
组成集群命令: rabbitmqctl join_cluster <clusternode> [--ram]
修改节点存储形式: rabbitmqctl change_cluster_node_type disc | ram
修改节点名称: rabbitmqctl rename_cluster_node oldnode1 newnode1 [oldnode2 newnode2] [oldnode3 newnode3...]

修改集群名称: rabbitmqctl set_cluster_name [cluster_name]

5. 镜像队列原理

5.1 镜像队列的数据流

5.1.1 客户端连接主节点

首先看生产者消费者直接与主节点连接的情况。该情况下队列的主副本所在的节点与生产者/消费者直接连接,效率较高。

在这里插入图片描述

  1. 生产者,消费者连接到 RabbitMQ 后,在 RabbitMQ 内部会创建对应的 Connection,Channel 进程。
  2. Connecton 进程从 socket 上接收生产者发送的消息后投递到 Channel 进程。
  3. 在 Channel 进程中,根据消息发送的 exchange 与消息的 routing-key,在内部数据库的路由表中,查找所有匹配的 Queue 的进程 PID,然后将消息投递到Queue 的进程中。在镜像队列的情况下,Channel 进程除了将消息发送给队列的 Leader 进程外,还会将消息发送给队列所有的 Follower 进程,而 Follower 进程都在远端节点上,因此这里就多了一次集群间的网络交互。
  4. 镜像队列的 Leader 进程收到消息后,需要将消息同步给所有的 Follower 进程。RabbitMQ 采用 GM(组播)算法实现,镜像队列中的 Leader 和所有 Follower 都会发送一次消息和接收一次消息,同时还会发送一次对消息的 ACK,和接收一次消息的 ACK。
  5. 综上所述,生产者发送一条消息,队列 Leader 进程所在节点会收到两次:一次是生产者发送的,一次是队列 Follower 进程发送的;同样也会将消息对外发送两次:一次是生产者对应的 Channel 进程将消息发送给队列的 Follower 进程;一次是队列的 Leader 进程进行广播同步将消息发送给 Follower 进程。此外,镜像队列的GM算法实现 ,每条消息还会有额外的确认消息在集群间进行发送。再结合图中的情况,一条消息从生产者到消费,Node1节点是2进3出的流量,Node2节点是2进1出的流量。

5.1.2 客户端连接从节点

在这里插入图片描述

如果生产者和消费者连接的是从节点,根据镜像队列的机制,只有主节点向外提供服务,所以镜像队列的消费需要由 node2 的队列消费消息。

一条消息从生产到消费,生产者消费者连接的节点是3进3出,队列master进程所在的节点是2进2出。

5.2 镜像队列的实现原理

5.2.1 普通队列结构

在这里插入图片描述

通常队列由两部分组成

  1. amqqueue_process ,负责协议相关的消息处理,即接收生产者发布的消息、向消费者投递消息、处理消息 confirm、acknowledge 等等
  2. backing_queue,它提供了相关的接口供 amqqueue_process 调用,完成消息的存储以及可能的持久化工作等。

5.2.2 镜像队列结构

在这里插入图片描述

镜像队列同样由这两部分组成,amqqueue_process 仍旧进行协议相关的消息处理,backing_queue 则是由 master 节点和 slave 节点组成的一个特殊的 backing_queue。Leader 节点和 Follower 节点都由一组进程组成,一个负责消息广播的 GM,一个负责对 GM 收到的广播消息进行回调处理。

在 Leader 节点上回调处理是 coordinator,在slave节点上则是 mirror_queue_slave。mirror_queue_slave 中包含了普通的 backing_queue 进行消息的存储,Leader 节点中 backing_queue 包含在 mirror_queue_master 中由 amqqueue_process 进行调用。

5.2.3 GM(Guaranteed Multicast)

GM 模块实现的是一种可靠的组播通信协议,该协议能够保证组播消息的原子性,即保证组中活着的节点要么都收到消息要么都收不到。
它的实现大致为:将所有的节点形成一个循环链表,每个节点都会监控位于自己左右两边的节点,当有节点新增时,相邻的节点保证当前广播的消息会复制到新的节点上 : 当有节点失效时,相邻的节点会接管以保证本次广播的消息会复制到所有的节点。在 Leader 和 Follower 上的这些 GM 形成一个组 (gm_group) ,这个组的信息会记录在 Mnesia 中。不同的镜像队列形成不同的组。操作命令从 Leader 对应的 GM 发出后,顺着链表传送到所有的节点。由于所有节点组成了一个循环链表, Leader 对应的 GM 最终会收到自己发送的操作命令,这个时候 Leader 就知道该操作命令都同步到了所有的 slave 上。

5.2.4 消息的广播

消息从 Leader 节点发出,顺着节点链表发送。在这期间,所有的 Follower 节点都会对消息进行缓存,当 Leader 节点收到自己发送的消息后,会再次广播 ack 消息,同样 ack 消息会顺着节点链表经过所有的 Follower 节点,其作用是通知 Follower 节点可以清除缓存的消息,当 ack 消息回到 Leader 节点时对应广播消息的生命周期结束。

下图为一个简单的示意图,A 节点为 Leader 节点,广播一条内容为 test 的消息。1 表示消息为广播的第一条消息;id=A表示消息的发送者为节点 A。右边是Follower 节点记录的状态信息。
在这里插入图片描述

为什么所有的节点都需要缓存一份发布的消息呢?
master发布的消息是依次经过所有slave节点,在这期间的任何时刻,有可能有节点失效,那么相邻的节点可能需要重新发送给新的节点。例如,A->B->C->D->A形成的循环链表,A为master节点,广播消息发送给节点B,B再发送给C,如果节点C收到B发送的消息还未发送给D时异常结束了,那么节点B感知后节点C失效后需要重新将消息发送给D。同样,如果B节点将消息发送给C后,B,C节点中新增了E节点,那么B节点需要再将消息发送给新增的E节点。

6. 疑问和思考

6.1 broker 离线后重新上线表现

基本的问题是,当 broker 离线并再次恢复时,它在镜像中的任何数据都将被丢弃。这是关键的设计缺陷。现在,镜像已恢复在线,但为空,管理员需要做出决定:是否同步镜像。“同步”意味着将当前消息从 leader 复制到镜像。

6.2 队列的同步阻塞问题

此时第二个致命的设计缺陷显露了出来。如果要同步消息,会阻塞整个队列,让这个队列不可用。当队列比较短的时候这通常不是什么问题,但当队列很长或者消息总大小很大的时候,同步将会需要很长时间。不仅如此,同步会导致集群中与内存相关的问题,有时甚至会导致同步卡住,需要重新启动。
默认情况下,所有镜像队列都会自动同步,但也有人用户不同步镜像。这样,所有新消息都将被复制,老消息都不会被复制,这将减少冗余,会使消息丢失的概率加大。
这个问题也引发滚动升级的问题,因为重新启动的 broker 将丢弃其所有数据,并需要同步来恢复全部数据冗余。

可以看出,镜像模式最大的问题就是性能问题。

7. 参考文档

暂无

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

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

相关文章

基于微信上海美食小程序系统设计与实现 研究背景和意义、国内外现状

博主介绍&#xff1a;黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者&#xff0c;CSDN博客专家&#xff0c;在线教育专家&#xff0c;CSDN钻石讲师&#xff1b;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程&#xff…

DiskGenius v4.30专业版下载

DiskGenius是一款专业级的数据恢复软件&#xff0c;算法精湛、功能强大&#xff0c;用户群体广泛&#xff1b;支持各种情况下的文件恢复和分区恢复&#xff0c;恢复效果好&#xff1b;文件预览、扇区编辑、加密分区恢复、Ext4分区恢复、RAID恢复等高级功能应有尽有&#xff0c;…

Redis篇之分布式锁

一、为什么要使用分布式锁 1.抢劵场景 &#xff08;1&#xff09;代码及流程图 &#xff08;2&#xff09;抢劵执行的正常流程 就是正好线程1执行完整个操作&#xff0c;线程2再执行。 &#xff08;3&#xff09;抢劵执行的非正常流程 因为线程是交替进行的&#xff0c;所以有…

leetcode1079:游戏玩法分析——求留存率

求留存率 题目描述题解 题目描述 表&#xff1a;Activity --------------------- | Column Name | Type | --------------------- | player_id | int | | device_id | int | | event_date | date | | games_played | int | --------------------- &#xff08;player_id&…

点云——噪声(代码)

本人硕士期间研究的方向就是三维目标点云跟踪&#xff0c;对点云和跟踪有着较为深入的理解&#xff0c;但一直忙于实习未进行梳理&#xff0c;今天趁着在家休息对点云的噪声进行梳理&#xff0c;因为预处理对于点云项目是至关重要的&#xff0c;所有代码都是近期重新复现过。 这…

中科大计网学习记录笔记(七):Web and HTTP

前言&#xff1a; 学习视频&#xff1a;中科大郑烇、杨坚全套《计算机网络&#xff08;自顶向下方法 第7版&#xff0c;James F.Kurose&#xff0c;Keith W.Ross&#xff09;》课程 该视频是B站非常著名的计网学习视频&#xff0c;但相信很多朋友和我一样在听完前面的部分发现信…

vulnhub通关-3 DC-3(含靶场资源)

文章目录 一、环境搭建1.环境描述靶场描述题目表述概括&#xff08;目标&#xff09; 2.靶场下载下载地址 3.环境启动 二、渗透靶场1.信息收集&#xff1a;寻找靶机IP分析nmap扫描存活主机 2.信息收集&#xff1a;服务和端口探测命令解析 3.访问Web4.探测框架版本号joomscan安装…

编码技巧——在项目中使用Alibaba Cloud Toolkit远程部署

背景 在新公司项目开发&#xff0c;当前项目为自建项目&#xff0c;意思是从开发到运维都需要自己负责&#xff0c;远程的服务器也是自己搭建的win操作系统&#xff1b; 之前在大厂工作时&#xff0c;一般提交代码之后&#xff0c;CICD流水线会自动的执行最新代码的拉取、构建打…

【iOS ARKit】3D人体姿态估计实例

与2D人体姿态检测一样&#xff0c;在ARKit 中&#xff0c;我们不必关心底层的人体骨骼关节点检测算法&#xff0c;也不必自己去调用这些算法&#xff0c;在运行使用 ARBodyTrackingConfiguration 配置的 ARSession 之后&#xff0c;基于摄像头图像的3D人体姿态估计任务也会启动…

SERVLET过滤器

SERVLET过滤器 全球因特网用户使用不同类型的Web浏览器访问应用服务器上存储的Web应用程序。每个浏览器根据对应的Web浏览器窗口中的设置显示应用程序中的信息。Web应用程序可能会有一些客户机的Web浏览器不支持的HTML标记或功能。这种情况下,应用程序在客户机的Web浏览器中可…

基于SpringBoot3的快速迭代平台

SpringBoot3的快速开发平台 前言一、技术栈二、项目结构三、总结 前言 MateBoot是一个基于SpringBoot3的快速开发平台&#xff0c;采用前后端分离的模式&#xff0c;前端采用Element Plus组件&#xff0c;后端采用SpringBoot3、Sa-token、Mybatis-Plus、Redis、RabbitMQ、Fast…

蓝桥杯Web应用开发-CSS3 新特性【练习三:文本阴影】

文本阴影 text-shadow 属性 给文本内容添加阴影的效果。 文本阴影的语法格式如下&#xff1a; text-shadow: x-offset y-offset blur color;• x-offset 是沿 x 轴方向的偏移距离&#xff0c;允许负值&#xff0c;必须参数。 • y-offset 是沿 y 轴方向的偏移距离&#xff0c…

项目02《游戏-09-开发》Unity3D

基于 项目02《游戏-08-开发》Unity3D &#xff0c; 本次任务是做抽卡界面&#xff0c;获取的卡片增添在背包中&#xff0c;并在背包中可以删除卡片&#xff0c; 首先在Canvas下创建一个空物体&#xff0c;命名为LotteryPanel&#xff0c;作为抽卡界面&#xff0c; …

软件价值10-数字时钟

这是一个数字时钟程序&#xff1a; # importing whole module from tkinter import * from tkinter.ttk import *# importing strftime function to # retrieve systems time from time import strftime# creating tkinter window root Tk() root.title(Clock)# This functio…

多路服务器技术如何处理大量并发请求?

在当今的互联网时代&#xff0c;随着用户数量的爆炸性增长和业务规模的扩大&#xff0c;多路服务器技术已成为处理大量并发请求的关键手段。多路服务器技术是一种并行处理技术&#xff0c;它可以通过多个服务器同时处理来自不同用户的请求&#xff0c;从而显著提高系统的整体性…

three.js 箭头ArrowHelper的实践应用

效果&#xff1a; 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"></div></div></el-main></…

复制和粘贴文本时剥离格式的5种方法(MacWindows)

您可能每天复制和粘贴多次。虽然它是一个非常方便的功能&#xff0c;但最大的烦恼之一就是带来了特殊的格式。从网络上获取一些文本&#xff0c;您经常会发现粘贴到文档中时&#xff0c;它保持原始样式。 我们将展示如何使用一些简单的技巧在不格式化的情况下复制和粘贴。 1.…

Zabbix 配置实时开通的LDAP认证-基于AD

介绍 本教程适用于6.4-7.0版本的Zabbix&#xff0c;域控&#xff08;AD&#xff09;使用Windows Server 2022搭建&#xff0c;域控等级为 2016。 域控域名为 songxwn.com 最终实现AD用户统一认证&#xff0c;统一改密&#xff0c;Zabbix用户自动添加。&#xff08;6.4之前不…

【远程通信系统】服务端初始化

服务器架构&#xff1a;libevent 线程池 数据库&#xff1a;MySQL 有两张表&#xff1a;chat_user和chat_group&#xff0c;分别保存用户信息和群信息 在线用户和群的保存&#xff1a; struct User {std::string name;//账号&#xff08;用户名struct bufferevent* bev;//客…

WordPress如何实现随机显示一句话经典语录?怎么添加到评论框中?

我们在一些WordPress网站的顶部或侧边栏或评论框中&#xff0c;经常看到会随机显示一句经典语录&#xff0c;他们是怎么实现的呢&#xff1f; 其实&#xff0c;boke112百科前面跟大家分享的『WordPress集成一言&#xff08;Hitokoto&#xff09;API经典语句功能』一文中就提供…