Jetty 的 Continuation 机制
讨论 Jetty 的 Continuation 机制,首先需要提到 Ajax 技术,Ajax 技术是当前开发
Web 应用的非常热门的技术,也是 Web 2.0 的一个重要的组成部分。Ajax 技术中的一个核心对象是 XMLHttpRequest
对象,这个对象支持异步请求,所谓异步请求即是指当客户端发送一个请求到服务器的时候,客户端不必一直等待服务器的响应。这样就不会造成整个页面的刷新,
给用户带来更好的体验。而当服务器端响应返回时,客户端利用一个 Javascript
函数对返回值进行处理,以更新页面上的部分元素的值。但很多时候这种异步事件只是在很小一部分的情况下才会发生,那么怎么保证一旦服务器端有了响应之后客
户端马上就知道呢,我们有两种方法来解决这个问题,一是让浏览器每隔几秒请求服务器来获得更改,我们称之为轮询
。二是服务器维持与浏览器的长时间的连接来传递数据,长连接的技术称之为 Comet
。
大家很容易就能发现轮询方式的主要缺点是产生了大量的传输浪费。因为可能大部分向服务器的请求是无效的,也就是说客户端等
待发生的事件没有发生,如果有大量的客户端的话,那么这种网络传输的浪费是非常厉害的。特别是对于服务器端很久才更新的应用程序来讲,比如邮件程序,这种
浪费就更是巨大了。并且对 Server 端处理请求的能力也相应提高了要求。如果很长时间才向 Server
端发送一次请求的话,那么客户端就不能的得到及时的响应。
如果使用 Comet 技术的话,客户端和服务器端必须保持一个长连接,一般情况下,服务器端每一个 Servlet 都会独占一个线程,这样就会使得服务器端有很多线程同时存在,这在客户端非常多的情况下也会对服务器端的处理能力带来很大的挑战。
Jetty 利用 Java 语言的非堵塞 I/O 技术来处理并发的大量连接。 Jetty 有一个处理长连接的机制:一个被称为 Continuations
的特性。利用 Continuation 机制,Jetty 可以使得一个线程能够用来同时处理多个从客户端发送过来的异步请求,下面我们通过一个简化的聊天程序的服务器端的代码来演示不使用 Continuation 机制和使用 Continuation 的差别。
Continuation 机制
public class ChatContinuation extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse response){
postMessage(request, response);
}
private void postMessage(HttpServletRequest request, HttpServletResponse response)
{
HttpSession session = request.getSession(true);
People people = (People)session.getAttribute(session.getId());
if (!people.hasEvent())
{
Continuation continuation =
ContinuationSupport.getContinuation(request, this);
people.setContinuation(continuation);
continuation.suspend(1000);
}
people.setContinuation(null);
people.sendEvent(response);
}
}
|
大家注意到,首先获取一个 Continuation 对象,然后把它挂起 1 秒钟,直到超时或者中间被 resume
函数唤醒位置,这里需要解释的是,在调用完 suspend
函数之后,这个线程就可处理其他的请求了,这也就大大提高了程序的并发性,使得长连接能够获得非常好的扩展性。
如果我们不使用 Continuation 机制,那么程序就如 清单 3 所示:
不使用 Continuation 机制
public class Chat extends HttpServlet{
public void doPost(HttpServletRequest request, HttpServletResponse response){
postMessage(request, response);
}
private void postMessage(HttpServletRequest request, HttpServletResponse response)
{
HttpSession session = request.getSession(true);
People people = (People)session.getAttribute(session.getId());
while (!people.hasEvent())
{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
people.setContinuation(null);
people.sendEvent(response);
}
}
|
大家注意到在等待事件发生的时间里,线程被挂起,直到所等待的事件发生为止,但在等待过程中,这个线程不能处理其他请求,
这也就造成了在客户端非常多的情况下服务器的处理能力跟不上的情况。下面我们解释一下 Jetty 的 Continuation 的机制是如何工作的。
为了使用 Continuatins,Jetty 必须配置为使用它的 SelectChannelConnector
处理请求。这个 connector 构建在 java.nio API 之上,允许它维持每个连接开放而不用消耗一个线程。当使用 SelectChannelConnector
时,ContinuationSupport.getContinuation()
提供一个 SelectChannelConnector.RetryContinuation
实例(但是,您必须针对 Continuation
接口编程)。当在 RetryContinuation
上调用 suspend()
时,它抛出一个特殊的运行时异常 -- RetryRequest
,该异常传播到 servlet 外并且回溯到 filter 链,最后被 SelectChannelConnector
捕获。但是不会发送一个异常响应给客户端,而是将请求维持在未决 Continuations 队列里,则 HTTP
连接保持开放。这样,用来服务请求的线程返回给 ThreadPool,然后又可以用来服务其他请求。暂停的请求停留在未决 Continuations
队列里直到指定的过期时间,或者在它的 Continuation 上调用 resume()
方法。当任何一个条件触发时,请求会重新提交给 servlet(通过 filter 链)。这样,整个请求被"重播"直到 RetryRequest 异常不再抛出,然后继续按正常情况执行。
分享到:
相关推荐
"同步解耦"和"异步化"是两个重要的概念,它们对于提高系统性能和扩展性至关重要。在这个主题中,我们将深入探讨SpringBoot如何实现这两个概念。 首先,让我们理解同步和异步的概念。在编程中,同步操作意味着调用一...
【淘宝网商品详情页静态异步化】是一个关于优化电商网站性能的主题,主要涉及的是如何在高并发情况下提升服务器响应速度以及改善用户体验。在面对如双11、双12等大促活动带来的巨大流量压力时,传统的B/S架构面临...
金牌原创]商品详情页静态异步化
后端性能优化六种方式:缓存化、服务化、异步化等 在软件开发中,后端性能优化是一个非常重要的方面。一个高性能的后端系统可以提高用户体验、增加系统的可扩展性和可维护性、本降低系统的运营成本。今天我们将讨论...
商品详情页静态异步化.pptx
本文来自于51cto,文章从异步化和并行化两个方案中给大家介绍如何处理架构设计中的高并发这个问题。同步和异步,阻塞和非阻塞,这几个词已经是老生常谈,但是还是有很多同学分不清楚,以为同步肯定就是阻塞,异步...
无锁异步化、事件驱动架构设计的_java_netty_网络编程框架;___轻量级,无需依赖任何第三方_ioGame
无锁异步化、事件驱动架构设计的 java netty 网络编程框架; 轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式; 适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景; 通过 ioGame 你...
无锁异步化、事件驱动架构设计的 java netty 网络编程框架; 轻量级,无需依赖任何第三方中间件或数据库就能支持集群、分布式; 适用于网络游戏服务器、物联网、内部系统及各种需要长连接的场景; 通过 ioGame 你...
它的产生背景是公司要求服务完全异步化,一个服务可能包括RPC调用请求、MemCached请求、KV存储请求以及MySQL数据库调用,目前其它三种请求的组件都有异步化的接口,但是数据库调用并没有。所以,在这个情况下,开发...
服务异步处理我将会有一个详细的说明文档(服务异步化的概念,服务异步化的几种标准实现,服务异步化容器的特点),后续给出。 Web服务异步化测试原因: TOP应用特殊性: 1.自身服务能力由后端的服务能力决定。(对...
每次日志输出到文件都会进行一次磁盘IO,在多应用的时候这种效果会导致一定的线程运行延迟,所以可以采用异步的方式处理。 采用异步写日志的方式,通过不让主线程去写日志文件而减少磁盘IO,避免并发下造成线程阻塞...
为了异步化,你需要在这些动作中调用Swoole的异步方法,如`task`或`taskwait`,将任务放入工作线程进行处理。 最后,`runtime`目录是Yii2的运行时目录,存放临时文件、日志等。在异步任务执行过程中,可能会生成...
在考虑变频器的频率和电压调节暂态过程的情况下建立了异步化同步发电机ASG(Asynchronized Synchronous Generator)的暂态数学模型,采用改进的变结构控制方法,设计了ASG的变结构励磁控制系统。在ASG单机对无穷大系统...
### 异步化汽轮发电机对电力系统低频振荡的抑制 #### 一、引言 电力系统中的低频振荡(通常频率在0.2Hz至2.5Hz之间)是电力系统动态稳定性的一个重要问题。这种振荡不仅会降低系统的传输能力,还可能导致发电机...
异步化同步发电机是一种特殊类型的发电机,它结合了同步发电机和异步电机的特点,能够在运行过程中灵活调节有功和无功功率,从而在电力系统中发挥重要作用。本文主要探讨了异步化同步发电机的稳态和暂态特性,并通过...
在Spring MVC中,我们可以通过`@Async`注解实现控制器方法的异步化。这样,当控制器接收到HTTP请求后,可以立即返回,而不会阻塞等待业务逻辑的执行。以下是一个简单的例子: ```java @Controller @EnableAsync ...
这个功能主要是为了解决高并发场景下服务器性能瓶颈的问题,通过将耗时的操作异步化,来提升系统的响应速度和整体吞吐量。接下来,我们将详细探讨这一特性。 ### 1. Spring MVC 异步处理概述 在传统的Spring MVC中...