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 机制
[java] view plaincopy在CODE上查看代码片派生到我的代码片
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 机制
[java] view plaincopy在CODE上查看代码片派生到我的代码片
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 异常不再抛出,然后继续按正常情况执行。
分享到:
相关推荐
Kotlin作为一种现代化的编程语言,为开发者提供了一种优雅的方式来处理异步逻辑:Kotlin协程。本压缩包文件“基于Kotlin协程实现异步编程.zip”包含了一份详细讲解如何使用Kotlin协程进行异步编程的PDF文档,以下是...
这个库在JavaScript的异步编程中扮演着重要角色,它提供了一种机制来模拟类似局部存储的功能,跨越了回调函数、Promise以及async/await等异步流程。 【描述】"关于continuation-local-storage的介绍"意味着我们将...
Cate代表基于 Continuation 的异步任务执行器。 它为并行任务调度提供了一些抽象,让您以类似同步的风格编写异步编程代码。 特征 Cate 使用Task抽象出一个最小的调度单元,它是用延续调度的。 任务可以组合在多个...
Continuations是一种程序对象,它可以捕获当前计算状态,然后在任意时间点恢复这个状态,甚至可以克隆或序列化。在用户看来,Continuations提供了暂停和恢复执行的能力,类似于保存和恢复游戏进度,这为开发者处理...
除了这些核心组件,Jetty工具包还包括其他一些关键模块,如Jetty Continuation(用于处理异步请求),Jetty JMX(提供JMX管理接口),以及Jetty Handler(提供各种服务器处理器)。Jetty的灵活性和可扩展性使其成为...
2. **Continuation机制**:通过Continuation支持异步处理,有效处理大量用户请求和长连接,减少资源消耗。 3. **模块化设计**:Jetty的接口设计使得开发者可以方便地替换或扩展其组件,以适应特定的应用需求。 **易...
在Java生态系统中,Groovy被广泛用于脚本编写、自动化任务和构建工具,如Gradle。"groovy-cps"是Groovy的一个重要概念,它涉及到Groovy代码的连续传递样式(Continuation Passing Style,CPS)执行。 连续传递样式...
6. **线程模型**:Jetty使用一种高效的线程模型,名为“Continuation”,它可以异步处理请求,避免阻塞主线程,提高服务器的并发处理能力。 7. **部署和管理Web应用**:Jetty支持多种方式部署Web应用,包括WAR文件...
Dsl.scala可能包含一种机制,允许开发者在DSL中方便地处理资源获取和释放,确保资源在不再需要时被正确地关闭。 “Monad Transformers”是另一个关键概念,它允许将一个Monad转换为另一个,从而结合不同类型的计算...
6. **Continuation**:Jetty提供了Continuation API,用于处理异步请求。当处理某个请求需要等待外部事件时,如数据库查询结果,可以暂停请求并恢复处理,提高响应速度。 7. **部署和生命周期管理**:Jetty提供了...
- **初始化(PT_INIT())** - 初始化原始线程。 - **开始执行(PT_BEGIN())** - 启动线程执行。 - **条件阻塞(PT_WAIT_UNTIL())** - 线程在满足特定条件前暂停。 - **退出(PT_EXIT())** - 结束线程。 此外,还有辅助...
6. **Continuation**:Jetty提供了对Servlet 3.0中Continuation接口的支持,允许开发者在处理长连接和异步操作时暂停和恢复请求。 7. **WebSocket**:Jetty提供了对WebSocket协议的支持,允许创建低延迟、双向通信...
gRPC拦截器是服务端和客户端都可以利用的机制,它允许在调用服务之前或之后执行额外的操作。拦截器可以用来增强gRPC服务的功能,例如: 1. 日志记录:在请求和响应之间记录详细信息,有助于调试和监控。 2. 认证与...
thorin的设计旨在支持现代编译器技术,如继续传递风格(Continuation-Passing Style, CPS)转换和编译器优化。CPS是一种编程范式,通过显式传递控制流来处理函数调用,这在实现复杂控制流和异步编程时非常有用。...
- **jetty-continuation.jar**:支持异步请求处理,用于处理长时间运行的操作。 这些库文件是Jetty运行的基础,开发者可以通过添加或移除这些库来定制Jetty的功能。 总的来说,Jetty 6.1.14(2)是一个功能完备、...
4. **继续传递风格(Continuation-Passing Style, CPS)**:这是一种转换程序的技巧,常用于处理控制流和异步编程。在效果处理中,CPS转换可以用来捕捉和操纵控制流,从而实现效果的处理。 5. **延续...
在 BPMScript 的核心理念中,它利用了基于延续(Continuation)的编程模型,这种模型允许程序在执行过程中暂停,并在稍后恢复执行,这对于处理异步操作和分布式计算非常有用。在业务流程管理领域,这使得BPMScript...