You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Celery后Django Admin存对象时PostgreSQL报EOF错误排查

问题排查:Django Admin保存对象时PostgreSQL连接异常

现象说明

  • Django Admin保存对象时,PostgreSQL日志抛出错误:LOG: unexpected EOF on client connection with an open transaction
  • Django自身无任何日志或报错,但浏览器端出现错误(附图)
  • 此前功能完全正常,引入Celery定时任务后出现该问题

相关代码

signals.py

@receiver(post_save, sender=Posts)
def send_save_obj(sender, instance, created, **kwargs):
    # Translate to latin
    relates_to = instance
    title = to_latin(instance.title)
    author = instance.author
    ...
    # Creating latin obj
    if created and language == 'uz':
        def save_latn_obj():

            # create latin post
            post = PostUzLatn.objects.create(
                relates_to=relates_to,
                title=title,
                ...
            )
            post.tags.add(tags)
        transaction.on_commit(save_latn_obj)
        
    # Sending to telegram channel
  
    # Get the current time in the server's local time zone
    server_time = datetime.now()

    # Create a timezone object for Tashkent
    tashkent_tz = pytz.timezone('Asia/Tashkent')

    # Convert the server time to Tashkent time
    tashkent_time = server_time.astimezone(tashkent_tz)

    if 'tg' in instance.social_network \
        and publish <= tashkent_time:
        send_news(
            title=instance.title, 
        )

        # Update status after sending msg
        Posts.objects.filter(id=instance.id).update(is_sent=["is_sent_tg",])

    # Delete the cache key to invalidate the cache for this view
    cache.clear()

bot.py

def send_news(title):
    if tizer:
        bot.send_video(CHANNEL_ID, video=tizer, caption=title, supports_streaming=True)
    else:
        bot.send_photo(CHANNEL_ID, image, caption=title)

可能原因及修复方向

1. 耗时操作阻塞事务导致连接断开

send_news是同步执行的网络请求(调用Telegram API),如果API响应慢,会长时间阻塞当前请求的数据库事务。PostgreSQL会因客户端长时间无响应,主动断开未完成事务的连接,触发unexpected EOF错误。

修复:
把send_news改为Celery异步任务,避免在信号函数内同步阻塞:

# signals.py中替换原send_news调用
from .tasks import send_news_task
send_news_task.delay(title=instance.title)

新建tasks.py定义异步任务:

from celery import shared_task
from .bot import send_news

@shared_task
def send_news_task(title):
    send_news(title)

2. 事务内的更新操作引发冲突

Posts.objects.filter(id=instance.id).update(...)直接在post_save信号内执行,此时原事务尚未提交,可能引发锁冲突或连接生命周期异常。

修复:
把更新操作放到transaction.on_commit回调中,确保原事务提交后再执行:

# 替换原更新代码
def update_sent_status():
    Posts.objects.filter(id=instance.id).update(is_sent=["is_sent_tg",])
transaction.on_commit(update_sent_status)

3. 时区处理逻辑不规范

使用datetime.now()获取非时区感知时间,可能导致时间判断逻辑异常,间接引发事务流程问题。

修复:
改用Django提供的时区感知时间工具:

from django.utils import timezone

server_time = timezone.now()
tashkent_tz = pytz.timezone('Asia/Tashkent')
tashkent_time = server_time.astimezone(tashkent_tz)

4. Celery连接池干扰Django数据库连接

引入Celery后,worker的数据库连接池可能与Django的连接池发生冲突,导致连接泄漏或被提前回收。

检查配置:
确保Celery连接池参数合理,例如:

CELERY_BROKER_POOL_LIMIT = 10
CELERY_DB_REUSE_MAX = 50

内容的提问来源于stack exchange,提问作者mirodil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 13:07:32