mirrord 的 RabbitMQ 队列拆分(Queue Splitting)完整指南:从集群配置到消息过滤实战 开发工具云原生CLI【免费下载链接】mirrordRun any process, on your machine or in an AI agents environment, as if it were a pod in your Kubernetes cluster: real env vars, DNS, network, traffic.项目地址https://gitcode.com/gh_mirrors/mi/mirrord点击查看免费下载本文基于 mirrord 官方文档rabbitmq.md及仓库源码编写面向需要在 Kubernetes 中为 RabbitMQ 消费者配置 mirrord 队列拆分的开发者。读完本文你将掌握如何在集群中启用 RabbitMQ 拆分、如何用MirrordPropertyList声明 RabbitMQ 集群连接与队列属性、如何用MirrordSplitConfig声明被拆分的队列以及如何在 mirrord 配置中用message_filter/jq_filter精确控制哪些消息流向本地应用。为什么需要队列拆分如果你的应用从队列服务消费消息直接运行 mirrord 会让本地应用与集群中已部署的应用以及队友的 mirrord 会话竞争队列消息。mirrord 的队列拆分Queue Splitting解决的是哪些消息归部署应用、哪些消息归本地开发这一分发问题匹配过滤条件的消息会到达你的本地应用不匹配的消息则到达部署应用或匹配了队友过滤条件的本地应用。具体参见队列拆分总览。不加任何特殊配置本地应用与部署应用竞争消费使用copy_targetscale_down部署应用完全不消费本地应用独占队列见替换整个 Deployment使用队列拆分为相关目标配置拆分并在 mirrord 配置中定义消息过滤器精细控制消息去向。队列拆分目前支持 Amazon SQS、Apache Kafka、RabbitMQ、Google Cloud Pub/Sub、Azure Service Bus、NATSJetStream 与 core pub/sub、Redis Pub/Sub、Temporal 和 BullMQ。queue一词在不同服务中对应 topic、subscription、stream/subject、channel、task queue 等概念。版本要求通过MirrordSplitConfig进行队列拆分需要 mirrord operator3.170.0或更高版本、mirrord CLI3.221.0或更高版本。RabbitMQ 的 jq 过滤需要 operator3.201.0、CLI3.253.0。RabbitMQ 队列拆分的工作原理以一个从 RabbitMQ 队列消费消息的应用为例拆分的完整过程如下首个拆分会话启动operator 创建两个临时队列——一个给集群中部署的目标应用一个给用户本地应用。随后 operator 按照用户配置的过滤器将消息从原始队列路由到临时队列。第二个用户加入第二个用户对同一队列启动 mirrord 拆分会话时operator 再创建一个临时队列供第二个用户的本地应用使用并把新队列和第二个用户的过滤器一并纳入路由逻辑。过滤器冲突如果两个用户定义的过滤器同时匹配某条消息消息会被随机分配给其中一个用户。从源码结构看operator 为每个 RabbitMQ 拆分会话创建一个MirrordRMQSessionCRD 对象group 为queues.mirrord.metalbear.coversion 为v1alpha其状态机依次经过Starting、RegisteringFilters、Ready等阶段并在会话创建前就记录好所有需要清理的队列保证失败时也能完整回收见 mirrord/operator/src/crd/rabbitmq.rs。在集群中启用 RabbitMQ 拆分第一步在 Helm chart 中启用在 mirrord-operator 的 Helm values 中开启operator.rmqSplitting开关operator 的队列拆分开关统一为sqsSplitting、kafkaSplitting、rmqSplitting、gcpPubsubSplitting等默认false见仓库内 helm-values.md 的 Feature flags 小节。第二步集群声明MirrordPropertyList启用operator.rmqSplitting后集群中会注册一个新的 CustomResource 类型——MirrordPropertyList。operator 需要凭它连接你的 RabbitMQ 集群以便按过滤器消费并重新路由消息。MirrordPropertyList与消费者工作负载以及MirrordSplitConfig同命名空间但可以与 RabbitMQ broker 所在命名空间不同也可以放在 operator 的命名空间实现跨命名空间共享一份声明见跨命名空间共享 Property List。它的建模参考了 Pod 容器 spec 中的env/envFrom字段支持三种取值方式在properties中用value直接设置用valueFrom.configMapKeyRef或valueFrom.secretKeyRef引用 ConfigMap / Secret 中的单个 key用propertiesFrom下的configMapRef/secretRef引入 ConfigMap / Secret 的全部 key可选的prefix会作为每个 key 的前缀。⚠️ 注意用value设置properties时值必须始终是字符串——写value: 1而不是value: 1。完整的集群声明示例apiVersion: mirrord.metalbear.co/v1 kind: MirrordPropertyList metadata: name: meme-rmq-cluster namespace: meme spec: properties: - name: host value: meme-rmq.meme.svc - name: username valueFrom: configMapKeyRef: name: meme-rmq-config key: rmq_user - name: password valueFrom: secretKeyRef: name: meme-rmq-secret key: rmq_password propertiesFrom: - secretRef: prefix: client. name: meme-rmq-client-properties optional: true - configMapRef: name: meme-rmq-common-properties optional: true至少需要创建一个包含集群属性的MirrordPropertyList。 如果你的应用期望特定的队列属性如durable或x-queue-type这类 arguments可以创建一个携带这些队列声明属性的MirrordPropertyListapiVersion: mirrord.metalbear.co/v1 kind: MirrordPropertyList metadata: name: meme-quorum-queue namespace: meme spec: properties: - name: durable value: true - name: arguments.x-queue-type value: quorum集群连接属性Cluster Properties属性描述必填类型默认值url完整 AMQP 连接 URL如amqp://user:passhost:5672/vhost作为host的替代。任何显式设置的scheme、port、username、password或vhost都会覆盖从 URL 解析出的对应部分✓ ¹string (URI)—scheme连接使用的协议—amqp或amqpsamqphost消息 broker 的主机名或 IP✓ ¹string—portbroker 监听的网络端口—integer按scheme取 5671 或 5672username用于认证连接的凭据—string—password指定用户的密钥或密码—string—vhostbroker 内的逻辑隔离单元virtual host—string/sasl.mechanism握手期间使用的认证策略—amqplainanonymousexternalplain或rabbit-cr-demo—tls.crt用于客户端认证的公钥证书PEM 格式—string (PEM)—tls.key与客户端证书匹配的私钥PEM 格式—string (PEM)—ca-certificates.crt用于验证 broker 身份的 CA 证书PEM 格式—string (PEM)—client.*发送给 broker 的自定义元数据或属性—object / key-value pairs—¹ 需要提供url或host之一。当某一部分同时存在于url中并被单独设置为其属性时以单独属性为准。username和password始终必需——直接设置或包含在url中。队列声明属性Queue Declare Properties属性描述必填类型默认值durable为 true 时队列在 broker 重启后仍然存在—booleanfalseexclusive为 true 时队列只能被当前连接访问连接关闭时被删除—booleanfalseauto_delete为 true 时最后一个消费者取消订阅后队列自动删除—booleanfalsearguments.*队列声明中发送的自定义属性—object / key-value pairs—第三步提供应用上下文MirrordSplitConfig启用operator.rmqSplitting后集群还会注册一个新的 CustomResource 类型——MirrordSplitConfig。拥有 CRD 查看权限的用户可以用kubectl get crd mirrordsplitconfigs.queues.mirrord.metalbear.co验证其存在。在运行 RabbitMQ 拆分会话之前必须为目标创建MirrordSplitConfig它告诉 operator拆分哪些队列以及应用如何发现这些队列的名字。为命名空间meme中的 Deploymentmeme-app定义的示例apiVersion: queues.mirrord.metalbear.co/v1 kind: MirrordSplitConfig metadata: name: meme-app-split namespace: meme spec: targetRef: apiVersion: apps/v1 kind: Deployment name: meme-app queues: - id: meme-queue kind: rmq clientConfig: meme-rmq-cluster appConfig: queue: - env: INCOMING_MEME_QUEUE_NAME containers: - main - id: ad-queue kind: rmq clientConfig: meme-rmq-cluster appConfig: queue: - env: AD_QUEUE_NAME containers: - main上述MirrordSplitConfig的含义目标为命名空间meme中 Deploymentmeme-app里的容器main集群连接参数定义在同命名空间meme的meme-rmq-clusterMirrordPropertyList中查找顺序先目标/配置所在命名空间后 operator 命名空间容器消费两个 RabbitMQ 队列队列名分别从环境变量INCOMING_MEME_QUEUE_NAME和AD_QUEUE_NAME读取在 mirrord 配置中可分别用 IDmeme-queue和ad-queue引用这两个队列。关联已部署的消费者MirrordSplitConfig是命名空间级资源只能引用同命名空间中部署的消费者通过spec.targetRef指定目标工作负载apiVersion— Kubernetes 工作负载的 API 版本如apps/v1rollout 则用argoproj.io/v1alpha1kind— 工作负载类型。支持Deployment、StatefulSet、Rolloutname— 工作负载名称。描述被消费的队列spec.queues列表中的每一项描述工作负载消费的一个或多个 RabbitMQ 队列id— 任意队列 ID供开发者从 mirrord 配置中引用kind— 必须为rmq对应 config 中的queue_type: RMQ见 split_queues.rs 中QueueKind::Rmq的定义clientConfigRabbitMQ 必填— 包含 RabbitMQ 集群连接属性的MirrordPropertyList名称queueConfig可选— 包含临时队列的队列声明属性durable、队列类型或任意其他属性的MirrordPropertyList名称appConfig.queue— 应用如何发现队列名。每个条目可以使用env— 包含队列名的确切环境变量名envLike— 匹配环境变量名的正则volume— 从configMap卷挂载的文件中读取队列名volume.namevolume.file而不是环境变量。详见挂载配置文件中的队列名fallback— 变量不存在时的回退队列名。env 变量仍会被改写以指向临时队列valueSelector— 从变量值中提取队列名的选择器支持嵌套 key 与.[]遍历数组或对象值。当 env 变量保存的是 JSON 而非纯名称时很有用。不支持管道、函数等其他 jq 操作符valuePattern— 队列名嵌在更大字符串中时使用的正则。捕获组名为value的组否则取第一个组标记出作为名称的部分只有该部分会被替换为临时队列名周围文本保持不变containers— 限制到特定容器可选默认所有非基础设施容器。appConfig.exchange可选— 当应用从环境变量读取 exchange 名称时operator 会在那里注入一个假的 exchange 名使本地应用不会向真实 exchange 发布或绑定。结构与appConfig.queue相同。从源码结构看RmqQueueDetails结构体见 mirrord/operator/src/crd/rabbitmq.rs正是这些字段的落点cluster_properties、queue_properties可选与exchange_source外加被 flatten 的队列名来源SplitQueueNameDetails。⚠️ operator 只能读取消费者的环境变量前提是它们满足以下条件之一直接定义在工作负载的 Pod 模板中值由value或valueFromconfig map 引用给出或通过envFrom从 config map 加载。Drain timeout排水超时针对某个目标的最后一个会话结束后operator 会保留拆分的临时资源一段时间drain timeout以便新会话复用然后才销毁它不会等待未读消息先被消费完。设置单位作用域效果MirrordSplitConfig上的spec.drainTimeout秒单个 split覆盖集群级默认值drainTimeout行为未设置两者皆无最后一个会话一结束就销毁等同于00立即销毁。未读消息可能丢失N资源最多保留N秒然后销毁设置过滤器完整的过滤器参考queue_type、message_filter、jq_filter见为一次 mirrord 运行设置过滤器。RabbitMQ 使用queue_type: RMQ同时支持基于消息头的message_filter和基于整条消息的jq_filter。下面这个示例中本地应用将收到 RabbitMQ 队列中MirrordSplitConfig中以 IDmeme-queue描述的一个消息子集——所有收到的消息都带有一个包含mirrord-sessionalice的baggage消息头{ operator: true, target: deployment/meme-app/container/main, feature: { split_queues: { meme-queue: { queue_type: RMQ, message_filter: { baggage: .*mirrord-sessionalice.* } } } } }使用 jq 过滤message_filter只能按名称匹配单个消息头。当需要匹配消息体、或匹配事先不知道名字的消息头时改用jq_filter。jq 程序运行在如下 JSON 文档上{ headers: { baggage: mirrord-sessionalice }, properties: { content_type: application/json, message_id: 5f2c..., timestamp: 1755600000 }, payload: {\priority\:\high\} }headers— AMQP basic-properties 的 headers 表。始终存在可能为空properties— 其余携带值的 basic propertiescontent_type、content_encoding、delivery_mode、priority、correlation_id、reply_to、expiration、message_id、timestamp、type、user_id和app_id。发布者未设置的属性不会出现payload— 消息体。当程序输出true时消息匹配。要在消息体上过滤先用fromjson解析{ operator: true, target: deployment/meme-app/container/main, feature: { split_queues: { meme-queue: { queue_type: RMQ, jq_filter: .payload | fromjson | .priority \high\ } } } }上面的示例中本地应用只接收消息体是 JSON 对象且priority: high的消息消息体不是合法 JSON 的消息永远不会匹配。如果同一队列同时设置了message_filter和jq_filter消息必须同时满足两者。头部过滤先执行因此 jq 程序只会看到已经通过头部过滤的消息。从源码看实现细节过滤器如何从配置一路传递到 operator在 mirrord 配置层feature.split_queues支持对象形式以队列 ID 为 key和数组形式每个条目带queue_id字段两者在解析时统一为SplitQueuesConfig见 mirrord/config/src/feature/split_queues.rs。每个QueueSplit条目包含queue_id、queue_modesteal默认 /mirror、queue_type、message_filter、filter、jq_filter与payload_protobuf。配置校验QueueSplit::verify会拒绝message_filter与filter同时设置、编译失败的正则、无法编译的 jq 程序等错误。CLI 侧通过ConnectParams把rmq_splitsqueue ID → message_filter map与rmq_jq_filtersqueue ID → jq 程序编码进连接请求见 mirrord/operator/src/client/connect_params.rs使用可组合filter形态的条目则通过queue_filters参数传输。operator 侧所有 broker 共用一棵过滤器树MessageFilterAttribute/Metadata/AllOf/AnyOf见 mirrord/operator/src/crd/queue_filter.rs并写入MirrordRMQSession的queue_filters/queue_jq_filters字段。queue_modesteal 与 mirror默认steal模式下匹配的消息只发给本地应用部署应用永远看不到mirror模式下匹配消息同时发给本地应用和部署应用两边各处理一份副本Temporal不支持 mirror。RabbitMQ 与其余所有支持 jq 的 broker 一样均可使用 jq 过滤mirrord up还会自动生成任意字符串值包含mirrord-sessionsession key标记即匹配的通配 jq 过滤器其中 RabbitMQ 的元数据选择器是.headers。会话标识mirrord-key 消息头启用会话 key 头注入operator Helm values 的operator.injectSessionKeyHeader后operator 路由到你的会话的每条消息都会被盖上携带会话 key 的mirrord-key本地应用据此判断消息属于哪个 mirrord 会话。只有投递给会话的副本会被盖章部署应用收到的消息不会被修改。RabbitMQ 属于元数据通道型服务mirrord-key放在**消息头message header**中各服务的载体与位置对照见队列拆分总览。消息处理日志每条路由到 mirrord 会话的消息都会产生一条Message Processing功能日志包含会话 key、路由模式、队列/主题名以及 broker 提供的关联或追踪元数据。RabbitMQ 日志的queue_type值为rmq可记录的字段包括message_id、correlation_id、traceparent、tracestate、baggage与序列化后的message_properties部分疑似含密钥的属性名会被[REDACTED]打码详见 monitoring.md。跨命名空间共享连接声明MirrordPropertyList按名称被MirrordSplitConfig引用operator 依次在1目标工作负载所在命名空间即MirrordSplitConfig所在命名空间、2operator 安装所在命名空间中查找。一个 broker 服务多个团队时可以在 operator 旁只定义一次凭据供全集群复用目标命名空间中的同名列表优先级更高团队可借此覆盖共享配置。注意目标命名空间中存在但 operator 无法解析的列表会让会话失败而不是回退到 operator 命名空间详见队列拆分总览。从 MirrordWorkloadQueueRegistry 迁移MirrordWorkloadQueueRegistry已废弃由MirrordSplitConfig取代。现有资源出于向后兼容仍可继续工作但建议迁移。迁移细节与字段映射见迁移到 MirrordSplitConfigRabbitMQ 部分的核心映射如下MirrordWorkloadQueueRegistry已废弃MirrordSplitConfig新spec.consumer.name/workloadTypespec.targetRef.name/kind附带apiVersionspec.consumer.containerappConfig.queue[].containersspec.queues.keyspec.queues[].idqueueType: RMQkind: rmqclusterPropertiesclientConfigqueuePropertiesqueueConfignameSource.envVarappConfig.queue[].envnameSource.regexPatternappConfig.queue[].envLikefallbackNameappConfig.queue[].fallbacknamesFromJsonMap: trueappConfig.queue[].valueSelector: .[]exchangeSourceappConfig.exchange迁移步骤1按上表创建新的MirrordSplitConfig已有的MirrordPropertyList集群声明原样复用2启动一个会话验证消息按预期拆分3删除旧的MirrordWorkloadQueueRegistry。operator 接受新旧资源混合使用可以逐个工作负载迁移。赞分享开发工具云原生CLI【免费下载链接】mirrordRun any process, on your machine or in an AI agents environment, as if it were a pod in your Kubernetes cluster: real env vars, DNS, network, traffic.项目地址https://gitcode.com/gh_mirrors/mi/mirrord点击查看免费下载相关推荐MDX 查询语言 ANTLR v4 文法解析从 SELECT 语句到词法规则的完整指南MDX 查询语言 ANTLR v4 文法解析从 SELECT 语句到词法规则的完整指南 导读 本文围绕 grammars v4 仓库中的 MDXMultiD开发工具云原生CLIeslint-plugin-unicorn 规则详解require-array-sort-compare——强制为 Arraysort()/toSorted() 提供比较函数eslint plugin unicorn 规则详解require array sort compare——强制为 Array sort /toSorted开发工具云原生CLIHumanizer 完全指南用 .NET 库把字符串、枚举、日期与数量变成人类可读文本Humanizer 完全指南用 .NET 库把字符串、枚举、日期与数量变成人类可读文本 Humanizer 是一个面向 .NET 的文本人性化库专门把字符串开发工具云原生CLI上一篇【免费下载】 Arcade-plus重燃Arcaea谱面编辑之光下一篇Piping Server 使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考