Multiple backend non blocking calls from NodeJS gives slow response - performance

I have a specific use case which Im trying to solve using Node. The response time that I receive from NodeJS is not the one I expect.
The application is an express.js web application. The flow is as below
a. Request reaches the server.
b. Based on the parameter, backend REST Service is invoked.
c. The response of the REST Service has links to multiple other objects.
d. Navigate each of the link and agrregate the data.
e. This data is formatted (not much) and send to the client.
The actual test data-
The response from C has got 100 links and hence I make 100 parallel calls (Im using async.map). Each of the backend service responds in less than 30 msecs. But the overall response time for 100 requests is 4 seconds. This is considerably high.
What I have observed is :
The time difference between the first backend request and the last backend request is around 3 seconds. I believe that this is due to the fact that Node is single threaded and it takes 3 seconds to place all of the 100 http requests.
The code that I use to make parallel calls is given below
var getIndividualRecord = function(entity,callback1)
{
httpExecutor.executeRequest( entity.link.url, callback1);
}
var aggregateData = function(err, results)
{
callback(null, results);
}
async.map(childObjects, getIndividualRecord, aggregateData);
The childObjects is an array with 100 records. httpExecutor makes a REST invocation using request module.
Is there something wrong Im doing or is this a wrong use case for Node?

You're assumption is correct: node is single threaded, so while your HTTP requests happen in a nonblocking manner (requests are made right after the other without even waiting for the response from the server), they don't truly happen in simultaneously.
So, yes, it's probable it takes Node 3 seconds to get through all these requests and process them.
There are a few ways "around" this, which might work depending on your situation:
Could you use Node's cluster module to spawn multiple node apps and each do a portion of the work? Then you would be doing things simultaneously (since you have N Node processes going on).
Use a background queue mechanism (aka: Resque, Beanstalk) and have a background worker (or a process spawned with Cluster) to distribute the work (to Node worker processes waiting around to pick things off this queue)
Refactor your web app a little bit to deal with the fact that parts will take a while. Perhaps render most of the page then onload make an ajax request that fires off the 3 second route and then puts the results in some DOM element when the AJAX request comes back.

i have similar scenario and similar observation.
in my case I run node app using pm2. in app there are 2 sub servers (let's call them A and B). pm2 spawns 2 processes per each server. from a client i call server A, it calculates simple thing and call server B in async manner. when server B responds server A sends data back to client.
very simple scenario but when I used jmeter to create 1000 threads (where each thread makes 50 calls)to call server A I got average response around 4 sec (for 50000 calls).
server B responds after 50ms and I think this is the problem. during first 50ms nodejs processes lots of incoming requests and then it cannot quickly process responses from server B and incoming calls.
I would expect that application code is executed in single thread but there supposed to be background threads to deal with all the rest. it seems this is not the case.

Related

250 users hitting around 60k overall requests in jmeter

I have 250 users ,and around 60000 sample counts should be hit including all the requests. Whichever request is supposed to get huge sample count,I have put those request within loop count,But the requests outside the loop are getting executed only 3-4 times which is less than expected. How do I handle this?
It is not very possible to provide the comprehensive answer without knowing what you're trying to achieve and seeing your test or at least Thread Group configuration
The easiest option is moving the requests which you want to execute more times into a separate Thread Group
If the requests have to stay in one Thread Group you can control the frequency using Throughput Controller
If the logic is more complex - consider using Switch Controller or Weighted Switch Controller

Response code 500 in JMeter when running with threads

Getting the following error in JMeter while running the list of APIs (with no of threads:1-140 with ramp up period-1).
Response code:500
Response message: Internal Server Error
How should I overcome this Error Response code in order to get the accurate response?
What should do to decrease amount of response with this response code?
In general a 500 is an unhandled response on the part of a developer. Usually on the backend but also on the performance testing tool front end.
Ask yourself, are you validating responses that come back from the server for appropriate content? I am not just suggesting an HTTP200 is valid. You need to check response content to ensure that it is what you expect is valid for the business process, for you can have a completely valid HTTP200 class page which contains a response which will send your business process off the rails. If you do not handle the exception on the part of the unexpected response then you will find that one to two steps down the road in the business process then you are pretty much guaranteed that you will find a 500 as your request is completely out of context with the state of the application at that point.
Test101, for every step there is an expected and positive result which allows the business process to continue. Check for that result and branch your code when you do not find that the result is true.
Or, if this is a single step business process then you are likely handing the service poor data and the developer has not fully fleshed out the graceful part of dealing with your poor data.
The general advice in JMeter is Ramp-up = number of threads, in your case 140
Start with Ramp-up = number of threads and adjust up or down as needed.
Currently you are sending every 1/140 seconds new thread which is almost simultaneously, the reason to the change is:
Ramp-up needs to be long enough to avoid too large a work-load at the start of a test
Status code - 500 comes from server/API's and it's not an issue of Jmeter. Sometimes the concurrent requests are rejected by server as it's too weak to handle that number of requests.In my case, I asked my server team to scale up servers so that we can test the underlying API . It's worth mentioning that sometimes Jmeter also runs out of memory. You can do some tweaking in set HEAP=-Xms512m -Xmx512m property of jmeter execuble file. Also listeners consume too much resources.Try not to use them.

Within a thread, are JMeter HTTP request/responses done sequentially?

I'm trying to understand the basics of JMeter. I've got a "plus1" Java servlet that adds one to a request parameter and returns the result, so it's a fast test servlet just so I can understand load testing.
Here's my test plan:
Thread Group: 1 thread, ramp up 1 s, loop count 10000
HTTP Request to localhost
Graph Results
Summary Report
When I run this, the summary report shows a throughput number of 200/sec or so.
The key question, with no controllers in the test plan, is JMeter running the test plan (sending a single request) and waiting for the response before looping?
When I introduce a more computationally intensive page for the request, the throughput number goes down as I would expect.
In short, yes.
There is an argument for having a sampler that would make a request and not wait for the response but it's an edge case. In most cases you would want a testing tool to wait to see what happens and verify things. It's also more realistic, most users will wait for a response, in fact they generally have to, before making subsequent calls.
If you want to run a capacity test then the best approach, I think, is to spread the load over multiple threads and to actually throttle the throughput of each one - you can do this using a Constant Throughput Controller. Eg. You could have 500 threads each running at 60 requests per minute, this would give a total load of 500 reqs/sec. This way, your test load is predictable and stable - it won't be linked to the speed of response from the server. Note. with multiple threads you'll want a ramp up period and you might find you have to spread the test over multiple machines (known as 'distributed' testing if you're going to google it).

Apache Makes some AJAX Request Behave Synchronously

I have this strange issue where sometimes if I make two AJAX requests to my Apache 2.2 server in rapid succession, the second request will wait for the first to finish before finishing.
Example, I have two requests, one that sleeps for 10 seconds and one that returns immediately. If I run the request that returns immediatly by itself it will always return within 300ms. However, if I call the request that takes 10 seconds, and then call the request that returns right away about 50% of the time the second request will wait until the first finishes and chrome will report that the request too about 10 seconds before receiving a response. The other half of the time the quick request will return right away.
I can't find any pattern to make it behave one way or another, it will just randomly block the quick AJAX requests sometimes, and other times it will behave as expected. I'm working on a dev server that only I am accessing and I've set several variables such as MaxRequestsPerChild to a high value.
Does anyone have any idea why Apache, seemingly at random, is turning my AJAX requests into synchronous requests?
Here is the code I'm running:
$.ajax({async:true,dataType:'json',url:'/progressTest',success:function(d){console.log('FINAL',d)}}); // Sleeps for 10 seconds
$.ajax({async:true,dataType:'json',url:'/progressTestStatus',success:function(d){console.log('STATUS',d)}}); // Takes ~300ms
And here are two screen shots. The first where it behaved as expected and the second where it waited for the slow process to finish first (in the example the timeout was set to 3 seconds).
UPDATE: Per the comments below - this appears to be related to Chrome only performing one request at a time. Any ideas why Chrome would set such a low limit on async requests?
The problem is not with Apache but with Google Chrome limiting the number of concurrent requests to your development server. I can only make guesses as to why it's limited to one request. Here are a couple:
1) Do you have many tabs open? There is a limit to the total number of concurrent connections and if you have many tabs making requests with KeepAlive you may be at that limit and can only establish one connect to your server. If that's the case you might be able to fix that by adding KeepAlive to your own output headers.
2) Do you have some extensions enabled. Some extensions do weird things to the browser. Try disabling all your extensions and making the same requests. If it works then enable them one at a time to find the culprit extension.

HTTP parallel requests and AJAX/polling

Okay, so we all know that most modern browsers (without tweaking) are set to 4 parallel HTTP requests at a time to a single domain/subdomain, but how does long-polling AJAX affect this?
Say I have a long-poll on a 15 second interval. While the browser is waiting for a response during those 15 seconds, does that still eat up one of the 4 parallel lines effectively making any new tabs or page loads open to only 3 parallel HTTP requests?
It's not always 4, often it's 2.
It is configurable to a higher number on the client side in many browsers.
Yes it does eat up one of the parallel connections.
You can have 2 concurrent requests via XHR..if you use more you might end up with unexpected results.
Use a Request Queue for more than 2 requests...each one being made after the previous one ends...
Some popular JS libraries implement a queue and can be used, or you could create one easily.

Resources