mcpField
F
frappe-ops-performance

frappe-ops-performance

github.com/impertio-studio云与 DevOps198114 次安装30 周前更新
代码仓库

关于 frappe-ops-performance

面向 Frappe/ERPNext 运维人员的性能调优参考,覆盖 MariaDB、Redis、Gunicorn 和 RQ,并提供诊断、监控与扩展建议。

主要功能

  1. 01数据库参数与慢查询分析
  2. 02Redis 内存及缓存配置
  3. 03Gunicorn 工作进程调优
  4. 04RQ 队列与后台任务诊断
  5. 05日志和系统健康监控
  6. 06纵向与横向扩展建议

适用场景

  1. 01排查页面加载缓慢
  2. 02诊断后台任务积压
  3. 03降低内存压力与超时
  4. 04规划单机或多机扩展

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/impertio-studio/frappe_claude_skill_package --skill frappe-ops-performance

安装后在 Claude Code 中输入/frappe-ops-performance确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
.gitkeep
anti-patterns.md
examples.md
workflows.md

详细介绍

性能调优

Frappe/ERPNext 的性能取决于四个层面:数据库(MariaDB)、缓存(Redis)、应用服务器(Gunicorn)和后台工作进程(RQ)。务必同时调优所有四个层面——只优化其中一层而忽略其他层会造成新的瓶颈。

快速参考

# Check system health
bench doctor

# Show pending background jobs
bench --site mysite.com show-pending-jobs

# Clear all caches
bench --site mysite.com clear-cache
bench --site mysite.com clear-website-cache

# Purge stuck background jobs
bench purge-jobs

# Enable MariaDB slow query log
# In /etc/mysql/mariadb.conf.d/50-server.cnf:
# slow_query_log = 1
# slow_query_log_file = /var/log/mysql/slow.log
# long_query_time = 1

# Check Gunicorn worker count
# In Procfile or supervisor config: -w [workers]
# Formula: workers = (2 * CPU_CORES) + 1

性能决策树

What is slow?
|
+-- Page loads are slow?
|   +-- Check Gunicorn workers (are they saturated?)
|   +-- Check MariaDB slow query log
|   +-- Check Redis memory (is cache evicting?)
|   +-- Enable CDN for static assets
|
+-- Background jobs are delayed?
|   +-- bench doctor (check worker count and pending jobs)
|   +-- Increase RQ worker count
|   +-- Check for long-running jobs blocking queues
|
+-- Database queries are slow?
|   +-- Enable slow query log
|   +-- Run EXPLAIN on slow queries
|   +-- Add indexes on frequently filtered columns
|   +-- Use get_cached_value instead of get_value
|
+-- Server runs out of memory?
|   +-- Reduce Gunicorn workers
|   +-- Set Redis maxmemory
|   +-- Check MariaDB innodb_buffer_pool_size
|   +-- Look for memory leaks in custom code
|
+-- High CPU usage?
|   +-- Profile Python code (cProfile)
|   +-- Check for N+1 query patterns
|   +-- Review custom scheduled jobs

MariaDB 调优

关键设置
# /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
# InnoDB buffer pool — MOST important setting
# Set to 50-70% of available RAM on dedicated DB server
# Set to 25-40% of RAM on shared server
innodb_buffer_pool_size = 2G

# Buffer pool instances (1 per GB of buffer pool)
innodb_buffer_pool_instances = 2

# Log file size (larger = better write performance, slower recovery)
innodb_log_file_size = 256M

# Flush method — use O_DIRECT to avoid double buffering
innodb_flush_method = O_DIRECT

# Character set (ALWAYS use utf8mb4 for Frappe)
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# Key buffer for MyISAM (Frappe uses InnoDB, keep small)
key_buffer_size = 32M

# Query cache (DISABLE for MariaDB 10.4+ / MySQL 8.0+)
query_cache_type = 0
query_cache_size = 0

# Connection limits
max_connections = 200
wait_timeout = 600
interactive_timeout = 600

# Temp tables
tmp_table_size = 64M
max_heap_table_size = 64M

# Slow query log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
慢查询分析
# Enable slow query log (runtime, no restart needed)
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;

# Analyze slow queries with mysqldumpslow
mysqldumpslow -t 10 -s c /var/log/mysql/slow.log
# -t 10: top 10 queries
# -s c: sort by count (use -s t for total time)

# Use EXPLAIN to analyze specific queries
EXPLAIN SELECT * FROM `tabSales Invoice` WHERE customer = 'ABC';
# Look for: type=ALL (full table scan), rows > 10000, Using filesort
索引优化
-- Check for missing indexes on frequently filtered columns
SHOW INDEX FROM `tabSales Invoice`;

-- Add index for common filter patterns
ALTER TABLE `tabSales Invoice` ADD INDEX idx_customer_date (customer, posting_date);

-- Frappe way: add index via DocType definition
-- In doctype JSON: set "in_list_view" or "search_index" on fields
-- OR use hooks.py:
-- after_migrate = ["myapp.patches.add_custom_indexes"]

Redis 配置

内存管理
# /etc/redis/redis.conf (or bench config/redis_cache.conf)

# Set maximum memory — NEVER let Redis use all available RAM
maxmemory 512mb

# Eviction policy — allkeys-lru is best for cache use
maxmemory-policy allkeys-lru

# Disable persistence for cache Redis (performance boost)
save ""
appendonly no
Frappe Redis 架构

Frappe 使用三个 Redis 实例:

实例默认端口用途内存参考
redis-cache13000文档缓存、会话数据256MB-1GB
redis-queue11000RQ 作业队列128MB-512MB
redis-socketio12000实时事件64MB-256MB

务必为 redis-cache 设置 maxmemory。否则,Redis 会无限增长,并可能触发 OOM killer。

Frappe 缓存 API
import frappe

# Basic Redis cache
frappe.cache.set_value("my_key", {"data": "value"})
result = frappe.cache.get_value("my_key")

# get_cached_value — cached database lookup (ALWAYS prefer over get_value for reads)
value = frappe.db.get_cached_value("Customer", "CUST-001", "customer_name")
# Equivalent to get_value but caches in Redis — dramatically faster for repeated reads

# Hashed cache (group related values)
frappe.cache.hset("settings", "key1", "value1")
frappe.cache.hget("settings", "key1")

# Clear specific cache
frappe.cache.delete_value("my_key")
frappe.cache.delete_keys("prefix*")

# Clear all cache (use sparingly)
# bench --site mysite.com clear-cache

Gunicorn 工作进程

工作进程数量公式
workers = (2 * CPU_CORES) + 1

Examples:
  2 CPU cores  →  5 workers
  4 CPU cores  →  9 workers
  8 CPU cores  → 17 workers
配置
# Traditional: edit Procfile or supervisor config
# In supervisor.conf:
command=/home/frappe/frappe-bench/env/bin/gunicorn \
    -b 127.0.0.1:8000 \
    -w 9 \                    # Worker count
    --timeout 120 \           # Request timeout (seconds)
    --graceful-timeout 30 \   # Graceful shutdown timeout
    --max-requests 5000 \     # Restart worker after N requests (prevents memory leaks)
    --max-requests-jitter 500 \
    frappe.app:application

# Docker: set via environment variable or command override
内存计算

每个 Gunicorn 工作进程会占用 150-300MB RAM。务必确认总内存足够:

Required RAM = workers * 300MB + MariaDB buffer pool + Redis + OS overhead

Example (4 CPU, 8GB RAM server):
  9 workers * 300MB = 2.7GB (Gunicorn)
  + 2GB (MariaDB innodb_buffer_pool_size)
  + 1GB (Redis total)
  + 1.5GB (OS + other)
  = 7.2GB — fits in 8GB

切勿设置超出 RAM 承受能力的工作进程数量。交换会严重影响性能。


后台工作进程(RQ)

工作进程队列
队列用途默认工作进程数
short快速任务(< 5 分钟)1
default标准任务1
long耗时任务(报表、批量操作)1
调整工作进程数量
# Supervisor: duplicate worker sections with unique names
# For high-volume sites, increase short/default workers:

[program:frappe-bench-frappe-worker-short-1]
command=bench worker --queue short
...

[program:frappe-bench-frappe-worker-short-2]
command=bench worker --queue short
...

# Docker: scale via docker compose
docker compose up -d --scale queue-short=3 --scale queue-long=2
诊断作业积压
# Check overall health
bench doctor
# Expected: Workers online: N, no pending jobs

# Check specific site queues
bench --site mysite.com show-pending-jobs

# Clear stuck jobs (use when jobs are permanently stuck)
bench purge-jobs

静态资源的 CDN 设置

# site_config.json
{
    "cdn_url": "https://cdn.example.com"
}
# All /assets/ URLs will be prefixed with the CDN URL

# ALTERNATIVELY: configure at Nginx level
# location /assets {
#     alias /home/frappe/frappe-bench/sites/assets;
#     expires 1y;
#     add_header Cache-Control "public, immutable";
# }

监控

bench doctor
bench doctor
# Output:
# -----Checking scheduler------
# mysite.com: scheduler is running
# Workers online: 3
# -----None Jobs-----
关键日志位置
日志路径内容
Frappe Web 日志logs/web.logHTTP 请求、错误
工作进程日志logs/worker.log后台作业输出
调度器日志logs/scheduler.log定时作业执行情况
站点级日志sites/{site}/logs/各站点的错误(v13+)
慢查询日志/var/log/mysql/slow.log慢数据库查询
定时作业日志(DocType)

在 ERPNext UI 中检查 Setup > Scheduled Job Log,查看:

  • 作业执行时间
  • 带有错误详情的失败作业
  • 执行频率分析
RQ 仪表板(可选)
# Install RQ dashboard for web-based job monitoring
pip install rq-dashboard
rq-dashboard --redis-url redis://localhost:11000
# Access at http://localhost:9181

常见瓶颈诊断

症状可能原因解决方案
页面加载缓慢,数据库耗时长缺少索引、N+1 查询添加索引,使用带筛选条件的 get_list
工作进程队列不断增长工作进程太少、作业耗时过长增加工作进程,优化作业代码
内存占用高,发生 OOM 终止Gunicorn 工作进程过多、Redis 无上限减少工作进程,设置 maxmemory
间歇性超时Gunicorn 超时时间过短增加 --timeout(默认 120s)
清除缓存后变慢缓存未预热部署后预热关键缓存
静态资源加载缓慢未使用 CDN、未启用浏览器缓存添加 CDN,设置 expires 标头

扩展模式

Vertical Scaling (single server):
  1. Add RAM → increase innodb_buffer_pool_size + Redis maxmemory
  2. Add CPU → increase Gunicorn workers + RQ workers
  3. Use SSD → dramatic improvement for database I/O

Horizontal Scaling (multiple servers):
  1. Separate DB server (MariaDB on dedicated host)
  2. Separate Redis server(s)
  3. Multiple app servers behind load balancer
  4. Read replicas for reporting queries
  5. Kubernetes with frappe_docker for auto-scaling

版本差异

功能v14v15v16
站点级日志v13+是是
bench doctor是是是
Scheduled Job Log是是是
get_cached_value是是是
后台工作进程(RQ)是是是

参考文件

文件内容
examples.md完整的调优配置和脚本
anti-patterns.md常见的性能错误
workflows.md分步调优工作流

相关技能

  • frappe-ops-deployment — 生产环境部署设置
  • frappe-ops-backup — 备份与灾难恢复
  • frappe-ops-bench — Bench CLI 参考
  • frappe-core-database — 数据库 API 和查询模式

评论

支持 Markdown