Tomcat和Jetty对WebSocket的支持
一調(diào)研才發(fā)現(xiàn),如今非常多主流的web框架都已經(jīng)開(kāi)始支持WebSocket了,不得不感慨時(shí)間太快,科技進(jìn)步太快,在微策略的幾年真的荒廢了。不多說(shuō),先記錄下今天的研究。
Tomcat:
? ? ? ?J2EE以下用的最多的容器應(yīng)該就是tomcat了。說(shuō)到tomcat對(duì)WebSocket的支持,不得不先提一下,眼下的WebSocket協(xié)議已經(jīng)經(jīng)過(guò)了好幾代的演變。不同瀏覽器對(duì)此協(xié)議的支持程度也不同。因此,假設(shè)作為server。最理想的是支持盡可能多的WebSocket協(xié)議版本號(hào)。
tomcat8真正支持jsr-356(包括對(duì)websocket的支持)。 tomcat7支持部分版本號(hào)的websocket實(shí)現(xiàn)不兼容jsr-356。因此,能用tomcat8的話,還是盡量用。
代碼實(shí)現(xiàn)相當(dāng)簡(jiǎn)單,下面是一個(gè)列子,僅僅須要tomcat8的基本庫(kù),不須要其它依賴。
import java.io.IOException; import javax.websocket.OnClose; import javax.websocket.OnMessage; import javax.websocket.OnOpen; import javax.websocket.Session; import javax.websocket.server.ServerEndpoint; @ServerEndpoint("/websocket") public class WebSocketTest { @OnMessage public void onMessage(String message, Session session) throws IOException, InterruptedException { // Print the client message for testing purposes System.out.println("Received: " + message); // Send the first message to the client session.getBasicRemote().sendText("This is the first server message"); // Send 3 messages to the client every 5 seconds int sentMessages = 0; while (sentMessages < 3) { Thread.sleep(5000); session.getBasicRemote().sendText("This is an intermediate server message. Count: " + sentMessages); sentMessages++; } // Send a final message to the client session.getBasicRemote().sendText("This is the last server message"); } @OnOpen public void onOpen() { System.out.println("Client connected"); } @OnClose public void onClose() { System.out.println("Connection closed"); } }Jetty:
? ? ? ?Jetty和Tomcat一樣,也是一個(gè)Servlet的容器。假設(shè)說(shuō)不同之處,那么最大的不同應(yīng)該是Tomcat採(cǎi)用的是BIO處理方式,也就是說(shuō)一個(gè)request會(huì)用一個(gè)線程去處理,即使是WebSocket這樣的長(zhǎng)連接,也是會(huì)獨(dú)立開(kāi)一個(gè)線程。
作為一個(gè)普通的Webserver,tomcat能夠輕松應(yīng)對(duì)耗時(shí)比較短的Request/Response。可是假設(shè)換成是長(zhǎng)連接的WebSocket。那麻煩就來(lái)了,對(duì)于上萬(wàn)用戶的聊天和推送,總不能開(kāi)上萬(wàn)個(gè)線程去處理吧。此時(shí),Jetty的性能就體現(xiàn)出來(lái)了。Jetty採(cǎi)用的是NIO,一個(gè)線程能夠處理多個(gè)WebSocket的長(zhǎng)鏈接,假設(shè)你的需求是大量耗時(shí)比較長(zhǎng)的request或者大量長(zhǎng)連接,那么建議採(cǎi)用Jetty。
? ? ? ? Jetty對(duì)WebSocket的實(shí)現(xiàn)有點(diǎn)繞,Servlet不再是繼承原來(lái)的HttpServlet。而是繼承WebSocketServlet。此處要注意導(dǎo)入jetty-util.jar和jetty-websocket.jar兩個(gè)包,否則可能會(huì)有class not found錯(cuò)誤。
ReverseAjaxServlet.java:
import java.io.IOException; import java.util.Date; import java.util.Random;import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import org.codehaus.jettison.json.JSONArray; import org.eclipse.jetty.websocket.WebSocket; import org.eclipse.jetty.websocket.WebSocketServlet;/*** @author Mathieu Carbou (mathieu.carbou@gmail.com)*/ public final class ReverseAjaxServlet extends WebSocketServlet {private final Endpoints endpoints = new Endpoints();private final Random random = new Random();private final Thread generator = new Thread("Event generator") {@Overridepublic void run() {while (!Thread.currentThread().isInterrupted()) {try {Thread.sleep(random.nextInt(5000));endpoints.broadcast(new JSONArray().put("At " + new Date()).toString());} catch (InterruptedException e) {Thread.currentThread().interrupt();}}}};@Overridepublic void init() throws ServletException {super.init();generator.start();}@Overridepublic void destroy() {generator.interrupt();super.destroy();}@Overridepublic WebSocket doWebSocketConnect(HttpServletRequest request, String protocol) {return endpoints.newEndpoint();}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {resp.getWriter().write("11111");} }
Endpoints.java:
Endpoint.java
總結(jié)
以上是生活随笔為你收集整理的Tomcat和Jetty对WebSocket的支持的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Jetty 与 Tomcat 比较,及性
- 下一篇: springboot-websocket