首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

反向 Ajax,第 2 部分 WebSocket(2)

反向 Ajax,第 2 部分 WebSocket(2)

FlashSockets对于不支持 WebSockets 的浏览器,一些库能够回退到 FlashSockets(通过 Flash 的套接字)。这些库通常提供相同的官方 WebSocket API,但是它们通过将调用委派给网站上包含的隐藏的 Flash 组件来实现。
优势FlashSockets 透明地提供 WebSockets 功能,即使在不支持 HTML5 WebSockets 的浏览器上也是如此。
缺点FlashSockets 具有以下缺点:
  • 它需要安装 Flash 插件(通常所有浏览器都有该插件)。
  • 它要求打开防火墙的 843 端口,以便 Flash 组件能够执行 HTTP 请求来检索包含域授权的策略文件。 如果无法访问 843 端口,那么库应回退或给出一个错误。所有处理都需要一定的时间(最多 3 秒钟,具体取决于库),这会减慢网站速度。
  • 如果客户端在代理服务器后面,那么到 843 端口的连接可能遭到拒绝。
WebSocketJS 项目提供一个网桥。它要求至少提供 Flash 10,并为 Firefox 3、Internet Explorer 8 和 Internet Explorer 9 提供 WebSockets 支持。
建议与 Comet 相比,WebSockets 带来很多好处。在日常开发过程中,支持 WebSockets 的客户端的速度变得更快,产生的需求也更少(因此,使用的带宽也更少)。但是,由于并非所有浏览器都支持 WebSockets,因此支持反向 Ajax 库的最佳选择将是能够检测到 WebSockets 支持,如果不支持 WebSockets,则回退到 Comet(长轮询)。
由于需要这两种技术来最大程度地利用所有浏览器并保持兼容性,因此建议您使用在这些技术之上提供抽象层的客户端 JavaScript 库。本系列的第 3 部分和第 4 部分将研究一些库,第 5 部分将展示这些库的应用。在服务器端,情况可能更复杂,如上一节所述。
服务器端的反向 Ajax 制约因素大致了解客户端可用的反向 Ajax 解决方案之后,让我们来看一下服务器上的反向 Ajax 解决方案。到目前为止,示例中主要使用的是客户端 JavaScript 代码。在服务器端,为了接受反向 Ajax 连接,某些技术需要使用特定功能来处理使用期较长的连接(与您熟悉的短 HTTP 请求相比较而言)。为了更好地进行扩展,应该使用新的线程模型,该模型需要使用 Java 中的特定 API 才能够暂停请求。此外,对于 WebSockets,您需要正确管理应用程序中使用的服务的作用域。
线程和非阻塞 I/O通常情况下,Web 服务器会将每个传入的 HTTP 连接与一个线程或一个进程相关联。这种连接可以是持久的(一直有效),因此多个请求可能使用同一个连接。在本文的示例中,可以将 Apache Web 服务器配置为 mpm_fork 或 mpm_worker 模型来改变这种行为。Java Web 服务器(应用服务器也包括在内)通常为每个传入连接使用一个线程。
生成新的线程会导致内存消耗和资源浪费,因为不能保证生成的线程会被使用。可能会已经建立连接,但没有从客户端或服务器发送数据。无论是否使用该线程,都会消耗内存和 CPU 资源来调度和争用开关。使用线程模型配置服务器时,通常需要配置一个线程池(设置处理传入连接的最大线程数)。如果错误地配置了该值,并且该值过低,那么您将遭遇线程匮乏问题;请求将一直处于等待状态,直到有了可用来处理这些请求的线程。在达到最大并发连接后,响应时间会延长。另一方面,配置较高的线程数可能导致内存不足异常。生成过多的线程会消耗 JVM 的所有堆内存,并导致服务器崩溃。
Java 最近推出了称为非阻塞 I/O 的新的 I/O API。该 API 使用一个选择器,避免每次执行连接到服务器的新 HTTP 连接时都绑定一个线程。有传入数据时,系统会收到一个事件,并分配一个线程来处理请求。因此,这也被称为 “每个请求一个线程” 模型。它允许 WebSphere 和 Jetty 等 Web 服务器进行扩展,并使用固定数量的线程处理越来越多的用户连接。在相同的硬件配置下,在这种模型下运行的 Web 服务器比 “每个连接一个线程” 模型具有更好的扩展性。
在 Philip McCarthy( Comet and Reverse Ajax 的作者)的博客中,他提供了关于两种线程模型的可扩展性的一个有趣基准(请参阅  以获得链接)。在 图 2 中,您会发现相同的模型:当使用过多的连接时,线程模型会停止工作。
图 2. 线程模型基准“每个连接一个线程” 模型(图 2 中的线程)通常会提供更快的响应,因为所有线程都已启用、准备就绪并等待使用,但是当连接数量过多时,则会停止服务。在 “每个请求一个线程” 模型下(图 2 的续图),要使用一个线程为到达的请求提供服务,而连接是通过 NIO 选择器进行处理的。响应时间可能会长一些,但是可以将线程回收利用,因此该解决方案在连接数量较大时扩展性更好一些。
为了了解线程的幕后工作方式,可以将 LEGO™ 块想象成为一个选择器。每个传入请求都连接到该 LEGO 块,并通过引脚识别。LEGO 块/选择器将拥有与连接数量相同的 PIN(和密钥)。然后,在等待新事件发生时,只需要使用一个线程在 PIN 上进行迭代。当发生事件时,选择器线程会检索发生事件的密钥,然后使用一个线程为传入请求提供服务。
"Rox Java NIO Tutorial" 提供了使用了用 Java 编译的 NIO 的良好示例(参阅 )。
返回列表