Jetty Continuation基本原理及实现

jetty 透明代理的实现 背景一提到proxy,大家首先想到就是squid、varnish、apache、lighttpd之类,接下来我们看看jetty8中的ProxyServlet是如何实现这个功能的ProxyServlet主要用到了continuation和http client两个技术点,如果了解了我的前几篇博文jetty io:http://blog.csdn.net/pwlazy/article/details/ 阅读详情

背景

在io密集型的web 应用,如何能更好地提升后台性能,jetty continuation是一个选择

现在特别流行的说法就是事件驱动,看看Node.js以及Redis, jetty continuation也不例外


一个例子

  1. package org.kaka.web;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.PrintWriter;  
  5.   
  6. import javax.servlet.ServletException;  
  7. import javax.servlet.http.HttpServlet;  
  8. import javax.servlet.http.HttpServletRequest;  
  9. import javax.servlet.http.HttpServletResponse;  
  10.   
  11. import org.eclipse.jetty.continuation.Continuation;  
  12. import org.eclipse.jetty.continuation.ContinuationSupport;  
  13.   
  14. public class SimpleSuspendResumeServlet extends HttpServlet {  
  15.   
  16.     /** 
  17.      *  
  18.      */  
  19.     private static final long serialVersionUID = 6112996063962978130L;  
  20.   
  21.     private MyAsyncHandler myAsyncHandler;  
  22.   
  23.     public void init() throws ServletException {  
  24.   
  25.         myAsyncHandler = new MyAsyncHandler() {  
  26.             public void register(final MyHandler myHandler) {  
  27.                 new Thread(new Runnable() {  
  28.                     public void run() {  
  29.                         try {  
  30.                             Thread.sleep(10000);  
  31.                             myHandler.onMyEvent(”complete!”);  
  32.                         } catch (InterruptedException e) {  
  33.                             // TODO Auto-generated catch block  
  34.                             e.printStackTrace();  
  35.                         }  
  36.   
  37.                     }  
  38.                 }).start();  
  39.             }  
  40.         };  
  41.   
  42.     }  
  43.   
  44.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  45.             throws ServletException, IOException {  
  46.         // if we need to get asynchronous results  
  47.         //Object results = request.getAttribute(“results”);  
  48.         final PrintWriter writer = response.getWriter();  
  49.         final Continuation continuation = ContinuationSupport  
  50.                 .getContinuation(request);  
  51.         //if (results == null) {  
  52.         if (continuation.isInitial()) {  
  53.               
  54.             //request.setAttribute(“results”,”null”);  
  55.             sendMyFirstResponse(response);  
  56.             // suspend the request  
  57.             continuation.suspend(); // always suspend before registration  
  58.   
  59.             // register with async service. The code here will depend on the  
  60.             // the service used (see Jetty HttpClient for example)  
  61.             myAsyncHandler.register(new MyHandler() {  
  62.                 public void onMyEvent(Object result) {  
  63.                     continuation.setAttribute(”results”, result);  
  64.                       
  65.                     continuation.resume();  
  66.                 }  
  67.             });  
  68.             return; // or continuation.undispatch();  
  69.         }  
  70.   
  71.         if (continuation.isExpired()) {  
  72.             sendMyTimeoutResponse(response);  
  73.             return;  
  74.         }  
  75.          //Send the results  
  76.         Object results = request.getAttribute(”results”);  
  77.         if(results==null){  
  78.             response.getWriter().write(”why reach here??”);  
  79.             continuation.resume();  
  80.             return;  
  81.         }  
  82.         sendMyResultResponse(response, results);  
  83.     }  
  84.   
  85.     private interface MyAsyncHandler {  
  86.         public void register(MyHandler myHandler);  
  87.     }  
  88.   
  89.     private interface MyHandler {  
  90.         public void onMyEvent(Object result);  
  91.     }  
  92.       
  93.     private void sendMyFirstResponse(HttpServletResponse response) throws IOException {  
  94.         //必须加上这一行,否者flush也没用,为什么?  
  95.         response.setContentType(”text/html”);  
  96.         response.getWriter().write(”start”);  
  97.         response.getWriter().flush();  
  98.   
  99.     }  
  100.   
  101.     private void sendMyResultResponse(HttpServletResponse response,  
  102.             Object results) throws IOException {  
  103.         //response.setContentType(“text/html”);  
  104.         response.getWriter().write(”results:” + results);  
  105.         response.getWriter().flush();  
  106.   
  107.     }  
  108.   
  109.     private void sendMyTimeoutResponse(HttpServletResponse response)  
  110.             throws IOException {  
  111.         response.getWriter().write(”timeout”);  
  112.   
  113.     }  
  114.   
  115. }  


这个例子到底干了什么?


出于演示的目的,这个例子格外简单。模拟了在web请求中如何处理一个耗时阻塞10s的io操作


  • 常规的程序遇到这种情况(假设没有设置超时),通常会等待10s,线程会白白浪费在哪,一旦请求一多,线程池及等待队列会满掉,从而导致网站无法服务
  • 稍微好点的程序恐怕会使用futuretask来解决问题,但无论怎样,futuretask带有轮询的性质,或多或少会带有阻塞
  • jetty continuation更进了一步, 采用事件驱动的方式来通知请求完成,丝毫不浪费一点io时间,一旦遇到阻塞,当前worker线程会结束,这样就可以服务其他请求,等耗时操作处理完毕通知jetty,此时jetty会再动用一个新的worker线程再次处理请求

常见流程

  • 具体流程1,耗时操作在AsyncContinuation默认超时(30s,可以设置)之内完成
  1. 当请求到来,被selector线程感知
    •  selector线程,会实例化org.eclipse.jetty.server.Request以及org.eclipse.jetty.server.AsyncContinuation
    • AsyncContinuation实例此时状态为__IDLE
  2. worker线程A会获取到selector线程派发的这个请求
    • 流程进入org.eclipse.jetty.server.AsyncHttpConnection(AbstractHttpConnection).handleRequest()
    • 调用_request._async.handling(),AsyncContinuation实例的状态__IDLE–>__DISPATCHED
    • 调用真正的业务逻辑server.handle(this);业务逻辑中调用 AsyncContinuation.suspend(ServletContext, ServletRequest, ServletResponse) ,会将AsyncContinuation实例的状态__DISPATCHED–>__ASYNCSTARTED
    • 最后调用_request._async.unhandle(),AsyncContinuation实例的状态__ASYNCSTARTED–>__ASYNCWAIT
      • 会将suspend的那个请求任务放入selector线程的超时队列(和redis 事件框架的做法非常类似)
    • 为了简单期间,假设在上诉过程中,耗时操作还没完成,此时worker线程A被回收将会服务其他请求,虽然当前请求并未完成
  3. 匿名应用线程(在jetty woker线程另外启动的线程)完成耗时操作
    • 调用AsyncContinuation.resume() ,此时AsyncContinuation实例的状态__ASYNCWAIT–>__REDISPATCH
    • 然后会往worker线程队列或者selector线程队列中添加一个请求task,以此来触发jetty再次完成未完成的请求
  4. worker线程B再次处理那个请求
    • 流程进入org.eclipse.jetty.server.AsyncHttpConnection(AbstractHttpConnection).handleRequest()
    • 调用_request._async.handling(),AsyncContinuation实例的状态__REDISPATCH–>__REDISPATCHED
    • 调用server.handleAsync(this);再次进入业务逻辑,此时耗时操作已完成,可以输出最后的结果
    • 调用_request._async.unhandle()   AsyncContinuation实例的状态__REDISPATCHED–>__UNCOMPLETED
    • 调用_request._async.doComplete(),AsyncContinuation实例的状态__UNCOMPLETED–>__COMPLETED 
    • 请求结束

  • 具体流程2,耗时操作超过了AsyncContinuation默认超时时间
  1. 同上
  2. 同上
  3. selector线程轮询中感知到耗时任务超时
    • 此时在轮询中能感知并获取这个task,见org.eclipse.jetty.io.nio.SelectorManager$SelectSet.doSelect()
    • 将此task丢入worker线程队列
  4. worker线程C处理超时任务
    • 调用AsyncContinuation.expired() ,此时AsyncContinuation实例的状态__ASYNCWAIT–>__REDISPATCH
    • 然后会往worker线程队列或者selector线程队列中添加一个请求task,以此来触发jetty再次完成未完成的请求
  5. 同上面的4

  • 具体流程3,耗时操作非常快
  1. 同上
  2. worker线程A会获取到selector线程派发的这个请求
    • 流程进入org.eclipse.jetty.server.AsyncHttpConnection(AbstractHttpConnection).handleRequest()
    • 调用_request._async.handling(),AsyncContinuation实例的状态__IDLE–>__DISPATCHED
    • 调用真正的业务逻辑server.handle(this);业务逻辑中调用 AsyncContinuation.suspend(ServletContext, ServletRequest, ServletResponse) ,会将AsyncContinuation实例的状态__DISPATCHED–>__ASYNCSTARTED​
  3. 匿名应用线程(在jetty woker线程另外启动的线程)完成耗时操作,在2)中调用_request._async.unhandle()之前完成
    • 调用AsyncContinuation.resume() ,此时AsyncContinuation实例的状态__ASYNCSTARTED–>__REDISPATCHING
  4. 还是那个work线程A,注意此时3已经完成
    • 调用_request._async.unhandle(),,AsyncContinuation实例的状态__REDISPATCHING–>__REDISPATCHED
    • 由于此时_request._async.unhandle()返回false,再次进入循环调用server.handleAsync(this);再次进入业务逻辑,此时耗时操作已完成,可以输出最后的结果
    • 调用_request._async.unhandle()   AsyncContinuation实例的状态__REDISPATCHED–>__UNCOMPLETED
    • 调用_request._async.doComplete(),AsyncContinuation实例的状态__UNCOMPLETED–>__COMPLETED
    • 请求结束 


小结


总体来讲

  • jetty continuation需要在应用中使用应用级的线程池来完成一些io任务,这个在普通的web编程并不常见
  • 在应用的第一次请求中需要
    • 调用AsyncContinuation.suspend(完成一个状态的转换,以及产生一个超时任务)
    • 将耗时任务派发给应用线程池
    • 完毕后,jetty回收该请求线程
  • io任务在应用线程中完成后,然后通过AsyncContinuation.resume或者complete等方法通知jetty任务完成
  • jetty然后会再次分配一个worker线程处理该请求(如果逻辑复杂,如并行的多次Io会分配多个worker线程)
  • 引入jetty continuation带来的负面作用是编程模型会变得复杂,需要仔细的切割各类io任务
Caused by: java.lang.ClassNotFoundException: org.eclipse.jetty.continuation.ContinuationThrowable 1、错误描述2017-03-14 10:43:02.328:INFO:oejs.Server:jetty-8.1.21.v20160908 2017-03-14 10:43:02.951:WARN:oejw.WebAppContext:Failed startup of context o.e.j.w.WebAppContext{/,file:/F:/workspace/TYIF/src/main 阅读详情

相关推荐

Jetty cometd(Continuation)学习笔记

Jetty cometd(Continuation)学习笔记,自己用的,别人那down的网页

Jetty Continuation机制

Continuation机制 Continuation机制是Jetty用于更好的支持异步Servlet的机制。 首先简要介绍一下技术应用的背景。异步请求是指当客户端发送一个请求到服务器的时候,客户端不必一直等待服务器的响应,例如Web 2.0中的Ajax(Asynchronous JavaScript and XML)技术、JDBC连接池等,当服务器端响应返回时,客户端利用一个 Javasc

kobejayandy的专栏 3544

大语言模型在构建UNSPSC 分类数据中的应用

UNSPSC 是联合国标准产品和服务代码。本文研究如何利用大语言模型生成分类系统的分析

姚家湾博客 1867

jetty continuation基本原理及实现

背景 在io密集型的web 应用,如何能更好地提升后台性能,jetty continuation是一个选择 现在特别流行的说法就是事件驱动,看看node.js以及redis, jetty continuation也不例外 一个例子 package org.kaka.web; import java.io.IOException; import java.io.PrintWriter; im...

helpbs 200

远程桌面连接失败?手把手教你解决CredSSP加密Oracle漏洞(Win10/Win11通用)

本文详细解析了Windows远程桌面连接因CredSSP加密Oracle漏洞安全更新导致的“身份验证错误”问题。文章从原理入手,提供了通过组策略编辑器(适用于专业版)和注册表编辑器(适用于家庭版)两种核心解决方案,指导用户将安全策略调整为推荐的“缓解”模式,以在保障安全的前提下恢复连接,并给出了高级脚本处理与安全最佳实践。

u6v7w8x的博客 724

DSP TMS320F280049之CCS工程的建立(库函数版)

TMS320F280049 DSP是TI最新出的一款C2000系列的DSP,主频为100MHZ,功能较为强大,具有较多的片上模拟外设。这一节主要讲述如何新建F280049的CCS工程。 Step1.下载文件: 下载C2000Ware软件并安装。下载地址如下: http://www.ti.com.cn/tool/cn/C2000WARE?keyMatch=C2000Ware%2...

fanxianyan1993的博客 1万+

Jetty Continuation实现原理和使用场景分析

Jetty Continuation实现原理和使用场景分析 Jetty continuation是什么?简单的说,就是用一个NIO模拟http同步连接。我们都知道http请求时同步的,就是说http request发送到server之后,server分配一个单独的线程处理这个请求,请求完成之后再返回response给请求端。这个过程中server处理线程一般是不释放,即使是什么都没有干。更关键的...

移动互联网后端技术 263

空天大模型详解

空天大模型是指面向空天信息领域(如卫星遥感、导航、气象等)设计的多模态人工智能模型,能够处理海量遥感数据、多传感器信息及跨时空分析任务。多模态融合:整合可见光、雷达、热红外、多光谱等多源遥感数据,构建统一表征空间,例如“空天·灵眸”3.0版支持航空、卫星及无人机数据的自动化解译。轻量化与高效推理:针对星载计算场景,采用分层量化、跨模态蒸馏技术压缩模型参数(如JigonGPT从1.02B压缩至0.23B,性能仅牺牲5.2%)18,并通过热传导架构提升计算速度2.4倍。神经符号结合。

zxy98的专栏 1569

Jetty Continuation源码分析

1.概述 jetty的continuation是用于异步处理请求,简单的讲,请求模型不再是一请求一线程,而是在请求的过程中,可以挂起当前请求,用该容器线程处理别的请求。减小请求线程数,从而减少内存占用和上下文切换。还可以使得应用对于请求更可控,比如针对不同优先级请求分别排队等。 servlet3中也有该异步请求的支持:http://docs.oracle.com/javaee/6/api/ja

kobejayandy的专栏 2850

【分享】获取微信通讯录python代码形式实现

微信号”, “昵称”, “地区”, “备注”, “标签”, “签名”, “来源”5. 找到最后一个空格所在的位置(后一个就是真正的联系人了)当前微信号与上一个相同的时候,说明到底部了,可以跳出循环。3. 滚动鼠标到最顶部(防止已经滚动了一部分了)7.记录下上一个联系人的微信号。7. 无限循环按键盘下箭头。获取详情中的以下元素内容。6. 点击第一个联系人。4. 获取联系人列表。

程序员老狼专注开发aigc或客服系统应用 2894

word 2013 长篇文档排版案例教程

office 2013 制作长文格式模板

1万+

jetty6 Continuation

http://langyu.iteye.com/blog/707713 背景资料    对于当前的很多网络应用,并行访问的用户数会远远超过服务器上的连接数。这是由于在用户与服务器会话中,当用户在做阅读内容或是填写表格等动作时,连接可能会因为这些暂停被关闭。所以成千上万的用户可以由数百个连接来提供服务。    但是基于AJAX的应用与传统网络应用相比有不同的业务模型(Traffic profil...

qian0021514578 161

手把手教你学simulink实例:基于Simulink的风力发电系统建模与仿真

风力发电作为一种清洁、可再生的能源形式,近年来得到了快速发展。风力发电系统的性能优化和控制策略设计对于提高发电效率、降低运行成本具有重要意义。本项目旨在使用MATLAB/Simulink平台,对风力发电系统进行建模与仿真,研究其动态特性,并验证控制策略的有效性。通过建立风力发电机、传动系统、发电机及电力电子变换器等子系统的模型,实现对风力发电系统的全面分析。

MHD0815的博客 559

Jetty Continuation源码学习

Jetty的NIO可以有效地减少请求的线程数,但是对于servlet而言,依然是每个servlet需要一个线程,Continuation的出现有效地解决了servlet中耗时操作占用请求线程的境况。 Continuation用于处理异步请求,可以在请求处理的上下文交给应用线程去处理并挂起当前请求,这样减少了请求线程的数量,最后当应用线程处理完成后恢复该请求。比如使用该功能可以解决ajax长轮

kobejayandy的专栏 1577

【服务器电源架构与关键技术发展趋势】深度解析架构、方案、玩家与未来趋势

技术维度:台达 / 光宝在高功率密度(97%+ 效率)和垂直整合上领先,大陆厂商(麦格米特 / 欧陆通)在成本控制和快速响应上更优,国际厂商(英飞凌)聚焦核心器件突破。 客户维度:台达绑定英伟达核心供应链,麦格米特 / 欧陆通兼顾国内外客户,光宝 / 中恒电气侧重云端与互联网厂商。 趋势适配:所有厂商均加速布局 800V 高压架构、液冷技术和高功率 Power Shelf,以应对 AI 服务器单柜功率从 10kW→200kW 的升级需求。

昔时扬尘处 723

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

jetty continuation的用法、实现、分析

项目中用到了jetty continuation,但是一直不知道continuation到底有什么作用,下面这个文章讲解的很清楚,附上自己的一点见解: 1. http请求的处理逻辑是什么? 当一个HTTP请求到来的时候,server分配一个单独的线程处理这个请求,请求完成之后再返回response给请求端。这个过程中 server处理线程一般是不释放,即...

weixin_33747129的博客 211

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

NIO+异步-jetty实现

NIO+异步的方式能让少量的线程(资源)做大量的事情,这适用于很多应用场景,比如代理服务、api服务、长连接服务等等,这些应用如果用同步方式将耗费大量机器资源。尽管NIO+异步能提高系统吞吐量,但其并不能让一个请求的等待时间下降,相反可能会增加等待时间。

Developer of XingKong22star 2698

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

上一篇: ZeroMQ:云计算时代最好的通讯库
下一篇: Jetty Continuation源码分析
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值