Reputation: 280
I have created an API server on which one of the endpoints retrieves, sorts and calculates data from a MySQL database.
The endpoint looks like this:
http://localhost:3003/widgetData/$userId/$widgetId/$startDate/$endDate/
$widgetId contains information on the data to be retrieved. So an example of a real use endpoint would be:
http://localhost:3003/widgetData/94/155/2018-07-01 00:00:00/2018-07-03 00:00:00/
When I fire off one request at a time I get a time of about 600ms-900ms (this is not great but based on the database architecture (entity-attribute-value) there was no other way to improve this speed). Below is a log from winston which I've set up to monitor the time spent on each request.
INFO: Data sent to user: 91 in 951.46ms [widgetId:92 - widgetType:barChart - countParams:1- timeSelected:2 Days - start:2018-07-01 00:00:00 end:2018-07-03 00:00:00]
NOTE: I have tested with and without the logger and there is no difference in time (using postman) so I know the timer I'm using does not block the event loop
When a user loads a dashboard in the front end of the system, this request could be fired off up to 1-100 times concurrently as each individual widget loads its own data. (Averagely its about 20-30 widgets per dashboard)
When multiple requests are sent, they seem to get "batched" and the first request waits until the last request is complete before responding. Here is an example output from the logger for 4 requests happening concurrently (sent from chrome in 4 browser tabs reloading at the same time)
INFO: Data sent to user: 91 in 3825.77ms [widgetId:156 - widgetType:barChart - countParams:2- timeSelected:2 Days - start:2018-07-01 00:00:00 end:2018-07-03 00:00:00]
INFO: Data sent to user: 91 in 3827.49ms [widgetId:157 - widgetType:barChart - countParams:1- timeSelected:2 Days - start:2018-07-01 00:00:00 end:2018-07-03 00:00:00]
INFO: Data sent to user: 91 in 3836.12ms [widgetId:92 - widgetType:barChart - countParams:1- timeSelected:2 Days - start:2018-07-01 00:00:00 end:2018-07-03 00:00:00]
INFO: Data sent to user: 91 in 3841.79ms [widgetId:155 - widgetType:barChart - countParams:3- timeSelected:2 Days - start:2018-07-01 00:00:00 end:2018-07-03 00:00:00]
What I'm expecting to see is all requests running at the speed of one request (as they all run asynchronously)
I've tried running part of the answer from the stack-overflow linked here and my code does not seem to block the Event Loop so I'm not really sure what is happening or how to resolve it.
I have also tried running the code in pm2 in cluster mode (by using pm2 start index.js -i max
) but all the requests seem to run on the same instance instead of balancing out between each other.
There is a lot of code running for each request, and I'm not sure what parts are potentially relevant to this problem. If there are code examples I need to add to this post please let me know as I can do.
Upvotes: 1
Views: 361
Reputation: 2844
I think the MySQL database is the bottleneck of your system. Try to measure sql queries execution time for one request and for parallel requests. You should see the drastic increase of query time. If it’s so, you need to avoid burst requests from dashboard page. As an option you can initialize widget only when they become visible. Another option would be manually partition all widget queries into chunks (i.e. 10 requests in a chunk) on sequentially run them (when all requests from previous chunk finishes). But these solutions won’t work when you have many users simultaneously opening dashboard. So you have to do optimize the slow sql queries to database.
Upvotes: 1