What is the difference between asynchronous and synchronous HTTP request?
Synchronous:
A synchronous request blocks the client until operation completes. In such case, javascript engine of the browser is blocked.
Asynchronous
An asynchronous request doesn’t block the client i.e. browser is responsive. At that time, user can perform another operations also. In such case, javascript engine of the browser is not blocked.
Check out Determining synchronous vs. asynchronous in web applications for previous discussion. In short:
Asynchronous APIs do not block. Every synchronous call waits and blocks for your results to > come back. This is just a sleeping thread and wasted computation.
Asynchronous APIs do not block. Every synchronous call waits and blocks for your results to come back. This is just a sleeping thread and wasted computation.
If you need something to happen, send an asynchronous request and do further computation when the request returns. This means your thread sits idle and can pick up other work.
Asynchronous requests is the way to scale to thousands of concurrent users.
Sachin Gandhwani's answer is very well explained in simple words. In case you are still not convinced with the difference of asynchronous HTTP request and synchronous HTTP request, you can read this - https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
A synchronous client constructs an HTTP structure, sends a request, and waits for a response. An asynchronous client constructs an HTTP structure, sends a request, and moves on. In this case, the client is notified when the response arrives. The original thread, or another thread, can then process the response. Although asynchronous behavior can result in faster overall execution, synchronous behavior might be preferred in certain cases where more simplified code is necessary.
Related
A coworker and I are having a disagreement on what constitutes "completion" of a WSASend overlapped IO request. He asserts using fWait as TRUE in the WSAGetOverlappedResult call only waits until the message is queued for sending. He believes waiting for the write/send operation to "complete" only means the message was successfully initiated. In my opinion that is far from a "completed" message to the other side of the socket...that would simple be a beginning of a send and not a completion. If the fWait of TRUE does not block until the bytes have been sent and been ACKed (or error returned), then this is far from synchronous...it would in fact be acting the same as asynchronous IO because it's just fire and forget.
I have been maintaining our company's communication library with my understanding of how to do, and what is, "synchronous" IO for decades so I'll be shocked if I'm indeed wrong in my understanding. But my coworker is a brilliant developer with TONS of TCP/IP experience and is adamant he's right. Says he even posed this question here on stackoverflow and was told he was right. I can't imagine how I could be misunderstanding "completion" of a send to mean anything other than the sending of the bytes requested were indeed sent and ACKed. But I've been wrong before LOL
So...who is right? What EXACTLY does it mean to wait for a WSASend request to be "complete"? Simply waiting until the message is queued for sending in the TCP/IP stack...or waiting for all the packets that constitute the message to be both sent and ACKed??? Or is the truth somewhere in-between?
You are wrong.
A send request is completed when the request is no longer being processed. Once the stack has taken over the operation, the request is no longer being processed and its resources can be used for some other purpose.
If you were right, overlapped I/O would be nearly useless. Who would want to have to wait until the other side ACKed a previous send in its entirety before they could queue any more data to the TCP connection?
How would overlapped I/O be useful if there was no way to determine when the queing process was complete? That's what the application needs to know so it can send another chunk of data.
You would always have dead time as the send queue would always have to get completely empty before more data could be queued on the sending side. Yuck!
And knowing when the ACK is received is useless anyway. It doesn't mean the application on the other end got the data. So it has no meaning at application layer. Knowing that the send has been queued does have meaning at application layer -- it means you can now queue more data to be sent and be guaranteed that all of the data from the previous send will be passed to the receiver's application layer before any data from the next send. That's what the application needs to know.
A synchronous call to WASSend also completes when the send is queued. An asynchronous operation just means you don't have to wait for whatever you'd wait for in a synchronous operation. So that's another reason your understanding would be quite strange.
Lastly, there is no standard or common way to wait for a remote ACK with synchronous operations. So you would have to think that asynchronous operations default to providing a semantic that is not even really available with synchronous ones. That's also pretty strange.
David is correct.
WSASend will complete when that data is handed off to the TCPIP stack (buffered at their layer) to be sent whenever the transport will allow. If it's a blocking call, it will wait until it's ready to pend; just like if it's async, the OVERLAPPED I/O will complete once it pends.
Some may ask why is this even necessary? This is behavior is crucial for keeping as much data in-flight over a TCP connection. In order to keep as much data in-flight, a sender should call WSASend until it pends (recall if it's a synchronous WSASend call then that thread will just block until WSASend can complete; if it's asynchronous, the async completion will occur once that WSASend call can pend).
Why would WSASend ever pend, why not just complete immediately? WSASend will only complete once the transport (in kernel) is ready to buffer more data. So looping until WSASend pends will keep that connection flush with enough data to keep the maximum data in-flight.
Hope this makes sense.
My testing seems to show I am indeed wrong. Synchronous behavior does not exist for sending...just receiving. I see how this is a performance help, but I object to all documentation saying sending fWait of TRUE in WSAGetOverlappedResult will wait until the IO request is "complete". This word implies much more than just it being queued up. Well..I'm flabbergasted that my understanding was off...but TCP handles things well enough that it hasn't caused me issues before.
Thanks for the excellent replies and patience with my frustrated replies. I'm incredibly disappointed at how all the documentation is written using words that would imply my understanding was right...when all along waiting for IO to "end", "complete", "finish" absolutely does NOT wait.
I am trying to write a HTTP API server which does basic CRUD operation on a specific resource. It talks to an external db server to do the operations.
Future support in scala is pretty good, and for all non-blocking computation, future is used. I have used future in many places where we wrap an operation with future and move on, when the value is eventually available and the call back is triggered.
Coming to an HTTP API server's context, it is possible to implement non-blocking asynchronous calls, but when a GET or a POST call still blocks the main thread right?
When a GET request is made, a success 200 means the data is written to the db successfully and not lost. Until the data is written to the server, the thread that was created is still blocking until the final acknowledgement has been received from the database that the insert is successful right?
The main thread(created when http request was received) could delegate and get a Future back, but is it still blocked until the onSuccess is trigged which gets triggered when the value is available, which means the db call was successful.
I am failing to understand how efficiently a HTTP server could be designed to maximize efficiency, what happens when few hundred requests hit a specific endpoint and how it is dealt with. I've been told that slick takes the best approach.
If someone could explain a successful http request lifecycle with future and without future, assuming there are 100 db connection threads.
When a GET request is made, a success 200 means the data is written to
the db successfully and not lost. Until the data is written to the
server, the thread that was created is still blocking until the final
acknowledgement has been received from the database that the insert is
successful right?
The thread that was created for the specific request need not be blocked at all. When you start an HTTP server, you always have the "main" thread ongoing and waiting for requests to come in. Once a request starts, it is usually offloaded to a thread which is taken from the thread pool (or ExecutionContext). The thread serving the request doesn't need to block anything, it only needs to register a callback which says "once this future completes, please complete this request with a success or failure indication". In the meanwhile, the client socket is still pending a response from your server, nothing returns. If, for example, we're on Linux and using epoll, then we pass the kernel a list of file descriptors to monitor for incoming data and wait for that data to become available, in which we will get back a notification for.
We get this for free when running on top of the JVM due to how java.NIO is implemented for Linux.
The main thread (created when http request was received) could delegate
and get a Future back, but is it still blocked until the onSuccess is
trigged which gets triggered when the value is available, which means
the db call was successful.
The main thread usually won't be blocked, as it is whats in charge of accepting new incoming connections. If you think about it logically, if the main thread blocked until your request completed, that means that we could only serve one concurrent request, and who wants a server which can only handle a single request at a time?
In order for it to be able to accept multiple request, it will never handle the processing of the route on the thread in which it accepts the connection, it will always delegate it to a background thread to do that work.
In general, there are many ways of doing efficient IO in both Linux and Windows. The former has epoll while the latter has IO completion ports. For more on how epoll works internally, see https://eklitzke.org/blocking-io-nonblocking-io-and-epoll
First off, there has to be something blocking the final main thread for it to keep running. But it's no different than having a threadpool and joining to it. I'm not exactly sure what you're asking here, since I think we both agree that using threads/concurrency is better than a single threaded operation.
Future is easy and efficient because it abstracts all the thread handling from you. By default, all new futures run in the global implicit ExecutionContext, which is just a default threadpool. Once you kick of a Future request, that thread will spawn and run, and your program execution will continue. There are also convenient constructs to directly manipulate the results of a future. For example, you can map, and flatMap on futures, and once that future(thread) returns, it will run your transformation.
It's not like single threaded languages where a single future will actually block the entire execution if you have a blocking call.
When you're comparing efficiency, what are you comparing it to?
In general "non-blocking" may mean different things in different contexts: non-blocking = asynchronous (your second question) and non-blocking = non-blocking IO (your first question). The second question is a bit simpler (addresses more traditional or well-known aspect let's say), so let's start from it.
The main thread(created when http request was received) could delegate and get a Future back, but is it still blocked until the onSuccess is trigged which gets triggered when the value is available, which means the db call was successful.
It is not blocked, because Future runs on different thread, so your main thread and thread where you execute your db call logic run concurrently (main thread still able to handle other requests while db call code of previous request is executing).
When a GET request is made, a success 200 means the data is written to the db successfully and not lost. Until the data is written to the server, the thread that was created is still blocking until the final acknowledgement has been received from the database that the insert is successful right?
This aspect is about IO. Thread making DB call (Network IO) is not necessary blocked. It is the case for old "thread per request" model, when thread is really blocked and you need create another thread for another DB request. However, nowadays non-blocking IO became popular. You can google for more details about it, but in general it allows you to use one thread for several IO operations.
I was wondering what is should do in my case. I have to get data from a rest server and display it on my application. The UI for this is a webview and if no data is received from the server then there is nothing to display on the screen. In this case do i use an async request or a sync request? Also my other question is what is the difference between an async request as opposed to sync request on a seperate thread? (I thought thats what async does anyway).. ANy help would be greatly appreciated. Im a newbie to ios.. Thanks
You should always use asynchronous loading of network requests. Never block the main thread waiting for a network response.
Asynchronous can be either synchronous on a separate thread, or scheduled in the run loop of any thread.
Hope this helps!
The difference between Asynchronous and Synchronous is that Synchronous is the more efficient method of PC communication. However Asynchronous is the most common method of communication used for email applications, internet access and networking. Synchronous is usually used for transmission of large data bocks.
I have a queue of jobs that need to be processed, the queue is periodically kicked by a timer but also by calling threads when a new job is added to the queue.
When the queue is kicked I want to initiate the processing of the queue on another thread as I don't want to block the calling thread (Which in a lot of cases will be the UI thread).
So to do this I run a grand central dispatch operation on the high priority concurrent queue, this creates an instance of my http class and submits the job through it (A job is essentially an http request).
The http class executes requests async using NSURLConnection internally.
My problem is the GCD operation finishes (As it has submitted all the async http requests) so then I guess the thread it was running on is either cleaned up and reused or exits. Which is wiping out my http classes that are in the process of doing these async web requests.
My question is, how do I make my http class hang around and finish processing the request without making the GCD operation wait for them?
Cheers
The main purpose of an asynch http would be not to block the main thread, since you are using a background thread through operation queue I'd say it is already taken care of. So what lacks if a defined end of processing where you can get your data back.
I'd say synchronous http would be cleaner to design and easier to support. You could use a NSURLConnection which has a synchronous method:
[NSURLConnection sendSynchronousRequest:returningResponse:error:]
I also just found a library that provides synchronouse mode of operation and promises to make cocoa (incl. cocoa touch) networking programming much easier: ASIHttpRequest
I have seen many a web framework provide a non-blocking web server, I just want to know what it means.
a blocking web-server is similar to a phone call. you need to wait on-line to get a response and continue; where as a non-blocking web-server is like a sms service. you sms your request,do your things and react when you receive an sms back!
Using a blocking socket, execution will wait (ie. "block") until the full socket operation has taken place. So, you can process any results/responses in your code immediately after. These are also called synchronous sockets.
A non-blocking socket operation will allow execution to resume immediately and you can handle the server's response with a callback or event. These are called asynchronous sockets.
Non-blocking generally means event driven, multiplexing all activity via an event driven system in a single thread, as opposed to using multiple threads.