Turn: http://java.csdn.net/page/2c89de24-b042-4a55-abf1-0db9bdef3aba
Start
In this article, I will show you how to use different Java technologies to build some simple comet web applications. Readers should have some knowledge about Java Servlet, Ajax and JavaScript. We will examine some of the features that support comet in Tomcat and jetty, so we need to use the latest versions of these two products. This article uses Tomcat 6.0.14 and jetty 6.1.14. in addition, a JDK that supports Java 5 or later is required. this article uses JDK 1.5.0-16. we also need to check the pre-release version of jetty 7 because it implements the servlet 3.0 specification. We will study this specification in this article.
Understanding comet
You may have heard of comet because it has received some attention recently. Comet is sometimes called reverse Ajax or server-side push ). The idea is simple: Push data directly from the server to the browser without waiting for the browser to request data. It sounds simple, but if you are familiar with Web applications, especially HTTP, you will know that this is not simple. Implementing comet web applications and ensuring scalability on browsers and servers is only possible in recent years. Later in this article, we will look at how some popular Java Web servers support the Scalable comet architecture, but first let's look at why we need to create a comet application, and common design patterns used to implement them.
Motivation for using comet
There is no doubt about the success of the HTTP protocol. It is the basis for most information exchange on the Internet. However, it also has some limitations. In particular, it is a stateless, one-way protocol. The request is sent to the Web server, and the server processes the request and returns a response concurrently-that's all. The request must be sent by the client, while the server can only send data in the response to the request. This will at least affect the practicability of many types of Web applications. A typical example is a chat program. There are also some examples, such as the score of the game, stock quotes or email programs.
These limitations of HTTP are also the reason for its success. The request/response cycle makes it a classic model, that is, each connection uses a thread. This method has huge scalability as long as it can quickly provide services for requests. A large number of requests can be processed every second, and a large number of users can be processed with only a small number of servers. This is ideal for many classic web applications, such as content management systems, search applications, and e-commerce sites. In any of the preceding web applications, the server provides the data requested by the user, closes the connection, and releases the thread so that it can serve other requests. If interaction still exists after the initial data is provided, the connection is kept in the open state, so the thread cannot be released and the server cannot serve many users.
However, what if I want to maintain interaction with users after responding to the request and sending the initial data? In the early days of the Web, Meta Refresh was often used. This will automatically instruct the browser to re-load the page after a specified number of seconds, so as to support simple round robin (polling ). This is not only a bad user experience, but also usually very inefficient. What if no new data is displayed on the page? At this time, you have to re-render the same page. What if there are few changes to the page and most of the pages do not change? Similarly, whether necessary or not, you have to request and retrieve all the content on the page.
The invention and popularity of Ajax have changed the above situation. Now, the server can communicate asynchronously, so you do not have to request the whole page again. You can perform incremental updates. You only need to use XMLHttpRequest to poll the server. This technology is often referred to as Comet. There are some variants of this technology, each of which has different performance and scalability. Let's take a look at these different types of comet.
Comet Style
The emergence of Ajax makes comet possible. The unidirectional nature of HTTP can be effectively avoided. There are actually some different ways to bypass this. As you may have guessed, the easiest way to support comet is poll ). Use XMLHttpRequest to send a call to the server. Wait for a fixed period of time (usually using the Javascript setTimeout Function) after the return, and then call it again. This is a very common technology. For example, most webmail applications use this technology to display emails when an email arrives.
This technology has advantages and disadvantages. In this case, you expect a quick response, just like any other Ajax request. There must be a pause between requests. Otherwise, continuous requests will throw the server, and in this case it is obviously not scalable. This pause causes a latency for the application. The longer the pause time, the more time it takes for new data on the server to arrive at the client. If the pause time is shortened, the server may be overwhelmed again. On the other hand, this is obviously the simplest way to implement comet.
It should be pointed out that many people think that polling does not belong to comet. On the contrary, they think that comet is a solution to the limitations of polling. The most common "true" comet technology is a variant of polling, namely long polling ). The main difference between polling and long polling is how long the server takes to respond. Long polling usually keeps the connection for a long period of time-usually several seconds, but it may also be one minute or longer. When an event occurs on the server, the response is sent and immediately closed, and the polling starts again immediately.
The advantage of long polling over general polling is that once data is available, it is immediately sent from the server to the client. The request may wait for a long time, during which no data is returned, but once new data is generated, it will be immediately sent to the client. Therefore, there is no latency. If you have used a Web-based chat program or any program that claims to be "real-time", it is likely to use this technology.
Long polling has a variation, which is the third type of Comet. This is usually called streaming ). In this style, the server pushes data back to the client, but does not close the connection. The connection will remain open until it expires and the request is resent. The XMLHttpRequest specification indicates that you can check whether the value of readystate is 3 or loading ing (instead of 4 or loaded) and obtain the data that is "Flowing" from the server. Like long polling, this method has no latency. When the data on the server is ready, the data is sent to the client. Another advantage of this method is that it can greatly reduce the number of requests sent to the server, thus avoiding overhead and latency related to setting server connections. Unfortunately, XMLHttpRequest has many different implementations in different browsers. This technology can only be used reliably in later versions of Mozilla Firefox. Long polling is still required for Internet Explorer or safari.
At this point, you may think that long polling and stream have a big problem. The request must exist on the server for a long time. This breaks the model of using one thread for each request, because the thread used for one request has never been released. Worse, the thread remains idle unless data is sent back. This is obviously not scalable. Fortunately, modern Java Web servers can solve this problem in many ways.
Comet in Java
Currently, many web servers are built in Java. One reason is that Java has a rich local thread model. Therefore, implementing a typical model that connects one thread is very simple. This model is not suitable for Comet, but Java has the same solution. To effectively process comet, non-blocking Io is required. Java provides non-blocking Io through its NiO library. both Apache Tomcat and jetty, the two most popular open-source servers, use NiO to add non-blocking Io to support comet. however, the implementations of these two servers are different. Let's take a look at Tomcat and jetty's support for Comet.
Tomcat and comet
For Apache Tomcat, to use Comet, you mainly need to do two things. First, you need to slightly modify the tomcat configuration file server. xml. By default, more typical synchronous I/O connectors are enabled. Now you only need to switch it to the asynchronous version, as shown in Listing 1.
Listing 1. Modifying Tomcat server. xml
Listing 2. Tomcat comet Servlet
Public class tomcatweatherservlet extends httpservlet implements cometprocessor {<br/> private messagesender = NULL; <br/> Private Static final integer timeout = 60*1000; <br/> @ override <br/> Public void destroy () {<br/> messagesender. stop (); <br/> messagesender = NULL; <br/>}< br/> @ override <br/> Public void Init () throws servletexception {<br/> messagesender = new messagesender (); <br/> thread messagesenderthread = <br/> New thread (messagesender, "messagesender [" + getservletcontext () <br/>. getcontextpath () + "]"); <br/> messagesenderthread. setdaemon (true); <br/> messagesenderthread. start (); <br/>}< br/> Public void event (final cometevent event) throws ioexception, servletexception {<br/> httpservletrequest request = event. gethttpservletrequest (); <br/> httpservletresponse response = event. gethttpservletresponse (); <br/> If (event. geteventtype () = cometevent. eventtype. begin) {<br/> request. setattribute ("org. apache. tomcat. comet. timeout ", timeout); <br/> log (" begin for session: "+ request. getsession (true ). GETID (); <br/> messagesender. setconnection (response); <br/> weatherman = new weatherman (95118,324 08); <br/> New thread (weatherman ). start (); <br/>}else if (event. geteventtype () = cometevent. eventtype. error) {<br/> log ("error for session:" + request. getsession (true ). GETID (); <br/> event. close (); <br/>}else if (event. geteventtype () = cometevent. eventtype. end) {<br/> log ("End for session:" + request. getsession (true ). GETID (); <br/> event. close (); <br/>}else if (event. geteventtype () = cometevent. eventtype. read) {<br/> throw new unsupportedoperationexception ("this servlet does not accept <br/> data "); <br/>}< br/>