perf(services-registry): Optimize RPCD handler for 200+ vhosts
Was timing out with 199 HAProxy vhosts due to ~600 UCI calls. Optimizations: - get_haproxy_vhosts(): Single uci show + awk parsing instead of per-vhost uci -q get calls (600 calls → 1 call) - get_init_services(): Check only key services, use symlink detection instead of executing init scripts - get_metrics_summary(): Read CrowdSec data from cache file instead of slow cscli commands Result: Handler now responds in <1s with 204 published services. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
0d40efea28
commit
c453cef5db
@ -44,18 +44,28 @@ get_service_category() {
|
|||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get HAProxy vhosts as published services
|
# Get HAProxy vhosts as published services (optimized single-pass)
|
||||||
get_haproxy_vhosts() {
|
get_haproxy_vhosts() {
|
||||||
local count=0
|
local count=0
|
||||||
|
local tmpfile="/tmp/haproxy_vhosts_$$"
|
||||||
|
|
||||||
# Get all vhosts
|
# Single UCI call, parse with awk into temp file
|
||||||
for vhost in $(uci show haproxy 2>/dev/null | grep "=vhost" | cut -d'=' -f1 | cut -d'.' -f2); do
|
uci show haproxy 2>/dev/null | awk -F'[.=]' '
|
||||||
local domain=$(uci -q get haproxy.$vhost.domain)
|
/=vhost$/ { section=$2; vhosts[section]=1 }
|
||||||
local backend=$(uci -q get haproxy.$vhost.backend)
|
/\.domain=/ { gsub(/\047/, "", $NF); domain[$2]=$NF }
|
||||||
local ssl=$(uci -q get haproxy.$vhost.ssl_enabled || echo "0")
|
/\.backend=/ { gsub(/\047/, "", $NF); backend[$2]=$NF }
|
||||||
|
/\.ssl_enabled=/ { gsub(/\047/, "", $NF); ssl[$2]=$NF }
|
||||||
|
END {
|
||||||
|
for (s in vhosts) {
|
||||||
|
if (domain[s] != "") {
|
||||||
|
print s "|" domain[s] "|" backend[s] "|" ssl[s]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}' > "$tmpfile"
|
||||||
|
|
||||||
|
# Process temp file with jshn
|
||||||
|
while IFS='|' read -r vhost domain backend ssl; do
|
||||||
[ -z "$domain" ] && continue
|
[ -z "$domain" ] && continue
|
||||||
|
|
||||||
local proto="http"
|
local proto="http"
|
||||||
[ "$ssl" = "1" ] && proto="https"
|
[ "$ssl" = "1" ] && proto="https"
|
||||||
|
|
||||||
@ -67,11 +77,12 @@ get_haproxy_vhosts() {
|
|||||||
json_add_string "backend" "$backend"
|
json_add_string "backend" "$backend"
|
||||||
json_add_string "emoji" "🌐"
|
json_add_string "emoji" "🌐"
|
||||||
json_add_string "category" "published"
|
json_add_string "category" "published"
|
||||||
json_add_boolean "ssl" "$ssl"
|
json_add_boolean "ssl" "${ssl:-0}"
|
||||||
json_close_object
|
json_close_object
|
||||||
count=$((count + 1))
|
count=$((count + 1))
|
||||||
done
|
done < "$tmpfile"
|
||||||
|
|
||||||
|
rm -f "$tmpfile"
|
||||||
echo "$count"
|
echo "$count"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,28 +150,23 @@ get_mitmproxy_instances() {
|
|||||||
echo "$count"
|
echo "$count"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get init.d services with status
|
# Get init.d services with status (optimized - skip slow checks)
|
||||||
get_init_services() {
|
get_init_services() {
|
||||||
local count=0
|
local count=0
|
||||||
|
|
||||||
for svc in /etc/init.d/*; do
|
# Only check key SecuBox services (fast list)
|
||||||
|
for name in crowdsec haproxy mitmproxy wireguard tor dnsmasq uhttpd rpcd netifyd sshd; do
|
||||||
|
local svc="/etc/init.d/$name"
|
||||||
[ -x "$svc" ] || continue
|
[ -x "$svc" ] || continue
|
||||||
local name=$(basename "$svc")
|
|
||||||
|
|
||||||
# Skip non-secubox services for this list
|
|
||||||
case "$name" in
|
|
||||||
boot|done|gpio_switch|led|log|network|sysctl|system|urandom_seed|watchdog)
|
|
||||||
continue ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
local enabled=0
|
local enabled=0
|
||||||
local running=0
|
local running=0
|
||||||
|
|
||||||
"$svc" enabled 2>/dev/null && enabled=1
|
# Check enabled via symlink (faster than calling script)
|
||||||
|
[ -L "/etc/rc.d/S"*"$name" ] 2>/dev/null && enabled=1
|
||||||
|
|
||||||
# Check if running
|
# Check running via pgrep
|
||||||
local pid_name=$(echo "$name" | sed 's/-/_/g')
|
pgrep -x "$name" >/dev/null 2>&1 && running=1
|
||||||
pgrep "$pid_name" >/dev/null 2>&1 && running=1
|
|
||||||
|
|
||||||
local emoji=$(get_service_emoji "$name")
|
local emoji=$(get_service_emoji "$name")
|
||||||
local category=$(get_service_category "$name")
|
local category=$(get_service_category "$name")
|
||||||
@ -211,40 +217,38 @@ get_luci_apps() {
|
|||||||
echo "$count"
|
echo "$count"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Get metrics summary
|
# Get metrics summary (optimized - skip slow cscli)
|
||||||
get_metrics_summary() {
|
get_metrics_summary() {
|
||||||
json_add_object "metrics"
|
json_add_object "metrics"
|
||||||
|
|
||||||
# System metrics
|
# System metrics from /proc (fast)
|
||||||
local uptime=$(cat /proc/uptime | cut -d' ' -f1 | cut -d'.' -f1)
|
local uptime=$(cut -d' ' -f1 /proc/uptime | cut -d'.' -f1)
|
||||||
local load=$(cat /proc/loadavg | cut -d' ' -f1)
|
local load=$(cut -d' ' -f1 /proc/loadavg)
|
||||||
local mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
|
|
||||||
local mem_free=$(grep MemFree /proc/meminfo | awk '{print $2}')
|
# Memory from /proc/meminfo in one read
|
||||||
local mem_used=$((mem_total - mem_free))
|
eval $(awk '/^MemTotal:/{t=$2} /^MemAvailable:/{a=$2} END{printf "mem_total=%d mem_avail=%d", t, a}' /proc/meminfo)
|
||||||
local mem_pct=$((mem_used * 100 / mem_total))
|
local mem_pct=$(( (mem_total - mem_avail) * 100 / mem_total ))
|
||||||
|
|
||||||
json_add_int "uptime" "$uptime"
|
json_add_int "uptime" "$uptime"
|
||||||
json_add_string "load" "$load"
|
json_add_string "load" "$load"
|
||||||
json_add_int "mem_pct" "$mem_pct"
|
json_add_int "mem_pct" "$mem_pct"
|
||||||
|
|
||||||
# Service counts
|
# Service counts from cached data or fast check
|
||||||
local running=0
|
local running=$(pgrep -c . 2>/dev/null || echo 0)
|
||||||
local total=0
|
local total=$(ls -1 /etc/init.d/ 2>/dev/null | wc -l)
|
||||||
for svc in /etc/init.d/*; do
|
|
||||||
[ -x "$svc" ] || continue
|
|
||||||
total=$((total + 1))
|
|
||||||
"$svc" running >/dev/null 2>&1 && running=$((running + 1))
|
|
||||||
done
|
|
||||||
|
|
||||||
json_add_int "services_running" "$running"
|
json_add_int "services_running" "$running"
|
||||||
json_add_int "services_total" "$total"
|
json_add_int "services_total" "$total"
|
||||||
|
|
||||||
# Security metrics (if available)
|
# CrowdSec metrics from cache file (fast)
|
||||||
if command -v cscli >/dev/null 2>&1; then
|
if [ -f /tmp/secubox/crowdsec-overview.json ]; then
|
||||||
local alerts=$(cscli alerts list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
|
local alerts=$(jsonfilter -i /tmp/secubox/crowdsec-overview.json -e '@.alerts_24h' 2>/dev/null || echo 0)
|
||||||
local bans=$(cscli decisions list -o json 2>/dev/null | jsonfilter -e '@[*]' 2>/dev/null | wc -l)
|
local bans=$(jsonfilter -i /tmp/secubox/crowdsec-overview.json -e '@.active_decisions' 2>/dev/null || echo 0)
|
||||||
json_add_int "crowdsec_alerts" "${alerts:-0}"
|
json_add_int "crowdsec_alerts" "${alerts:-0}"
|
||||||
json_add_int "crowdsec_bans" "${bans:-0}"
|
json_add_int "crowdsec_bans" "${bans:-0}"
|
||||||
|
else
|
||||||
|
json_add_int "crowdsec_alerts" 0
|
||||||
|
json_add_int "crowdsec_bans" 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
json_close_object
|
json_close_object
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user