Saturday, September 12, 2015

How Tomcat Works



How Tomcat Works
A Simple Web Server
The Socket and ServerSocket Class


The role of a server socket is to wait for connection requests from clients. Once the server socket gets a connection request, it creates a Socket instance to handle the communication with the client.

The Request class
An instance of this class is constructed by passing the InputStream object obtained from a Socket that handles the communication with the client. You call one of the read methods of the InputStream object to obtain the HTTP request raw data.

The Response class
A Response object is constructed by the HttpServer class's await method by passing the OutputStream object obtained from the socket.

Simple Servlet Container
the init, service, and destroy methods are the servlet's life cycle methods. 
The servlet container calls the destroy method before removing a servlet instance from service. This normally happens when the servlet container is shut down or the servlet container needs some free memory. This method is called only after all threads within the servlet's service method have exited or after a timeout period has passed. After the servlet container has called the destroy method, it will not call the service method again on the same servlet. The destroy method gives the servlet an opportunity to clean up any resources that are being held, such as memory, file handles, and threads, and make sure that any persistent state is synchronized with the servlet's current state in memory.


a fully-functional servlet container does the following for each HTTP request for a servlet:
  • When the servlet is called for the first time, load the servlet class and call the servlet's init method (once only)
  • For each request, construct an instance of javax.servlet.ServletRequest and an instance of javax.servlet.ServletResponse.
  • Invoke the servlet's service method, passing the ServletRequest and ServletResponse objects.
  • When the servlet class is shut down, call the servlet's destroy method and unload the servlet class.
A servlet's service method receives a javax.servlet.ServletRequest instance and a javax.servlet.ServletResponse instance from the servlet container. This is to say that for every HTTP request, a servlet container must construct a ServletRequest object and a ServletResponse object and pass them to the service method of the servlet it is serving.

The ServletProcessor2 Class
In a servlet container, the location where a class loader can find servlet classes is called a repository.
RequestFacade requestFacade = new RequestFacade(request);
ResponseFacade responseFacade = new ResponseFacade(response);
try {
    servlet = (Servlet) myClass.newInstance();
    servlet.service((ServletRequest) requestFacade, (ServletResponse) responseFacade);
    }
Using RequestFacade or ResponseFacade to protect container's Request or Response.

Connector
The StringManager class therefore has been designed so that an instance of StringManager is shared by all objects inside a package. 

If you are familiar with design patterns, you’ll guess correctly that StringManager is a singleton class.

This chapter’s application consists of three modules: connector, startup, and core.


The startup module consists only of one class, Bootstrap, which starts the application.

the task of waiting for HTTP requests is given to the HttpConnector instance, and the task of creating request and response objects is assigned to the HttpProcessor instance.

Because the connector does not know which values will be needed by the invoked servlet, the connector must parse all values that can be obtained from the HTTP request. However, parsing an HTTP request involves expensive string and other operations, and the connector can save lots of CPU cycles if it parses only values that will be needed by the servlet. For example, if the servlet does not need any request parameter (i.e. it does not call the getParameter, getParameterMap, getParameterNames, or getParameterValues methods of javax.servlet.http.HttpServletRequest), the connector does not need to parse these parameters from the query string and or from the HTTP request body. Tomcat's default connector (and the connector in this chapter's application) tries to be more efficient by leaving the parameter parsing until it is really needed by the servlet.


Chunked Encoding

The consequence of establishing a persistent connection is that the server can send byte streams from multiple resources, and the client can send multiple requests using the same connection. As a result, the sender must send the content length header of each request or response so that the recipient would know how to interpret the bytes.


HTTP 1.1 employs a special header called transfer-encoding to indicate that the byte stream will be sent in chunks. For every chunk, the length (in hexadecimal) followed by CR/LF is sent prior to the data. A transaction is marked with a zero length 

The HttpConnector Class

The HttpConnector maintains a pool of HttpProcessor instances to avoid creating HttpProcessor objects all the time. 
private Stack processors = new Stack();

while (curProcessors < minProcessors) {
  if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
    break;
  HttpProcessor processor = newProcessor();
  recycle(processor);
}
while (!stopped) {
  Socket socket = null;
  try {
    socket = serverSocket.accept();
    HttpProcessor processor = createProcessor();
if (processor == null) {
  try {
    log(sm.getString("httpConnector.noProcessor"));
    socket.close();
  }
  ...
  continue;
}
else {
  processor.assign(socket);
}

synchronized void assign(Socket socket) {
  // Wait for the Processor to get the previous Socket
  while (available) {
    try {
      wait();
    }
    catch (InterruptedException e) {
    }
  }
  // Store the newly available Socket and notify our thread
  this.socket = socket;
  available = true;
  notifyAll();
  ...
}

private synchronized Socket await() {
  // Wait for the Connector to provide a new Socket
  while (!available) {
    try {
      wait();
    }
    catch (InterruptedException e) {
    }
  }

  // Notify the Connector that we have received this Socket
  Socket socket = this.socket;
  available = false;
  notifyAll();
  if ((debug >= 1) && (socket != null))
    log("  The incoming request has been awaited");
  return (socket);
}


Why does the await method need to use a local variable (socket) and not return the instance’s socket variable? So that the instance’s socket variable can be assigned to the next incoming socket before the current socket gets processed completely.

The SimpleContainer class implements org.apache.catalina.container so that it can be associated with the connector.

Labels

Review (572) System Design (334) System Design - Review (198) Java (189) Coding (75) Interview-System Design (65) Interview (63) Book Notes (59) Coding - Review (59) to-do (45) Linux (43) Knowledge (39) Interview-Java (35) Knowledge - Review (32) Database (31) Design Patterns (31) Big Data (29) Product Architecture (28) MultiThread (27) Soft Skills (27) Concurrency (26) Cracking Code Interview (26) Miscs (25) Distributed (24) OOD Design (24) Google (23) Career (22) Interview - Review (21) Java - Code (21) Operating System (21) Interview Q&A (20) System Design - Practice (20) Tips (19) Algorithm (17) Company - Facebook (17) Security (17) How to Ace Interview (16) Brain Teaser (14) Linux - Shell (14) Redis (14) Testing (14) Tools (14) Code Quality (13) Search (13) Spark (13) Spring (13) Company - LinkedIn (12) How to (12) Interview-Database (12) Interview-Operating System (12) Solr (12) Architecture Principles (11) Resource (10) Amazon (9) Cache (9) Git (9) Interview - MultiThread (9) Scalability (9) Trouble Shooting (9) Web Dev (9) Architecture Model (8) Better Programmer (8) Cassandra (8) Company - Uber (8) Java67 (8) Math (8) OO Design principles (8) SOLID (8) Design (7) Interview Corner (7) JVM (7) Java Basics (7) Kafka (7) Mac (7) Machine Learning (7) NoSQL (7) C++ (6) Chrome (6) File System (6) Highscalability (6) How to Better (6) Network (6) Restful (6) CareerCup (5) Code Review (5) Hash (5) How to Interview (5) JDK Source Code (5) JavaScript (5) Leetcode (5) Must Known (5) Python (5)

Popular Posts