Clustering en - Pa-dej/Vex GitHub Wiki
Clustering (English)
Clustering allows multiple Vex nodes to share reputation, rate limits, and player registry through Redis.
Architecture (ASCII)
+------------------+
| Clients |
+--------+---------+
|
+---------+----------+
| Load Balancer |
+----+---------+-----+
| |
+-------+--+ +--+-------+
| Vex A | | Vex B |
| node_id | | node_id |
+----+----+ +----+------+
| |
+------+-+----+
| |
+---+-v---+
| Redis |
+---+-----+
|
+--------+--------+
| Backends |
+-----------------+
When to use clustering
- You run multiple proxy nodes behind a load balancer.
- You want shared anti-bot reputation and global rate limiting.
- You need a global player list across nodes.
Redis setup
Redis should be reachable by all nodes. Example:
docker run -d --name vex-redis -p 6379:6379 redis:7
Node configuration
[cluster]
enabled = true
node_id = "edge-1"
heartbeat_interval_secs = 5
heartbeat_ttl_secs = 15
allow_degraded = true
[cluster.redis]
url = "redis://127.0.0.1:6379"
connect_timeout_ms = 1000
command_timeout_ms = 500
circuit_breaker_errors = 5
circuit_breaker_reset_ms = 5000
pubsub_channel = "vex.cluster"
Shared reputation
- Each node writes IP scores to Redis.
- Reads merge local cache + Redis values.
- Decay and block escalation remain local but use shared score.
Global rate limiting
- Token buckets are stored as Redis atomic counters.
- Bucket refill logic runs per node, but counters are global.
- Prevents a single IP from flooding all nodes.
Pub/sub events
- Attack mode changes propagate to all nodes.
- Reputation deltas are broadcast to reduce stale scores.
- Broadcast messages can be pushed to all nodes.
Degraded mode
When Redis is unavailable:
- Nodes continue to accept connections if
allow_degraded = true. - Local reputation cache keeps working without cross-node sync.
- Circuit breaker backs off Redis attempts until it recovers.
Docker Compose example (2-node cluster)
version: "3.9"
services:
redis:
image: redis:7
ports:
- "6379:6379"
vex-a:
image: vex:latest
ports:
- "25577:25577"
volumes:
- ./vex-a.toml:/app/vex.toml
depends_on:
- redis
vex-b:
image: vex:latest
ports:
- "25578:25577"
volumes:
- ./vex-b.toml:/app/vex.toml
depends_on:
- redis