- 后端
- 前端
- 协同办公
- 即时通讯
- 企业应用
【免费下载链接】dootask
DooTask是一款开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具;同时消息功能使用非对称加密技术让你的沟通更安全。
本文面向 DooTask 部署管理员,系统梳理「打开任务列表 / 消息会话 / 仪表盘明显变慢、多人操作卡顿、CPU / 内存占用高」等性能问题的根因定位与解决方案。读完你可以掌握一套从量化观测(docker stats)到分层调优(全文搜索、MySQL、Swoole、Redis、nginx、硬件扩容)的完整实战流程,并理解为什么 DooTask 的 Swoole 常驻内存架构不能套用 PHP-FPM 时代的优化经验。
问题现象与排查前提
当 DooTask 出现以下现象时,基本都属于本文讨论的性能问题范畴:
- 打开任务列表、消息会话、仪表盘加载时间明显变长;
- 多人同时在线操作时整体卡顿、白屏或请求超时;
- 主机 CPU、内存长期高位,甚至出现 CPU 100%;
- 消息发送延迟、任务列表打开缓慢。
排查此类问题前需要两个前提:一是拥有部署主机的 root 权限,能够执行 docker 相关命令与修改配置文件;二是理解 DooTask 的运行时架构——它的后端并不是传统 PHP-FPM 短生命周期进程模型,而是基于 Swoole 的常驻内存协程模型(LaravelS 框架),因此很多 PHP-FPM 时代的优化经验(例如无脑调大pm.max_children)在这里不适用。
从部署形态看,DooTask 的 Docker 编排包含 php(Swoole 常驻进程)、nginx(反向代理与静态资源)、redis(缓存 / 队列 / Session)、mariadb(主数据库)和 appstore(应用商店容器),见 docker-compose.yml。性能问题的定位顺序也应当按这条链路逐层排查。
第一步:先量化,再动手
不要凭感觉调参。第一步永远是用数据定位瓶颈容器:
docker stats观察哪个容器吃满 CPU 或内存:
- php 容器吃满 → 进入 Swoole 进程模型调优(下文第三节);
- mariadb 容器吃满 → 进入 MySQL 慢查询排查(第二节);
- redis 容器内存逼近上限 → 进入 Redis 容量限制(第四节);
- nginx 容器连接数 / 带宽吃紧 → 进入反向代理优化(第五节)。
DooTask 官方对硬件的最低建议是 2 核 4G 以上(见 README_CN.md),正常规模建议 4 核 8G 起步。当活跃用户数超过 100 人后,建议给 MySQL 分配独立机器;超过 200 人时,建议给 MySQL / Redis 单独分配资源,避免多容器争抢同一台主机的 IO 与内存。
数据量大是首要根因:启用 Manticore 全文搜索
对绝大多数「越用越卡」的实例而言,真正的瓶颈往往不是硬件,而是消息、任务、文件等大表在百万级数据量下的检索能力。
DooTask 的全站搜索(全局搜索、消息搜索、任务搜索、文件搜索)默认依赖 Manticore 全文搜索服务,前提是必须在应用商店安装 search 插件(入口:AppStore → search)。只有安装后,索引与查询链路才会切换到 Manticore;否则系统会静默降级为 MySQLLIKE模糊查询。
这一点在源码中有明确的分支实现。例如消息搜索模块 app/Module/Manticore/ManticoreMsg.php 中,searchDialogs()会先判断Apps::isInstalled("search"),未安装时调用searchDialogsByMysql()走 MySQL 回退搜索;文件搜索模块 app/Module/Manticore/ManticoreFile.php 同样在未安装 Manticore 时降级到 MySQLLIKE。
MySQLLIKE无法利用倒排索引,百万级messages/tasks表上做模糊匹配会带来全表扫描和极高的 CPU 开销,这正是「消息发送延迟、任务列表打开慢」的直接来源。因此:
- 打开 AppStore,安装并启用 search 插件;
- 确认 Manticore 服务可达。Manticore 的主机与端口在 config/dootask.php 中配置:默认
SEARCH_HOST=search、SEARCH_PORT=9306(Manticore 的 MySQL 协议端口),可通过.env覆盖; - 等待索引同步。项目提供了一组 Manticore 同步命令与任务,例如 app/Console/Commands/SyncMsgToManticore.php、app/Console/Commands/SyncTaskToManticore.php 以及常驻同步任务 app/Tasks/ManticoreSyncTask.php,负责把业务数据持续写入 Manticore 索引。
注意:如果 search 插件未安装,仅靠调大机器配置无法根治搜索慢的问题;这也是本文「先检查数据量与大表检索」优先于「加 CPU / 内存」的原因。
MySQL 慢查询:开慢日志、按报告补索引
DooTask 自带数据库镜像已经默认开启了慢查询日志。在 docker/mysql/conf.d/docker.cnf 中可以确认:
slow_query_log=1 slow-query-log-file=/var/lib/mysql/mysql-slow.log long_query_time=3也就是说执行超过 3 秒的 SQL 都会被记录。排查时进入 mariadb 容器读取慢日志,例如:
docker exec dootask-mariadb-<APP_ID> tail -f /var/lib/mysql/mysql-slow.log拿到慢 SQL 后,按报告针对messages、tasks、project_task_users、web_socket_dialog_msg_reads这类高频大表补充联合索引(仓库迁移中已有大量索引优化先例,如 2024_03_17_160641_add_index_some_20240317.php、2025_12_26_000000_add_indexes_to_web_socket_dialog_msgs.php 可供参考)。
另一个 MySQL 关键参数是 InnoDB 缓冲池:
innodb_buffer_pool_size = 4096M该值决定 InnoDB 能在内存中缓存多少数据页,官方镜像默认 4G(docker.cnf)。对于数据量大、内存充足的机器,建议调到物理内存的 50% 左右;如果 MySQL 已拆到独立机器,则可按独立机器内存重新评估。另外注意 docker.cnf 中max_connections = 500、table_open_cache = 2048等连接与表缓存参数,当活跃用户增多导致连接耗尽时,也应同步检查。
Swoole 进程模型调优:worker_num 与 task_worker_num
DooTask 后端通过 LaravelS 把 Laravel 跑在 Swoole 常驻进程中(php 容器由 supervisor 拉起bin/laravels start,见 docker/php/php.conf 与 bin/auto)。核心进程参数集中在 config/laravels.php:
'reactor_num' => env('LARAVELS_REACTOR_NUM', swoole_cpu_num()), 'worker_num' => env('LARAVELS_WORKER_NUM', swoole_cpu_num()), 'task_worker_num' => env('LARAVELS_TASK_WORKER_NUM', swoole_cpu_num() * 2), 'max_request' => env('LARAVELS_MAX_REQUEST', 100000), 'dispatch_mode' => 2, 'enable_coroutine' => true,关键点:
worker_num默认等于 CPU 核数(swoole_cpu_num()),负责处理 HTTP 请求。多核机器上应确认该值确实生效、所有核都被用到;如果容器被限制在单核或核数探测异常,并发能力会大打折扣。task_worker_num默认是核数的 2 倍,负责处理异步任务(消息推送、通知、Manticore 同步等)。如果偏小,后台任务会积压,表现为「消息发送延迟、通知收不到」,此时需要按任务量调大task_worker_num。max_request默认 100000,即每个 worker 处理满 10 万请求后自动重启,用于规避常驻进程的内存泄漏累积。enable_coroutine => true表示启用 Swoole 协程,这也是「PHP-FPM 经验不适用」的根本原因:协程并发模型下,盲目增加进程数并不会线性提升吞吐,反而会加大内存与上下文切换开销。
这些参数均可通过.env中的LARAVELS_WORKER_NUM、LARAVELS_TASK_WORKER_NUM、LARAVELS_REACTOR_NUM、LARAVELS_MAX_REQUEST覆盖(参考 .env.docker 中LARAVELS_LISTEN_IP/LARAVELS_LISTEN_PORT的写法)。
改完任何 Swoole 相关配置,必须重启 PHP 服务才能生效:./cmd php restart(底层逻辑见 cmd 的restart_php(),通过supervisorctl restart php拉起常驻进程)。否则新参数不会加载,误以为调优生效而实际仍在旧配置下运行。
Redis 容量:防缓存撑爆
DooTask 的缓存、队列、Session 默认全部走 Redis(.env.docker:CACHE_DRIVER=redis、QUEUE_CONNECTION=redis、SESSION_DRIVER=redis)。docker-compose 中的 redis 容器 docker-compose.yml 默认没有 maxmemory 限制,大用户量下缓存与队列数据累积,会把 Redis 撑爆,进而拖垮整个系统。
建议为 Redis 显式设置容量上限与淘汰策略:
maxmemory 2gb maxmemory-policy allkeys-lrumaxmemory 2gb:按实际可用内存设定硬上限,防止 Redis 无界增长吃光内存;maxmemory-policy allkeys-lru:达到上限后按 LRU 淘汰最久未使用的键,保证热数据常驻、系统稳定。
由于 docker-compose 中的 redis 镜像没有挂载自定义配置文件,实际操作时可以在容器内通过redis-cli CONFIG SET临时调整,或自定义 redis.conf 挂载到/usr/local/etc/redis/redis.conf后重启容器(注意 redis_data 卷会持久化数据,配置调整后需同步保证重启不丢失)。
nginx 反代瓶颈
nginx 作为唯一入口负责静态资源与 WebSocket 转发(见 docker/nginx/default.conf)。如果确认 nginx 容器 CPU / 连接数吃紧,需要检查:
- worker 进程数与连接数:默认
nginx:alpine镜像配置较为保守,并发高时可在挂载的站点配置中调大worker_processes(建议等于核数)与worker_connections; - 静态资源 gzip / cache:
public/下存在大量前端静态资源(public/js、public/css),应开启 gzip 压缩与浏览器缓存(expires/Cache-Control),避免每次刷新都回源; - upstream 连接复用:default.conf 中已为 php 服务配置
keepalive 16与proxy_http_version 1.1,location @laravels与/ws均走该 upstream,若确认此处成为瓶颈,可适当调大 keepalive 数量。
注意/ws的 WebSocket 代理超时已设置为 3600s(default.conf),长连接场景下不应再人为缩短该超时。
硬件扩容与架构拆分
当软件层优化做完后仍不够,才考虑资源层扩容。优先级如下:
- 加 CPU / 内存(最简单):先在
docker-compose.yml中给 php / mariadb 服务合理分配资源,再考虑整机升级; - MySQL 拆到独立机器:用户超过 100 后,把 mariadb 容器迁移到独立主机,DooTask 通过
.env中的DB_HOST、DB_PORT、DB_DATABASE、DB_USERNAME、DB_PASSWORD连接外部数据库(.env.docker),并把DB_HOST从默认的mariadb改为外部主机地址即可; - Redis 单独分配资源:用户超过 200 后,同样可通过
REDIS_HOST、REDIS_PORT指向独立 Redis 实例。
迁移外部 DB 时注意保持数据一致性(建议先./cmd mysql backup备份,参考 cmd),并同步检查外部数据库的innodb_buffer_pool_size、慢查询日志等参数配置。
反模式清单:这些操作不要做
- 不要只加 worker 不加 CPU:
worker_num本质是 CPU 绑定型进程数,CPU 不足时盲目加大 worker 只会加剧线程切换与内存占用,系统反而更慢; - 生产环境不要保留
APP_DEBUG=true:调试模式下日志会爆炸式增长,拖慢磁盘与整体响应。生产必须保持APP_DEBUG=false(.env.docker 默认即为 false;可通过./cmd debug false一键切换,见 cmd); - 不要套用 PHP-FPM 调优经验:DooTask 是 Swoole 常驻协程模型,
php-fpm.conf那套进程池调优思路不适用。
相关 FAQ 延伸阅读
- 装了 search 插件仍然搜不到结果:参见 全局搜索无结果 FAQ
- 磁盘空间耗尽导致系统异常:参见 磁盘满 FAQ
- 备份 / 升级运维实践:参见 部署备份 FAQ 与 部署升级 FAQ
- 后端
- 前端
- 协同办公
- 即时通讯
- 企业应用
【免费下载链接】dootask
DooTask是一款开源在线项目任务管理工具,提供各类文档协作工具、在线思维导图、在线流程图、项目管理、任务分发、即时IM,文件管理等工具;同时消息功能使用非对称加密技术让你的沟通更安全。
相关推荐
从卡顿到丝滑:Dubbo性能调优与故障排查实战指南
从卡顿到丝滑:Dubbo性能调优与故障排查实战指南 Apache Dubbo作为一款高性能的RPC和微服务框架,在实际应用中可能会遇到各种性能瓶颈和故障问题。本
后端RPC框架微服务服务注册发现优化BongoCat系统调用性能:从卡顿到丝滑的实战指南
优化BongoCat系统调用性能:从卡顿到丝滑的实战指南 你是否遇到过BongoCat在高频键盘输入时出现动画延迟?当你快速敲击键盘或移动鼠标时,可爱的猫咪动画
桌面应用Cherry Studio 性能调试指南:从卡顿、CPU 到内存泄漏的系统化排查方法
Cherry Studio 性能调试指南:从卡顿、CPU 到内存泄漏的系统化排查方法 本文基于仓库内 .agents/skills/cherry electro
人工智能大模型AI 应用交互助手本地部署
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考