Comet模式是一种服务器端推技术,它的核心思想提供一种能让当服务器端往客户端发送数据的方式。Comet模式为什么会出现?刚开始人们在客户端通过不断自动刷新整个页面来更新数据,后来觉得体验不好又使用了AJAX不断从客户端轮询服务器更新数据,然后是使用Comet模式由服务器端通过长连接推数据。Comet模式能大大减少发送到服务器端的请求从而避免了很多开销,而且它还具备更好的实时性。

如图所示,客户端发送一个请求到服务器,服务器接收了连接后一直保持住连接不关闭;接着客户端发送一个操作报文告诉服务器需要做什么操作,服务器处理完事件1后会给客户端响应,然后处理完事件2后又会给客户端响应;然后客户端继续发送操作报文给服务器,服务器再进行响应。

一般Comet模式需要NIO配合,而在BIO中无法使用Comet模式。在Tomcat内部集成Comet模式的思路也比较清晰,引入了一个CometProcessor接口,此接口只有一个event方法,具体接口代码如下:

public interface CometProcessor extends Servlet{
    public void event(CometEvent event)
        throws IOException, ServletException;
}

而CometEvent则表示Comet相关的事件,它包含四BEGIN, READ, END, ERROR四个事件,分别表示:

① BEGIN,表示请求开始,此时客户端连接已被接收。

② READ,表示可以读取客户端连接,你可以开始读取数据了,读取的过程不会阻塞。

③ END,表示请求结束,此时客户端连接将被断开。

④ ERROR,表示发生了IO异常,一般将会结束此次请求并且连接会被断开。

下面看一个简单的例子:

public class CometServlet extends HttpServlet implements CometProcessor {

    protected ArrayList connections = new ArrayList();

    public void event(CometEvent event) throws IOException, ServletException {
        HttpServletRequest request = event.getHttpServletRequest();
        HttpServletResponse response = event.getHttpServletResponse();
        if (event.getEventType() == CometEvent.EventType.BEGIN) {
            synchronized (connections) {
                connections.add(response);
            }
        } else if (event.getEventType() == CometEvent.EventType.ERROR) {
            synchronized (connections) {
                connections.remove(response);
            }
        }else if (event.getEventType() == CometEvent.EventType.END) {
            synchronized (connections) {
                connections.remove(response);
            }
        } else if (event.getEventType() == CometEvent.EventType.READ) {
            InputStream is = request.getInputStream();
            byte[] buf = new byte[512];
            do {
                int n = is.read(buf);
                if (n > 0) {
                    System.out.println(new String(buf, 0, n));
                } else if (n < 0) {
                    return;
                }
            } while (is.available() > 0);
        }
    }
}

这个例子中只是简单的客户端连接都接收起来而不做任何处理,并将客户端发送过来的数据输出。很容易理解,在BEGIN事件中接收连接并把响应对象假如到列表中,发送ERROR或END事件时则将响应对象移除,当READ事件时则读取数据并输出。

有了CometProcessor接口后,Tomcat内部就可以识别Comet模式的Servlet了,我们知道Tomcat对请求的处理是管道模式的,所以在Wrapper容器的管道中判断加载的Servlet是否继承了CometProcessor,继承则说明是Comet模式,则使用Comet方式处理。它的处理过程如图,当一个客户端连接到来,被接收器接收后注册到NioChannel队列中,Poller组件不断轮询是否有NioChannel需要处理,如果有则调用前面实例化的Comet模式Servlet,这里主要用到CometProcessor接口的event方法,Poller会将对应的请求对象、响应对象和事件封装成都CometEvent对象并传入event方法。此时即执行event方法的逻辑,完成对不同事件的处理,从而实现了Comet模式。

Tomcat如何实现Comet的更多相关文章

  1. 75篇关于Tomcat源码和机制的文章

    75篇关于Tomcat源码和机制的文章 标签: tomcat源码机制 2016-12-30 16:00 10083人阅读 评论(1) 收藏 举报  分类: tomcat内核(82)  版权声明:本文为 ...

  2. Tomcat组成与工作原理

    laosijikaichele 关注  0.2 2018.06.02 10:44 字数 5175 阅读 2798评论 0喜欢 8 原文:https://juejin.im/post/58eb5fdda ...

  3. Tomcat开发Comet要点

    Comet技术的悄然流行,Jetty在比较早地支持了Comet,提供了Comet 的Servlet,同样从Tomcat6开始,Comet已经在Tomcat的标准Servlet中开始支持了,这是个好事情 ...

  4. windows 环境下nginx + tomcat群 + redis 实现session共享

    nginx作为负载均衡根据定义将不同的用户请求分发到不同的服务器,同时也解决了因单点部署服务器故障导致的整个应用不能访问的问题 在加入nginx之后,如果多个服务器中的一个或多个(不是全部)发生故障, ...

  5. tomcat连接器

    Connector是Tomcat最核心的组件之一,负责处理一个WebServer最核心的连接管理.Net IO.线程(可选).协议解析和处理的工作.一.连接器介绍在开始Connector探索之路之前, ...

  6. Java后端WebSocket的Tomcat实现

    转自:http://blog.chenzuhuang.com/archive/28.html 文章摘要随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5 ...

  7. Comet:基于 HTTP 长连接的“服务器推”技术解析

    原文链接:http://www.cnblogs.com/deepleo/p/Comet.html 一.背景介绍 传统web请求,是显式的向服务器发送http Request,拿到Response后显示 ...

  8. 【Tomcat】Tomcat Session在Redis共享

    参考的优秀文章 Redis-backed non-sticky session store for Apache Tomcat 简单地配置Tomcat Session在Redis共享 我使用的是现有的 ...

  9. tomcat架构

    很多开源应用服务器都是集成tomcat作为web container的,而且对于tomcat的servlet container这部分代码很少改动.这样,这些应用服务器的性能基本上就取决于Tomcat ...

随机推荐

  1. Linux OpenGL 实践篇-5 纹理

    纹理 在之前的实践中,我们所渲染的物体的表面颜色都是纯色或者根据顶点位置计算出的一个颜色,这种方式在表现物体细节方面是比较吃资源的,因为我们每增加一个细节,我们就需要定义更多的顶点及其属性.所以美术人 ...

  2. SQL SERVER 索引名前缀代表的意思

    PK - Primary Key IX - Non-Unique Index AK - Unique Index (AX should have been AK (Alternate Key)) CK ...

  3. [LeetCode] Falling Squares 下落的方块

    On an infinite number line (x-axis), we drop given squares in the order they are given. The i-th squ ...

  4. [LeetCode] Remove Comments 移除注释

    Given a C++ program, remove comments from it. The program source is an array where source[i] is the ...

  5. Spring--bean的作用范围

    在Spring中,bean的作用范围分以下几种: singleton:spring ioc容器中仅有一个bean实例,bean以单例的方式存在 prototype:每次从容器中调用bean时,都返回一 ...

  6. C++Primer学习——类

    我们在创建类的对象时,类不应该仅仅被声明,还应该被定义过,否则无法知道类占用了多少的内存 但是如果一个类的名字已经出现过就被认为是已经声明过了,所以允许包含自己的指针或者引用. 默认构造函数: 当类中 ...

  7. hdu 5119(2014北京)

    题意: 随机选择一个数,如果后面有比他小的就进行交换,直到没有为止(算一轮).求多少轮后为递增序列 思路: 倒着找,如果有比经过的最小数大的,ans+1 #include <iostream&g ...

  8. hdu 3436 splay树+离散化*

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  9. Python的IO编程

    原文传送门:请点击 原文传送门:请点击

  10. Intellij idea: java.lang.ClassNotFoundException:javax.el.ELResolver异常解决办法

    使用Intellij idea编译过程中遇到的问题及解决办法. 由于编译时候报javax.servlet不存在,我把tomcat下的servlet-api.jar放到了External Librari ...