Executing background task in python and return API response quickly - python-asyncio

API description
I am creating a REST API in Flask
POST API call creates a new entry in DB and returns the primary key of that entry to the
Long running task inside the API
Running a shell command that makes a network call which lasts about 6/7 seconds
Based on the output of the shell command, updating the DB
Main issue with above
We cannot have our API take such long time to return
Since our return value is NOT dependent on step 2,3 - we can execute them in background
We can return immediately after creating an entry in DB and asking remainder to be done in background
How should we do this? (I can think of 4 ways)
Process pool (am ok with scaling limitation)
Task queue & workers (too much infra manage, setup)
Thread pool (possible GIL, though not much)
AsyncIO/gevent (might not allow API to return quickly)

Related

Sustainable solution using JMeter for a big functional flow

I have a huge flow to test using APIs. There are 3 endpoints. One is starting a process (db migration) that can last ~2-3 days, one is returning the status of the current running process (in progress, success, fail) and the last one is returning all the failed processes (as a list).
The whole flow should be:
Start the first process
Call the second endpoint until the first process ends (should get Fail or Success)
If the process failed, call the first endpoint again, if not, go to the next process.
The problem is that 1 process can last around 2-3 days and we have around 20k processes to check. (this should take a lot of time). I do have a special VM only for this.
My question: does it worth trying to implement a solution for this using JMeter?
It is not worth implementing in JMeter unless you want to use the tool as a workload automation engine that replaces functionalities provided by UC4 AppWorkr or Control-M. Based on what you describe, it does not appear to be a load test except the 2nd part that continuously queries the services for success/failure. I do not know the architecture behind that implementation. Hence, I am unable to quantify even that would be a load test or not.

How to keep webserver responsive while executing many asynchronous background tasks

I am working on a web application that provides its users to optionally execute long-running processes 'in background'. An example would be some long-running report generation, or deleting thousands of objects simultaneously.
I've implemented this using an ExecutorService defined as FixedThreadPool using a ThreadFactory. The ThreadFactory is built like this:
ThreadFactoryBuilder()
.setNameFormat(clientId + "-BackgroundTask-%d")
.setDaemon(true)
.setPriority(Thread.MIN_PRIORITY)
.build()
I execute the task like this:
Future<TaskStatus> future = clientExecutors.get(clientId).submit(
backgroundTask::execute);
taskFutures.put(backgroundTask.getTaskId(), future);
How can I enforce my webserver to always priorize handling new incoming requests (as fast as possible) over executing background tasks?
In other words: It should never ever happen, that a user has to wait long time while browsing the site, just because there are a lot of background-tasks executing. As you can see from above, I tried to do this by setting .setPriority(Thread.MIN_PRIORITY). However that does not seem to be sufficient.
Furthermore, as for now, I've set some arbitrary value for the FixedThreadPool size (10) and use it globally for the entire background-handling of the application (and all its customers).
Instead I would like to define a threadpool for each customer, to make sure each customer has the same privilege to run a certain amount of tasks in the background. Say, each customer has a FixedThreadPool of size 5, and on the server I'll have a max. of 50 different customers. That would add up to 250 running background tasks at the same time.
The most important requirement here is: it does not matter, how long these background-tasks need to execute (say 2 minutes, or 20 minutes). What is important, is that each customer has the ability to send 5 tasks to be executed in background, and each of those are worked on equally.
I've tested running 30 cpu-intensive background tasks and it turns out that while these are running and cpu is near 100%, new incoming requests take a very long time to be handled.
So obviously, I am doing it wrong.
Update 12.09.2017
I've read about microservices and while it sounds great I see a great challenge in splitting the necessary parts from our monolithic application. Mostly because nearly every operation might turn into a long running process given a big enough data selection.
Furthermore, wouldn't I run into the same problem with my microservice, i.e. the server running the microservice would suffer the same performance degradation. Well the only good thing would, that the rest of the web app would not suffer from it anymore.
I've read some posts about introducing Thread.sleep(1) or Thread.sleep in general into CPU-heavy operations to reduce the amount of CPU used in these operations. I've also read about someone who introduced this as an aspect so that he can even change the amount of time waited dynamically in order to have some control about how much cpu would be used.
However, my gut tells me that ain't right either. What do you think about introducing Thread.sleep to lower the amount of CPU used for a task? Is this common practice? If not, what would be the right approach?
I would highly consider changing your system architecture to offload these long-running requests to a separate instance instead of running them in-process with the general request-service application. In general I think it is an anti-pattern to handle both batch / online (or long / short running) processing in the same application instance.
Ideally you'd build a standalone microservice to handle these requests, but you could also simply just deploy X instances of your existing application, and configure your load balancer to route requests to the long running invocation paths (e.g. POST /myapp/longrunningjob) only to the instances dedicated to running these long-running processes.

Laravel Queues for multi user environment

I am using Laravel 5.1, and I have a task that takes around 2 minutes to process, and this task particularly is generating a report...
Now, it is obvious that I can't make the user wait for 2 minutes on the same page where I took user's input, instead I should process this task in the background and notify the user later about task completion...
So, to achieve this, Laravel provides Queues that runs the tasks in background (If I didn't understand wrong), Now for multi-user environment, i.e. if more than one user demands report generation (say there are 4 users), so being the feature named Queues, does it mean that tasks will be performed one after the other (i.e. when 4 users demand for report generation one after other, then 4th user's report will only be generated when report of 3rd user is generated) ??
If Queues completes their tasks one after other, then is there anyway with which tasks are instantly processed in background, on request of user, and user can get notified later when its task is completed??
Queue based architecture is little complicated than that. See the Queue provides you an interface to different messaging implementations like rabbitMQ, beanstalkd.
Now at any point in code you send send message to Queue which in this context is termed as a JOB. Now your queue will have multiple jobs which are ready to get out as in FIFO sequence.
As per your questions, there are worker which listens to queue, they get a job and execute them. It's up to you how many workers you want. If you have one worker your tasks will be executed one after another, more the workers more the parallel processes.
Worker process are started with command line interface of laravel called Artisan. Each process means one worker. You can start multiple workers with supervisor.
Since you know for sure that u r going to send notification to user after around 2 mins, i suggest to use cron job to check whether any report to generate every 2 mins and if there are, you can send notification to user. That check will be a simple one query so don't need to worry about performance that much.

Multiple backend non blocking calls from NodeJS gives slow response

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.

Can EWS calls be done parallel without slowing down?

I want to retrieve information from an Excachange Server (2010 via EWS API). In detail I want build a windows service to iterate over all excachange users and index their private mailboxes using impersonalisation.
That works well but its very slow when I do this one user after another (depending on the mailbox volume and the amout of users). The indexing speed is now about 500 items per minute.
The following calls takes about 250 milliseconds on my test system:
PropertySet myPropertySet = new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.ParentFolderId);
myPropertySet.RequestedBodyType = BodyType.Text;
myPropertySet.Add(entryIdExtendedProperty);
Item item = Item.Bind(es, itemKey, myPropertySet);
So my idea was to do a parallelization. So far I tried 3 ways:
Background worker: One worker thread per user.
Result: No effect. It seems that doing this will slow down very call. In sum the overall speed stays the same.
Separate EXE processes: One EXE per user. I created a "Worker"-Exe and called them with the user as argument: IndexWorker.exe -user1
Result: Same result! The calls of every exe are slowed down!
Separate Windows Services: One service per user.
Result: Suddenly, the request did not slow down, which means I could bring the overall speed to a multiple of 500 items per minute (I triet up to 3 processes, thats 1500 items per minute). Not bad but I lets me alone with the question:
Why are EWS calls slowed down in 1) and 2) but not in 3)?
Threading would the most elegant way for me, is there any option oder setting that I may use?
I read a couple of things about Throttling Policies and the EWSFindCountLimit. Is this the right direction?
Did you get to the bottom of why the separate service gave you such an increase in performance? The throttling is applied at the Service Account level, so it should not matter where you are making the calls from.
Your issue is the throttling policy. You need to create a throttling policy for your service account that doesn't restrict EWS or RPC activity.

Resources