Gatling VS Postman: Big difference in response time - performance-testing

I am trying to measure the performance of a single REST endpoint (GET) with Gatling, with a very simple setup like this one:
val httpProtocol: HttpProtocolBuilder = http
.baseUrl("https://domain:8085")
.acceptHeader("*/*");
val scn =
scenario("MyScenario")
.exec(
http("MyRequest")
.get(myPath)
)
setUp(scn.inject(rampUsersPerSec(1) to (1) during (10 seconds))).protocols(httpProtocol)
Which means 1 request per second.
The problem is that the min response time is more than 500ms, average 600ms, but if I do the same test manually with Postman, same endpoint and parameters, the response time is between 150ms and 250ms.
Why could be this difference appear? How can I track the issue?
I verified that the execution time in the server side is the same for both.
Thank you!

Which means 1 request per second - no it doesn't, it means 1 thread executing requests for 10 seconds as fast as it can, given you state response time is around 500ms my expectation is that around 20 requests have been executed which gives approximately 2 requests per second. I don't think it is the real issue, but it's not the "same test"
It's also not the "same test" when it comes to HTTP Headers, Postman sends few more by default like Postman-Token and especially Accept-Encoding which is missing in your Gatling test and present by default in Postman requests and this guy can have quite big impact
In order to be absolutely to send the same request that Postman sends you can just record it using Gatling Recorder

Related

How to limit execution of python flask function to single instance

I have a Python Flask page which is extremely slow to generate. It takes about 1 minute to pull all the data from external APIs, process the data before returning the page. Fortunately, the data is valid for up to 1 hour so I can cache the result and return cached results quickly for most of the requests.
This works well except for the minute after the cache expires. If 10 requests were made within that single minute, there will be 10 calls to veryslowpage() function, this eats up the HTTPS connection pool due to the external API calls and eats up memory due to the data processing, affecting other pages on the site. Is there a method to limit this function to a single instance, so 10 requests will result in only 1 call to veryslowpage() while the rest wait until the cached result is ready?
from flask import Flask, request, abort, render_template
from flask_caching import Cache
#app.route('/veryslowpage', methods=['GET'])
#cache.cached(timeout=3600, query_string=True)
def veryslowpage():
data = callexternalAPIs()
result = heavydataprocessing(data)
return render_template("./index.html", content=result)
You could simply create a function that periodically fetch the data from API (every hour) and store it in your database. Then in your route function read the data from your database instead of external API.
A better approach is creating a very simple script and call it (in another thread) in your app/init.py that fetch the data every one hour and update the database.
You could create a file or a database entry that contains the information that you are calculating the response in a different thread. Then, your method would check if such a file exists and if it does, let it wait and check for the response periodically.
You could also proactively create the data once every hour (or every 59 minutes if that matters) so you always have a fresh response available. You could use something like APScheduler for this.

Elasticsearch 429 Too Many Requests _bulk with synchronous requests

I am using AWS Elasticsearch service. On dev environment there is t3.small instance.
I have approx 15 000 records that I want to index as a bulk. What I do is splitting this amount on chunks of 250 items each (or lower than 10 MiB). And run _bulk request with refresh="wait_for" option, one by one, and waiting until request is finished before sending the next one.
At some point, approximately on 25 iteration, the request is immediately fails with message
429 Too Many Requests /_bulk
Just in case, if chunk size will be 500 this will fail on 25/2 request (around 12)
It doesn't tell anything more. Just only this, I cannot understand why this happens if there is no anything else that could send bulk requests in parallel with me. I checked that the data size is lesser than 10MB.
What I already have
I send each request consistently, awaiting the previous one
Bulk request size is lesser than 10MiB
Each bulk request contains no more than 250 records in it (+ 250 to indicate that this is indexing)
I am using refresh="wait_for"
And even have 2 seconds delay before sending a new request (which I strongly want to remove)
Adding new instances or increasing storage space doesn't help at all
What could be the reason of having that error? How can I be guaranteed that my request will not be failed if I send everything consistently? Is there any additional option I can pass to be sure that bulk request is completely finished?
A 429 error message as a write rejection indicates a bulk queue error. The es_rejected_execution_exception[bulk] indicates that your queue is full and that any new requests are rejected. When the number of requests to the Elasticsearch cluster exceeds the bulk queue size (threadpool.bulk.queue_size), this bulk queue error occurs. A bulk queue on each node can hold between 50 and 200 requests, depending on which Elasticsearch version you are using.
You can consult this link https://aws.amazon.com/premiumsupport/knowledge-center/resolve-429-error-es/ and check the write rejection best practices

Overcoming Azure Vision Read API Transactions-Per-Second (TPS) limit

I am working on a system where we are calling Vision Read API for extracting the contents from raster PDF. Files are of different sizes, ranging from one page to several hundred pages.
Files are stored in Azure Blob and there will be a function to push files to Read API once when all files are uploaded to blob. There could be hundreds of files.
Therefore, when the process starts, a large number of documents are expected to be sent for text extraction per second. But Vision API has limit of 10 transactions per second including read.
I am wondering what would be best approach? Some type of throttling or queue?
Is there any integration available (say with queue) from where the Read API will pull documents and is there any type of push notification available to notify about completion of read operation? How can I prevent timeouts due to exceeding 10 TPS limit?
Per my understanding , there are 2 key points you want to know :
How to overcome 10 TPS limit while you have lot of files to read.
Looking for a best approach to get the Read operation status and
result.
Your question is a bit broad,maybe I can provide you with some suggestions:
For Q1, Generally ,if you reach TPS limit , you will get a HTTP 429 response , you must wait for some time to call API again, or else the next call of API will be refused. Usually we retry the operation using something like an exponential back off retry policy to handle the 429 error:
2.1) You need check the HTTP response code in your code.
2.2) When HTTP response code is 429, then retry this operation after N seconds which you can define by yourself such as 10 seconds…
For example, the following is a response of 429. You can set your wait time as (26 + n) seconds. (PS: you can define n by yourself here, such as n = 5…)
{
"error":{
"statusCode": 429,
"message": "Rate limit is exceeded. Try again in 26 seconds."
}
}
2.3) If step 2 succeed, continue the next operation.
2.4) If step 2 fail with 429 too, retry this operation after N*N seconds (you can define by yourself too) which is an exponential back off retry policy..
2.5) If step 4 fail with 429 too, retry this operation after NNN seconds…
2.6) You should always wait for current operation to succeed, and the Waiting time will be exponential growth.
For Q2,, As we know , we can use this API to get Read operation status/result.
If you want to get the completion notification/result, you should build a roll polling request for each of your operation at intervals,i.e. each 10 seconds to send a check request.You can use Azure function or Azure automation runbook to create asynchronous tasks to check read operation status and once its done , handle the result based on your requirement.
Hope it helps. If you have any further concerns , please feel free to let me know.

Is there a way to select an unbroken series of requests each lasting a given duration?

I need to find any requests where 5 of them in a row take 30 seconds or more.
Is there a way to do this using a kusto query?
I guess it could be rephrased as 'if there is a request that takes 30 seconds or more to get a response, check if the next 4 requests also take 30 seconds'.
Check this thread -
Check for the request where response time is higher
Hope it helps.

SOAP UI - How to determine time taken between steps

I just want to know what will be the best way to determine time taken between test steps and log an overall average time within free version of SOAP UI? I have a test which has a 2 request steps, lets say request step 1 is step 3 and request step 2 is step 5 in the test case. I am performing a load test so I'm iterating through the test multiple times but want to know the average time taken between request step 1 and until it reaches request step 2 after the whole test has finished.
Any ideas on best practice to do this?
You can verify the Date Header from request's response.
You can add some groovy script in the steps to write timestamps in a file...

Resources