client
Overview
The **`client`** file is a lightweight asynchronous HTTP load testing script. Its primary purpose is to measure the responsiveness and throughput of an HTTP server running locally by issuing a rapid sequence of HTTP GET requests to the server’s root endpoint. It runs for a fixed duration (5 seconds) and reports the total number of requests completed in that interval.
This script uses Python’s `asyncio` for asynchronous concurrency and the `httpx` library’s asynchronous client to maximize request throughput without blocking. It is designed to be used alongside an HTTP server (such as the Flask app example in the integration) to validate server performance under load.
Detailed Explanation
Global Variables
Variable | Description |
|---|---|
`port` | The port number of the target HTTP server, passed as a command-line argument. |
`url` | The full URL constructed using the port, targeting `http://127.0.0.1:`. |
An `httpx.Timeout` object setting a 5-second timeout per request to avoid stalling. | |
`client` | An instance of `httpx.AsyncClient` configured with the timeout for sending async HTTP requests. |
`stop_time` | The absolute timestamp 5 seconds in the future when the test should stop. |
`TEST_MESSAGE` | A constant string message displayed to the user indicating test progress. |
Function: async def main()
Purpose
Runs the asynchronous load test by sending repeated GET requests to the target URL until the timeout (`stop_time`) is reached. It keeps count of successful requests and prints results.
Parameters
None
Return Value
None (performs output to stdout)
Behavior
Writes the startup message
TEST_MESSAGEto standard output and flushes to ensure immediate display.Initializes a counter
countto zero.Enters a loop that runs until the current time exceeds
stop_time.On each iteration:
Sends an asynchronous GET request to the
urlusing the sharedclient.Increments the
countof successful requests.
After the loop ends, outputs a carriage return (
\r) to overwrite the prior message line and prints a summary message with the total requests made.
Usage Example
$ python3 client 8001
http test running... ok, 12345 requests made
Here, the client targets a server running on localhost port 8001 and runs for 5 seconds, printing how many requests were completed.
Implementation Details
Asynchronous HTTP Requests:
The use ofhttpx.AsyncClientcombined withawait client.get(url)allows non-blocking HTTP calls. This maximizes throughput by not waiting synchronously for each response before issuing the next request.Fixed Duration Loop:
The loop’s condition checks the current time against a predefinedstop_timeto ensure the test runs precisely for about 5 seconds.Timeout Configuration:
Thehttpx.Timeout(5.0)ensures individual requests do not hang indefinitely, matching the test duration.Standard Output Handling:
The script usessys.stdout.write()andflush()for immediate output, and a carriage return\rto update the line with the final result cleanly.Manual Event Loop Management:
The script creates a new event loop viaasyncio.new_event_loop(), sets it as current, runs the asyncmain()function, then closes the loop. This explicit control ensures clean setup/teardown of the asyncio environment.
Interaction with Other System Components
Target HTTP Server:
The client requires a running HTTP server accessible athttp://127.0.0.1:<port>. It is typically used alongside the Flask application example that serializes JSON responses usingorjson.Load Testing in Integration Workflow:
This client is part of an integration testing suite which includes:The Flask server (
wsgi.py) that handles incoming requests.The Gunicorn launch script (
http) that runs the server with multiple workers.The orchestration script (
run) that manages starting the server and client together.
Performance Validation:
By generating a rapid stream of requests, it helps assess the server’s JSON serialization and HTTP handling performance under pressure.
Mermaid Diagram
This class-free file centers around a single asynchronous function and global variables. A flowchart showing the main execution workflow and function relationships is appropriate:
flowchart TD
Start["Start Script"] --> ParsePort["Parse port from sys.argv"]
ParsePort --> Setup["Setup URL, Timeout, AsyncClient"]
Setup --> SetStopTime["Calculate stop_time (now + 5 sec)"]
SetStopTime --> MainFunc["Run async main()"]
subgraph AsyncMain [async def main()]
direction TB
PrintStart["Print TEST_MESSAGE to stdout"]
LoopCheck["while time < stop_time"]
SendRequest["await client.get(url)"]
IncrementCount["count += 1"]
LoopCheck -->|True| SendRequest --> IncrementCount --> LoopCheck
LoopCheck -->|False| PrintEnd["Print final count message"]
end
MainFunc --> End["Close event loop and exit"]
Summary
The **`client`** file is a concise asynchronous HTTP load generator that sends as many HTTP GET requests as possible to a given local server within 5 seconds. It leverages `asyncio` and `httpx.AsyncClient` for high throughput, providing a simple but effective way to measure server responsiveness and request handling capacity. This script is a key component in an HTTP server integration testing suite, facilitating performance benchmarking and validation of JSON serialization under concurrent load.
Appendix: How to Run
python3 client <port>
Replace
<port>with the port number your HTTP server is listening on (e.g., 8001).Ensure the target HTTP server is running before starting the client.
The script will print progress and final request count after 5 seconds.