Skip to main content

developing-funboost-mixin

当需要为 funboost 创建 Consumer 或 Publisher 的 Mixin 扩展类时使用。触发场景:添加监控、熔断、限流、链路追踪等横切关注点,编写自定义前置/后置处理钩子。关键词:mixin, consumer_override_cls, publisher_override_cls, ConsumerMixin, 自定义消费者, hook, 拦截器, 熔断器, 监控, Prometheus, OpenTelemetry。

Source facts

Repository
ydf0509/funboost
Last source activity
August 4, 2026 at 14:03
Detected SKILL.md language
Chinese
Stars
892
Forks
165

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
developing-funboost-mixin
description
当需要为 funboost 创建 Consumer 或 Publisher 的 Mixin 扩展类时使用。触发场景:添加监控、熔断、限流、链路追踪等横切关注点,编写自定义前置/后置处理钩子。关键词:mixin, consumer_override_cls, publisher_override_cls, ConsumerMixin, 自定义消费者, hook, 拦截器, 熔断器, 监控, Prometheus, OpenTelemetry。
# 开发 Funboost Mixin 扩展 ## 概述 Mixin 可以向任意 funboost broker 添加横切关注点(监控、链路追踪、限流等),而无需修改 broker 本身。利用 Python 的 MRO 拦截方法。 **核心原则:** Mixin 重写特定方法,调用 `super()` 继续链路,配置存在 `user_options` 中。 ## 适用场景 - 为任务执行添加监控/指标 - 实现熔断器、限流器 - 添加 OpenTelemetry / Prometheus 埋点 - 自定义任务执行前后的处理逻辑 - 通过 MRO 组合多种行为 ## 已有 Mixin 参考 | Mixin | 用途 | 位置 | |-------|------|------| | `CircuitBreakerConsumerMixin` | 高错误率时停止消费 | `funboost/contrib/override_publisher_consumer_cls/` | | `MicroBatchConsumerMixin` | 微批消费(攒多条再处理) | `funboost/contrib/override_publisher_consumer_cls/` | | `PrometheusConsumerMixin` | 导出 Prometheus 指标 | `funboost/contrib/override_publisher_consumer_cls/` | | `PrometheusPublisherMixin` | 发布端 Prometheus 指标 | `funboost/contrib/override_publisher_consumer_cls/` | | `AutoOtelConsumerMixin` | OpenTelemetry 链路追踪 | `funboost/contrib/override_publisher_consumer_cls/` | | `AutoOtelPublisherMixin` | 发布端 OpenTelemetry 追踪 | `funboost/contrib/override_publisher_consumer_cls/` | | `PeriodicQuotaConsumerMixin` | 时间窗口配额限制 | `funboost/contrib/override_publisher_consumer_cls/` | | `AlertNotifierConsumerMixin` | 异常告警通知 | `funboost/contrib/override_publisher_consumer_cls/` | ## Mixin 模板 ```python from funboost.consumers.base_consumer import AbstractConsumer class MyConsumerMixin(AbstractConsumer): """ 继承 AbstractConsumer 是可选的(仅为 IDE 自动补全)。 不继承也能正常工作——运行时 mixin 通过动态多重继承合并 MRO。 """ def custom_init(self): super().custom_init() # 从 user_options 读取配置 opts = self.consumer_params.user_options.get("my_mixin_options", {}) self._threshold = opts.get("threshold", 10) self._counter = 0 def _submit_task(self, kw): """任务提交到线程池前的前置检查/限流""" if self._counter > self._threshold: print(f"[WARN] 已提交 {self._counter} 次,超过阈值 {self._threshold},可进行限流") super()._submit_task(kw) def _both_sync_and_aio_frame_custom_record_process_info_func( self, current_function_result_status, kw ): """ 每个任务执行后调用(同步和异步都会触发)。 注意:此钩子内禁止有 IO 阻塞操作(如 HTTP 请求、数据库写入), 否则会拖慢消费速度。如需 IO 操作,请用 _frame_custom_record_process_info_func (仅同步触发)或异步钩子配合 simple_run_in_executor。 """ super()._both_sync_and_aio_frame_custom_record_process_info_func( current_function_result_status, kw ) if current_function_result_status.success: self._counter = 0 # 成功时重置计数 else: self._counter += 1 ``` ## 使用方式 ```python from funboost import boost, BoosterParams, BrokerEnum @boost(BoosterParams( queue_name="monitored_task", broker_kind=BrokerEnum.REDIS_ACK_ABLE, consumer_override_cls=MyConsumerMixin, user_options={ "my_mixin_options": { "threshold": 100, } }, )) def my_task(x): return x * 2 ``` ## 关键重写点 ### 前置钩子 | 方法 | 调用时机 | 用途 | |------|----------|------| | `_submit_task(kw)` | 任务进入线程池前 | 限流、熔断、配额检查 | | `_before_start_consuming_message_hook()` | 消费者启动时(一次性) | 初始化连接、注册指标 | ### 后置钩子 | 方法 | 调用时机 | 用途 | |------|----------|------| | `_both_sync_and_aio_frame_custom_record_process_info_func` | 每个任务执行后(仅 CPU 操作) | 计数器、状态更新 | | `_frame_custom_record_process_info_func` | 每个任务执行后(同步线程中,允许 IO) | 写数据库、HTTP 调用 | | `_aio_frame_custom_record_process_info_func` | 每个任务执行后(异步协程中,允许 IO) | 异步写数据库 | **三种后置钩子的选择原则:** - `_both_sync_and_aio_frame_custom_record_process_info_func(self, current_function_result_status, kw)` **禁止 IO 阻塞**。在任务框架的核心路径上调用(同步/异步统一入口),适合纯内存操作(计数器递增、状态标记)。 - `_frame_custom_record_process_info_func(self, current_function_result_status, kw)` **允许同步 IO**。在同步消费模式(threading/gevent/eventlet)下的并发池工作线程中调用(与任务执行同线程),适合写数据库、发 HTTP 请求等阻塞操作。不会阻塞拉取消息的调度线程,但长时间 IO 会占用 worker 降低有效并发。 - `_aio_frame_custom_record_process_info_func(self, current_function_result_status, kw)` **允许异步 IO**。在异步消费模式(`concurrent_mode=ASYNC`)下作为协程调用,适合 `await` 异步数据库写入。 ```python class MonitorMixin(AbstractConsumer): def custom_init(self): super().custom_init() self._total = 0 self._failures = 0 def _both_sync_and_aio_frame_custom_record_process_info_func( self, current_function_result_status, kw ): """纯内存操作 — 禁止 IO""" super()._both_sync_and_aio_frame_custom_record_process_info_func( current_function_result_status, kw ) self._total += 1 if not current_function_result_status.success: self._failures += 1 def _frame_custom_record_process_info_func( self, current_function_result_status, kw ): """同步 IO 允许 — 如写数据库、发告警""" super()._frame_custom_record_process_info_func( current_function_result_status, kw ) if not current_function_result_status.success: import requests requests.post("http://alert.example.com/notify", json={ "queue": self.queue_name, "error": str(current_function_result_status.exception), "total": self._total, }) async def _aio_frame_custom_record_process_info_func( self, current_function_result_status, kw ): """异步 IO 允许 — 异步消费模式下使用""" await super()._aio_frame_custom_record_process_info_func( current_function_result_status, kw ) if not current_function_result_status.success: import aiohttp async with aiohttp.ClientSession() as session: await session.post("http://alert.example.com/notify", json={ "queue": self.queue_name, "error": str(current_function_result_status.exception), }) ``` ### 执行包裹 | 方法 | 调用时机 | 用途 | |------|----------|------| | `_run(kw)` | 同步任务执行 | 链路追踪 Span、计时 | | `_async_run(kw)` | 异步任务执行 | 异步链路追踪 | ## 配置规范 将 mixin 专属配置放在 `user_options` 的命名空间 key 下: ```python user_options={ "circuit_breaker_options": { "failure_threshold": 5, "recovery_timeout": 60, }, "my_custom_mixin_options": { "my_key": "my_value", }, } ``` 这样防止多个 mixin 的配置键冲突。 ## 组合多个 Mixin ```python class CombinedMixin(CircuitBreakerConsumerMixin, PrometheusConsumerMixin): """MRO 确保两个 mixin 的方法都能执行""" pass @boost(BoosterParams( queue_name="combined_task", consumer_override_cls=CombinedMixin, user_options={ "circuit_breaker_options": {"failure_threshold": 5}, }, )) def my_task(x): ... ``` 两个 mixin 都能正常工作,因为它们都调用了 `super()` — MRO 正确串联。 ## 异步兼容 如果后置钩子涉及 IO 操作: ```python from funboost.concurrent_pool.async_helper import simple_run_in_executor class MyAsyncAwareMixin(AbstractConsumer): def _frame_custom_record_process_info_func(self, status, kw): """同步版本(含 IO)""" super()._frame_custom_record_process_info_func(status, kw) self._save_to_db(status) async def _aio_frame_custom_record_process_info_func(self, status, kw): """异步版本 — 通过 executor 复用同步逻辑""" await super()._aio_frame_custom_record_process_info_func(status, kw) await simple_run_in_executor( self._frame_custom_record_process_info_func, status, kw ) ``` ## 常见错误 | 错误 | 修正 | |------|------| | 重写时忘记调 `super()` | 除抽象方法外始终调用 super() | | `user_options` 键名扁平化 | 应放在 mixin 专属的嵌套 key 下 | | 只重写 `_run` 不重写 `_async_run` | 必须同时处理同步和异步路径 | | 到处写 try/except 防御 | 让异常正常抛出——funboost 处理重试 | | 不继承导致无 IDE 补全 | 继承 `AbstractConsumer` 获取自动补全(运行时可选) | | 多 mixin 组合时 MRO 冲突 | 确保所有 mixin 中一致调用 super() | ## Publisher Mixin 示例 ```python from funboost.publishers.base_publisher import AbstractPublisher class MyPublisherMixin(AbstractPublisher): def _publish_impl(self, msg: str): """拦截发布,添加日志/指标""" self._log_publish(msg) super()._publish_impl(msg) def _after_publish(self, publish_msg_context): super()._after_publish(publish_msg_context) self._record_publish_metric() ``` ## 参考代码位置 - 已有 mixin:`funboost/contrib/override_publisher_consumer_cls/` - 基础 consumer 类:`funboost/consumers/base_consumer.py` - 基础 publisher 类:`funboost/publishers/base_publisher.py` - 教程:`funboost_all_docs_and_codes.md` 4.21b 章节 ## 相关 Skill - `developing-funboost-broker` — 新增消息中间件 - `funboost-observability` — 监控、链路追踪与告警
View on GitHub