From d1e727ad5e9bb2d0467e641f8f7ecb5a493782e4 Mon Sep 17 00:00:00 2001 From: Xavier Fontanet Date: Wed, 10 Jul 2024 15:43:18 +0200 Subject: [PATCH] add a concurrent requests script --- concurrent_requests.py | 79 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 concurrent_requests.py diff --git a/concurrent_requests.py b/concurrent_requests.py new file mode 100644 index 0000000..728a8c0 --- /dev/null +++ b/concurrent_requests.py @@ -0,0 +1,79 @@ +import asyncio +import random +import aiohttp +import yaml +import time +import numpy as np + +status_stats = {} + +# init params +def getParams(): + with open('params.yml', 'r') as params_file: + try: + return yaml.safe_load(params_file) + except yaml.YAMLError as error: + print(error) + +params = getParams() +requestsNumber = params['concurrent_requests'] +endpoint = params['endpoint'] +service = params['service'] +parameters = params['parameters'] + +# init functions +def fPar(param): + return '?' + param + '=' + str(parameters[param]) + +def mPar(param): + return '&' + param + '=' + str(parameters[param]) + +def mRandPar(param): + options = parameters[param].split(', ') + selected = random.choice(options) + return '&' + param + '=' + selected + +def nextUrl(id): + url = "http://" + endpoint + '/' + module + '/' + service + fPar('firsParam') + mRandPar('multipleValueParam') + mPar('otherParam') + print("Id: {} to call {}".format(id, url)) + return (id, url) + +async def asyncHttpGet(url_tuple, session): + id, url = url_tuple + try: + start_time = time.time() + async with session.get(url=url) as response: + spent_time = round((time.time() - start_time)*1000) + code = response.status + resp = await response.read() + print("Id: {}, Got {} status in {} milis with response length of {}.".format(id, code, spent_time, len(resp))) + if code != 200 or len(resp) < 200: + print("ID: {}. Error: {}.".format(id, resp)) + # Save stats + if code in status_stats: + status_stats[code]['times'].append(spent_time) + status_stats[code]['count'] += 1 + else: + status_stats[code] = {'times': [spent_time], 'count': 1} + except Exception as e: + print("Id: {}. Unable to get url {} due to {}.".format(id, url, e)) + +async def allRequests(urlsToCall): + start_time = time.time() + async with aiohttp.ClientSession() as session: + ret = await asyncio.gather(*[asyncHttpGet(url, session) for url in urlsToCall]) + spent_time = round((time.time() - start_time)*1000) + print("Finalized all {} requests in {} milis.".format(len(ret), spent_time)) + +# MAIN +asyncio.run(allRequests([nextUrl(i) for i in range(0, requestsNumber)])) + +print("### STATS ###") +for status_code, stats in sorted(status_stats.items()): + average_time = round(np.mean(stats['times'])) + min_time = min(stats['times']) + max_time = max(stats['times']) + p50 = round(np.percentile(stats['times'], 50)) + p95 = round(np.percentile(stats['times'], 95)) + print("With status {} happened to {:<3} requests, average time was {} milis. Min: {}, p50: {}, p95: {}, Max: {}". + format(status_code, stats['count'], average_time, min_time, p50, p95, max_time)) \ No newline at end of file