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. a标签点击页面刷新但还保存当前点击的class是激活的状态

    $(".shop-list1").find("li").each(function(){            var href=$(this).attr(&q ...

  2. ·c#之Thread实现暂停继续(转)

    暂停与继续实现,可以使用Thread.Suspend和Thread.Resume而这两个方法,在VS2010里提示已经过时,不建议使用,在网上查阅了一些资料,发现有个事件通知的方法很好,事件通知的大致 ...

  3. vue-cli的使用

    1.安装node https://nodejs.org/en/download/ 2.webpack安装[我选全局安装] 全局安装 npm install --global webpack 本地安装 ...

  4. [LeetCode] Longest Uncommon Subsequence II 最长非共同子序列之二

    Given a list of strings, you need to find the longest uncommon subsequence among them. The longest u ...

  5. [HNOI2001]软件开发

    题目描述 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的 服务,其中一项服务就是要为每个开发人员每天提供一块 ...

  6. [BZOJ]4810: [Ynoi2017]由乃的玉米田

    Time Limit: 30 Sec  Memory Limit: 256 MB Description 由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差 ...

  7. [usaco6.1.1Postal Vans]

    来自FallDream的博客,未经允许,请勿转载,谢谢. 给你一个4*n的棋盘,问从(1,1)出发恰好经过所有格子一次的走法数量.(n<=1000) 插头dp,用f[i][j][k]表示转移到第 ...

  8. bzoj 1974: [Sdoi2010]代码拍卖会

    Description 随着iPig在P++语言上的造诣日益提升,他形成了自己一套完整的代 码库.猪王国想参加POI的童鞋们都争先恐后问iPig索要代码库.iPi g不想把代码库给所有想要的小猪,只想 ...

  9. python变量、条件循环语句

    1. 变量名 - 字母  - 数字  - 下划线  #数字不能开头:不能是关键字:最好不好和python内置的函数等重复 2. 条件语句 缩进用4个空格(Tab键)注意缩进如果是空格键和Tab键混用, ...

  10. 记一次java heap space的解决办法

    问题缘由:后台上传excel导入到数据库,数据量太大,导致报错. 解决方案: 用jdk自带的性能分析器(jconsole)查看了一下,当excel开始导入的时候,发现堆空间直接爆掉. 增加堆空间,在c ...