diff --git a/deploy/apply-lag-fix.sh b/deploy/apply-lag-fix.sh new file mode 100644 index 0000000..065c195 --- /dev/null +++ b/deploy/apply-lag-fix.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# 部署卡顿修复并验证 rt= +set -e +DJANGO_DIR="/opt/1panel/apps/openresty/nginx/www/sites/43.142.166.152.443/django" +NGINX_LOG="/opt/1panel/apps/openresty/nginx/log/access.log" +cd "$DJANGO_DIR" + +echo ">>> git pull" +git pull origin main + +echo ">>> 更新 systemd (6 workers)" +cp deploy/systemd/gunicorn-dianjing.service /etc/systemd/system/gunicorn-dianjing.service +systemctl daemon-reload +systemctl restart gunicorn-dianjing.service +sleep 2 +systemctl is-active gunicorn-dianjing.service +pgrep -cf 'gunicorn.*a_long_dianjing' || true + +echo "" +echo ">>> 最近慢请求 (rt>=0.5s):" +grep -a 'hqhd' "$NGINX_LOG" | awk 'match($0,/rt=([0-9.]+)/,a){if(a[1]+0>=0.5)print}' | tail -5 + +echo "" +echo ">>> 最近 dddhq / merchant-staff/me:" +grep -a 'hqhd' "$NGINX_LOG" | grep -E 'ddhq|merchant-staff/me' | tail -8 | awk 'match($0,/rt=([0-9.]+)/,a){rt=a[1]} match($0,/POST ([^ ]+)/,b){print " rt="rt"s "b[1]}' + +echo "" +echo "部署完成。请用手机再试,然后看上面 rt 是否都 <0.2s" diff --git a/deploy/systemd/gunicorn-dianjing.service b/deploy/systemd/gunicorn-dianjing.service index 10cd659..048b7e7 100644 --- a/deploy/systemd/gunicorn-dianjing.service +++ b/deploy/systemd/gunicorn-dianjing.service @@ -7,7 +7,7 @@ Type=simple User=root Group=root WorkingDirectory=/opt/1panel/apps/openresty/nginx/www/sites/43.142.166.152.443/django -ExecStart=/usr/local/bin/gunicorn --bind 127.0.0.1:8001 --workers 4 --threads 4 --worker-class gthread --timeout 120 --log-level warning --access-logfile /dev/null --error-logfile /tmp/gunicorn-error.log a_long_dianjing.wsgi:application +ExecStart=/usr/local/bin/gunicorn --bind 127.0.0.1:8001 --workers 6 --threads 4 --worker-class gthread --timeout 120 --log-level warning --access-logfile /dev/null --error-logfile /tmp/gunicorn-error.log a_long_dianjing.wsgi:application Restart=always RestartSec=3 StandardOutput=null diff --git a/merchant_ops/services/bootstrap.py b/merchant_ops/services/bootstrap.py index 440c322..5839eab 100644 --- a/merchant_ops/services/bootstrap.py +++ b/merchant_ops/services/bootstrap.py @@ -4,6 +4,10 @@ from merchant_ops.models import ( MerchantStaffPermission, MerchantStaffRole, MerchantStaffRolePermission, ) +_SYSTEM_ROLE_CODES = {t['role_code'] for t in SYSTEM_ROLE_TEMPLATES} +_SYSTEM_BOOTSTRAPPED = False +_MERCHANT_BOOTSTRAPPED = set() + def seed_global_permissions(): for idx, (code, name) in enumerate(PERMISSION_DEFINITIONS): @@ -23,7 +27,24 @@ def _sync_role_permissions(role, perm_codes): role.role_permissions.exclude(perm_code__in=perm_codes).delete() +def _system_roles_ready(): + if not _SYSTEM_ROLE_CODES: + return False + existing = set( + MerchantStaffRole.query.filter( + merchant_id=None, is_system=True, status=1, + ).values_list('role_code', flat=True) + ) + if not _SYSTEM_ROLE_CODES <= existing: + return False + return MerchantStaffPermission.query.count() >= len(PERMISSION_DEFINITIONS) + + def ensure_system_role_templates(): + global _SYSTEM_BOOTSTRAPPED + if _SYSTEM_BOOTSTRAPPED or _system_roles_ready(): + _SYSTEM_BOOTSTRAPPED = True + return seed_global_permissions() for tpl in SYSTEM_ROLE_TEMPLATES: role, _ = MerchantStaffRole.objects.get_or_create( @@ -38,10 +59,24 @@ def ensure_system_role_templates(): }, ) _sync_role_permissions(role, tpl['permissions']) + _SYSTEM_BOOTSTRAPPED = True def ensure_merchant_roles(merchant_id): - """为商家复制系统角色模板,并同步预置角色权限。""" + """为商家复制系统角色模板。已初始化则直接返回,避免热路径全量同步拖垮 worker。""" + mid = str(merchant_id) + if mid in _MERCHANT_BOOTSTRAPPED: + return + + existing_codes = set( + MerchantStaffRole.query.filter( + merchant_id=merchant_id, is_system=True, status=1, + ).values_list('role_code', flat=True) + ) + if _SYSTEM_ROLE_CODES and _SYSTEM_ROLE_CODES <= existing_codes: + _MERCHANT_BOOTSTRAPPED.add(mid) + return + ensure_system_role_templates() templates = MerchantStaffRole.query.filter(merchant_id=None, status=1) for tpl in templates: @@ -58,3 +93,4 @@ def ensure_merchant_roles(merchant_id): ) tpl_perms = list(tpl.role_permissions.values_list('perm_code', flat=True)) _sync_role_permissions(role, tpl_perms) + _MERCHANT_BOOTSTRAPPED.add(mid)