多进程Apache/ModWSGI下Django进程间通信更新配置的方案咨询
针对Django+Apache多进程场景的轻量IPC方案
1. 利用ModWSGI内置的共享内存与进程通知
ModWSGI原生提供了跨进程的共享内存字典和进程通知机制,完全适配Apache/ModWSGI的部署场景:
- 用
mod_wsgi.processes.shared存储配置的版本号,作为变更标记 - 配置变更时,在触发信号的进程里递增版本号,再调用
mod_wsgi.processes.notify()通知所有进程 - 其他进程通过中间件在请求前置阶段检查版本号,若本地缓存版本低于共享内存版本,就重新拉取数据库配置并更新字段属性
示例代码思路:
# 配置更新中间件 from django.utils.deprecation import MiddlewareMixin import mod_wsgi class ConfigSyncMiddleware(MiddlewareMixin): def process_request(self, request): local_version = getattr(request, '_config_version', 0) shared_version = mod_wsgi.processes.shared.get('config_version', 0) if local_version < shared_version: # 从数据库拉取最新字段配置并更新verbose_name update_model_field_verbose_names() request._config_version = shared_version # 配置变更信号处理函数 def on_config_updated(sender, **kwargs): current_version = mod_wsgi.processes.shared.get('config_version', 0) mod_wsgi.processes.shared['config_version'] = current_version + 1 mod_wsgi.processes.notify()
2. 使用django-cacheops的事件广播
如果项目已经在用django-cacheops做ORM缓存,可直接利用它的跨进程事件广播能力:
- 缓存最新的字段配置,同时通过缓存失效事件触发所有进程更新
- 无需额外依赖,且缓存本身能减少数据库查询次数
示例代码思路:
# 监听缓存失效事件 from cacheops.signals import cache_invalidated def sync_field_config(sender, **kwargs): if kwargs.get('key') == 'field_label_config': update_model_field_verbose_names() cache_invalidated.connect(sync_field_config) # 配置变更时触发更新 def on_config_updated(sender, **kwargs): from django.core.cache import cache # 更新缓存中的最新配置 cache.set('field_label_config', fetch_latest_field_configs()) # 发送广播通知所有进程 from cacheops import invalidate_obj invalidate_obj('field_label_config')
3. 基于django-redis的Pub/Sub功能
若项目用Redis作为缓存,可直接借助Redis的发布订阅实现进程间通知:
- 每个Apache子进程启动时启动一个后台订阅线程,监听指定频道
- 配置变更时在频道发布消息,订阅线程收到后立即更新本地内存中的配置
示例代码思路:
# 进程启动时启动订阅线程 import threading import redis from django.conf import settings from django.apps import AppConfig def subscribe_config_updates(): r = redis.Redis.from_url(settings.CACHES['default']['LOCATION']) pubsub = r.pubsub() pubsub.subscribe('field_config_updates') for msg in pubsub.listen(): if msg['type'] == 'message': update_model_field_verbose_names() class ConfigAppConfig(AppConfig): name = 'config' def ready(self): # 每个子进程启动独立的订阅线程(守护线程不阻塞进程退出) threading.Thread(target=subscribe_config_updates, daemon=True).start() # 配置变更时发布消息 def on_config_updated(sender, **kwargs): r = redis.Redis.from_url(settings.CACHES['default']['LOCATION']) r.publish('field_config_updates', 'updated')
内容的提问来源于stack exchange,提问作者Cerin
相关产品推荐
相关产品推荐

