I'm using Square's Tape library to persist HTTP Request Tasks to disk so that if I make a request and it fails due to things like network errors or server issues, the request won't be lost and can be tried again later.
Is there a recommended strategy for removing "bad" tasks from the ObjectQueue? I can imagine a possible scenario where you create a malformed HTTP request task, add it to the task queue, and then try to process it in a service like in the tape-sample code. Because the request is malformed (or maybe the service its trying to hit has been retired), the request never succeeds and the request just kinda sits in the queue forever blocking further added requests from ever being processed. I suppose one option could be to keep track of the number of failed attempts for the head task.
Related
I have an Android client app that sends some data to a server in Python, where the Python server is supposed to run a long time-consuming operation/computation and return the results to the client.
To do so, I initially started using Flask with Python on the server side, and an asynchronous android http library on the client side to send the data via http POST. However, I quickly noticed that this is not the way to go, because the computation on the server takes time which causes problems such as the client getting timeout errors ... etc.
Then, I started using Tornado's Websockets on the server side, and an android library for websockets on the client side. However, the first main problem is that when the server is running the time-consuming operation for a given client, the other potential clients need to wait ... and it seems a bit of a pain to make tornado work in a multi-threaded setting (as it is originally planned to be single-threaded). Another minor problem, is if the client goes off-line while the server is processing his request, then the client might never get the result when he connects back.
Therefore, I would like to ask if you have any solutions or recommendation on what to use if I want to have such a setting with an asynchronous multi-threaded Python server who is supposed to do heavy-cpu computations with data from a client without making the other potential clients wait for their turn; and potentially making the client able to get the result from the server when he connects back.
FIrst of all, if you're going to do cpu-heavy operations in your backend, you [most probably] need to run it in separate process. Not in thread/coro/etc. The reason is that python is limited to single thread at time (you may read more about GIL). Doing cpu-heavy operation in multithreading gives your backend some availability, but hits performance overall.
Simple/old solution for this — run your backend in multiple process (and threads, preferably). I.e. deploy your flask with gunicorn, give it multiple worker processes. This way, you'll have system that capable of doing number_of_processes - 1 heavy computations and still be available for handling requests. Limit for processes is usually up to cpu_cores * 2, depending on cpu arch.
Slightly more complicated:
accept data
run heavy function in different process
gather result, return
Great interface for this would be ProcessPoolExecutor. The drawback is — it's harder to handle failures/process hanging over
Another way around is task queue + workers. One of most used is celery. Idea is to
open WS connection
put task in queue
worker (in different process or even different physical node) eventually picks up task, compute it, put result in some DB
main process gets callback/result of long polling over result DB
main process sends result over WS
This is more suited for really heavy and not real-time tasks, but gives you out-of-the-box handling for failures/restarts/etc.
I've read alot of different recommendations on how to use locks - but the behavior of my current code in both IOS and Android does not behave correctly.
What I'm trying to do is build a queue system with a HTTP Request. If a Request fails, it should be the first request to be retried. Both send and add to queue is in the same method, so it shall not add a new object into the queue until the previous request has finished. If one fails and when the next request gets added it would send two requests (in the same package and clearing the queue).
Android:
// Java
synchronized(locker)
{
Add object to a queue if there is a new object to be added
If any objects in queue - send request with AsyncTask
}
IOS:
// Objective-C
#synchronized(locker)
{
Add object to a queue if there is a new object to be added
If any objects in queue - send request with NSURLSessionDataTask
}
...and on fail, do not remove the object from the queue.
In this case - I am guessing that the lock does get released and another thread could possibly be sending the next request right away and come first since the tasks are dispatched in another thread?
I've tried with normal locks with some success on Android and complete failure on iOS where the entire system freezed up. Since then I've read about locking a lock on IOS that it has to be unlocked by the same thread - would a dispatch_async(dispatch_get_main_queue()... on the entire method work or would I have to dispatched it again when the completitionHandler finishes? Can I be certain that the completitionHandler is called on the same thread as the method creating it?
It's very important that each package are sent in the correct order. What is the best approach towards a multithreaded HTTP Request system like this?
Don't spawn new threads by AsyncTask or NSURLSessionDataTask. If you need the threads to serialize, i.e. at most one of them may run at the same time, and the next one has to wait for the first one to finish completely, there's absolutely no reason to run multiple threads.
You're going to want one (1) thread for all requests, and maybe send data to it using a queue. Otherwise, the UI might freeze while sending http requests.
I am using retrofit on the android side and node.js on the backend side.
Retrofit allows async requests, so can I send two requests from android in parallel on the server and get the result back, or I can send one request and use caolan async to run two different requests in parallel.
Which request should I use from retrofit? Should I send parallel requests or execute them as one request in parallel?
I think the second approach is better because the first approach increases server requests which adds to the server load.
Please tell me, which approach should I use?
Your milage may vary but in general batching saves opening and closing multiple connections. I've had gains in performance once I started batching multiple requests together rather than having to open and close a connection for each request. Best way to find out for your use case is to write a test for both and compare.
I have 2 class of AsyncTask for handling request one for sync and other class for handling other request but when I send sync request and move to other page and request response for second request will get after sync request responds. How I solution this?
Hope any one help me
Basically you can use Volley
Volley offers the following benefits:
Automatic scheduling of network requests.
Multiple concurrent network connections.
Transparent disk and memory response caching with standard HTTP
cache coherence.
Support for request prioritization.
Cancellation request API. You can cancel a single request, or you
can set blocks or scopes of requests to cancel.
Ease of customization, for example, for retry and backoff.
Strong ordering that makes it easy to correctly populate your UI
with data fetched asynchronously from the network.
Debugging and tracing tools.
You can easily find a tutorial for it and
It much faster then AsyncTask .
For reference check this
You can make asyntask run parallel execution by replacing execute() with executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR).
I am using volley library for performing network operation to speed up the things. My Question is that Does Volley executes the requests which have added in the queue sequentially or parallel.
Suppose I add request like Req1, Req2, Req3 , Will they start to run parallel or second request will wait until first finished ??
According to the Volley documentation
Volley maintains several network threads. If a thread is not doing anything, then it will take on a job in the queue.
To answer your question, Req1, Req2 and Req3 will each be placed in a worker thread and will run in parallel.
Volley also caches your downloaded data (and determines whether to re-download based on the expire time in the HTTP header of the downloaded data), so if your data doesn't need to be downloaded again, it's fetched from the cache, which is faster than re-downloading.
These are some of the reasons that Volley is proclaimed to be faster than standard network operations for the situations that it's appropriate to use it. You can, of course, implement this yourself, but Google has done a lot of the hard work for you.
Usually a queue starts each operation according to the order it was queued, unless it's a priority queue.
Therefore, assuming equal priority (Assuming that the Volley queue is non priority queue), we can conclude that Req1 will get started first. Then Req2, followed by Req3.
However, we can not guarantee the order which each finishes. If Req1 is time consuming, then the requests will finish in a different order than Req1, Req2, Req3.
All we can guarantee is that they will be started in the order Req1, Req2, Req3.