Loading

解决服务内部libreoffice 没反应问题

一个专门放celery worker的docker中,
在docker内部安装lireoffice 用于服务内部文件转换, 但是会出现:
d8362d2e-b77d-4454-947f-206997aec088

首先进入容器确认libreoffice 是否正常

docker exec -it docker_name /bin/bash
which soffice
soffice --version

如果都有显示,表示有安装

拿容器内部一个文件进行测试

time soffice --headless --convert-to html --outdir /tmp /path/to/file.xlsx

如果能正常转换,表示libreoffice进程正常

其他命令:
查看是否有残留进程

ps -ef | grep -E 'soffice|libreoffice'

杀死相关进程

pkill -f soffice
pkill -f libreoffice

查看当前并发配置
ps -ef | grep celery | grep nltb

当前worker配置

  celery -A app.celery worker -P $WORKER_CLASS -c 2 --loglevel $LOG_LEVEL \
    -Q nltb -n nltb_worker@%h &

由于设置并发数>1, 可能出现的原因有:
77067b3a-3964-4dff-afc1-0c340bd58ab4
987a711d-a080-4bc2-8699-2dd96ae618cf
868b3cc3-f91e-47ac-a5f2-32dba8f7f7f5

当前设计:
redis缓冲队列任务 -> 定时取出 -> 推送解析异步任务 -> libreoffice开始执行

经排查,存在两个问题
1.在推送异步任务前做了redis查重处理,并且check_task没有返回布尔值导致的。
2. 重复推送任务,导致两个worker都执行同样的任务,可能有多个任务同时对同一个文件进行处理导致阻塞(待验证,mock一下多线程下处理同一份文件)

class TBStructuredAsyncService:
	 self.check_task(tenant_id, content_id, task_id, file_id, kb_id)
	 # 开始推送异步任务

    def check_task(self, tenant_id, content_id, task_id, file_id, kb_id):
        # 判断当前任务是否完成
        current_time = datetime.datetime.now()

        content = db.session.query(Content).filter(
            Content.id == content_id,
            Content.tenant_id == tenant_id,
        ).first()
        task = db.session.query(ContentTask).filter(ContentTask.id == task_id).first()
        formatted_time = current_time.strftime("%Y-%m-%d %H:%M:%S")
        if task:
            logger.info(f"task_id:{task_id} task:{task.progress}")
            # 判断是否存在,若存在则出栈,不存在则返回
            if redis_client.exists(task.redis_key):
                redis_client.delete(task.redis_key)
            else:
                return
        if content and content.run != FileParseTaskStatus.DONE.value:
            logger.warning(
                f"=== 开始解析结构化数据 ===\n[{formatted_time}] file_id: {file_id}, kb_id: {kb_id}, task_id:{task_id} content_id: {content_id}")
        
		

但尽管添加返回布尔值,依然会出现重复推送的问题。因为定时扫描的频率太高了,第二次重复推送的速度比redis删除的速度还快。

因此添加原子锁

        lock_key = f"nltb:structured:start:{task_id}:{index}"
        lock_value = f"{content_id}:{file_id}"
        if not redis_client.set(lock_key, lock_value, nx=True, ex=STRUCTURED_START_LOCK_EXPIRE_SECONDS):
            logger.warning(f"跳过重复结构化解析投递: task_id={task_id}, content_id={content_id}, index={index}")
            return

        if not self.check_task(tenant_id, content_id, task_id, file_id, kb_id):
            return
posted @ 2026-06-04 14:29  踩坑大王的日记  阅读(14)  评论(0)    收藏  举报