Add load test harness for pool and fleet sizing
Adds the scripts used to size the connection pool and validate fleet polling under load: burst arrival and mixed workload drivers, pool and resource samplers, a UI probe, host seed/drop SQL, and a gevent Dockerfile. Hosts are addressed by compose service name (api:5001) rather than a local path, so the harness runs against any stack rather than one machine. loadtest_token.py mints a scoped collector token named LOADTEST and prints the secret once, then revokes only that token by name so a real collector token is never touched. envkeyfallback is false, so the harness needs a genuine managed token rather than an env key.
This commit is contained in:
42
scripts/loadtest/pool_status.py
Normal file
42
scripts/loadtest/pool_status.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""Report SQLAlchemy pool saturation from inside the API container.
|
||||
|
||||
WHY: MySQL's max_connections is NOT the ceiling that binds first. The effective
|
||||
limit is per-process: pool_size + max_overflow, multiplied by worker count.
|
||||
With the defaults (5 + 10) and 4 workers that is 60, not 151. A peak of 52
|
||||
therefore means 87 percent of the real ceiling, not 34 percent.
|
||||
|
||||
Prints the computed ceiling so a measured high-water mark can be compared
|
||||
against the right number.
|
||||
|
||||
Usage (inside the api container, PYTHONPATH=/app):
|
||||
python pool_status.py
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
|
||||
from shopdb import create_app
|
||||
from shopdb.api import db
|
||||
|
||||
|
||||
def main():
|
||||
app = create_app(os.environ.get('FLASK_ENV', 'production'))
|
||||
with app.app_context():
|
||||
engine = db.engine
|
||||
pool = engine.pool
|
||||
size = pool.size()
|
||||
overflow = getattr(pool, '_max_overflow', 0)
|
||||
workers = int(os.environ.get('GUNICORN_WORKERS', '4'))
|
||||
print(json.dumps({
|
||||
'pool_class': type(pool).__name__,
|
||||
'pool_size': size,
|
||||
'max_overflow': overflow,
|
||||
'per_worker_ceiling': size + overflow,
|
||||
'workers': workers,
|
||||
'effective_ceiling': (size + overflow) * workers,
|
||||
'checkedout': pool.checkedout(),
|
||||
'status': pool.status(),
|
||||
}, indent=2))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user