When a request is made to a web page, and it is handled via a servlet (which is processed via tomcat), once you enter processing at the servlet level (or a spring mvc controller), has the entire request header/body/etc. been sent from the client to the server already?
Say the client is performing a http POST to a web page, and the post contains allot of form elements.
Will all this data be going through tomcat and your executing servlet or if you don’t actually reference:
request.getParamater("abc")
Then you won’t incurr that extra load since it won’t be streamed?
I cannot find a reference but I belive that the servlet starts processing once the whole header is available (all request headers followed by two newlines). That’s why you have
getInputStream()andgetReader()rather thangetBody()returningStringorbyte[].This way the servlet can start handling the request data while the client is still sending it, allowing servlets to process very large amounts of data with small memory footprint. For instance upload servlet can read uploaded file byte by byte and save it to disk without the need to have full request contents in memory at the same time.
Here is a servlet I used for testing (in Scala, sorry for that):
Now I use
ncto simulate slow client:Nothing happens on the server side. I now manually send some HTTP headers:
Still nothing happens on the server side. Tomcat accepted the connection but haven’t yet invoked
UploadServlet.doPost. But the moment I hit Enter two times, the servlet prints thenameparameter but blocks ongetLines()(getInputStream()underneath).I can now send lines of text (Tomcat expects
10000000bytes) usingncand they are incrementally printed on the server side (input.getLines()returns anIterator[String]blocking until new line is available).Servlets summary
Tomcat waits for the whole HTTP header before it starts processing the request (passing it to matching servlet)
Request body does not have to be fully available prior to
doPost()invocation. This is fine, otherwise we would soon run out of memory.The same applies to sending response – we can do this incrementally.
Spring MVC
With Spring MVC you have to be careful. Consider the following two methods (note different argument types):
Entering
/upload/goodwill invokegoodUploadhandler method as soon as HTTP header is received but it will block if you try to readbodyInputStreamif no body has yet been received.However
/upload/badwill wait until the wholePOSTbody is available since we have explicitly requested the whole body as a byte array (Stringwould have the same effect):@RequestBody body: Array[Byte].So it is up to you how Spring MVC handles large request bodies.
TCP/IP level
Remember that HTTP works on top of TCP/IP. Just because you haven’t called
getInputStream()/getReader()doesn’t mean that the server is not receiving the data from the client. In fact, the operating system manages the network socket and keeps receiving TCP/IP packets, which aren’t consumed. It means that the data from the client is pushed to the server, but the operating system has to buffer that data.Maybe somebody more experienced can answer what is happening in this situations (not really a question for this site). O/S may close the socket abruptly if the server does not read incoming data or it may simply buffer it and swap if the buffer grows to large? Another solution might be to stop acknowledging client packets, causing the client to slow down/stop. Really depends on the O/S, not on HTTP/servlets.