tomcat 轮询_用Spring长轮询Tomcat

tomcat 轮询

就像喜剧演员弗兰基· 豪威尔 ( Frankie Howerd)所说的“噢,小姐小姐” ,但足够多的英国影射和双重诱惑,因为长轮询Tomcat对隔壁的闷气不是某种性的偏见,这是一种技术(或更像是一种hack)由于乔布斯(Steve Jobs)拒绝在iPhone和iPad上支持Adobe Flash Player而开发的 。 事实是,将Flash Player用作Web应用程序的一部分是一种很好的支持“ 发布和订阅”范例的方法,因为它能够满足那些需要实时更新的情况,例如实时股票价格,新闻更新和更改。博彩赔率,而直接HTTP及其请求/回复范例是支持静态页面的一种好方法。 许多公司在开发使用Flash的应用程序方面投入了大量精力,以便为用户提供实时数据。 当苹果公司宣布iOS将不支持Adobe Flash时,如果没有iPhone解决方案,它们就会变得干and无力,要重新进入移动市场,我想其中有很多都经过长时间的投票。

那么,什么是长期 投票 ? 嗯,这不是华沙的高个子,其想法是模仿“发布和订阅”模式。 场景如下:

  1. 浏览器从服务器请求一些数据。
  2. 服务器没有可用的数据,并允许请求挂起。
  3. 稍后,响应数据可用,服务器完成请求。
  4. 浏览器一接收到数据,便立即显示该数据,然后立即请求更新。
  5. 现在,流程循环回到点2。

我怀疑Spring的Guy不太热衷于“长期投票”一词,因为他们更正式地将此技术称为异步请求处理

在上面查看我的“长轮询”或“ 异步请求处理”流程时,您可能会猜测服务器将发生什么。 每次您强迫服务器等待数据可用时,都会占用其一些宝贵资源。 如果您的网站很受欢迎并且负担很重,那么等待更新消耗的资源数量会激增,因此服务器可能会用尽并崩溃。

在2月和3月,我写了一系列有关Producer Consumer模式的博客,这似乎是进行长期投票的理想情况。 如果您尚未阅读我的Producer Consumer模式博客,请在此处查看

在那种原始情况下,我说过“电视公司会向每个游戏发送记者,以将实时更新反馈到系统中,然后将其发送回演播室。 到达工作室后,更新将被放入队列中,然后由电传打字机显示在屏幕上。”

随着时代的变迁,电视公司希望用Web应用程序代替旧的Teletype,该应用程序可以实时显示比赛更新。

屏幕截图2013年8月19日的18.04.01

在这种新情况下,电视公司总裁聘请了敏捷牛仔公司的朋友来整理更新。 为了使事情变得容易,他为他们提供了MessageMatchMatchReporter类的源代码,这些类在新项目中可以重复使用。 Agile Cowboys的首席执行官为此聘用了一些新开发人员:负责前端JavaScript,JQuery,CSS和HTML专家以及负责Spring MVC Webapp的Java专家。

前端专家提供了以下JavaScript轮询代码:

var allow = true; 
var startUrl; 
var pollUrl; function Poll() { this.start = function start(start, poll) { startUrl = start; pollUrl = poll; if (request) { request.abort(); // abort any pending request } // fire off the request to MatchUpdateController var request = $.ajax({ url : startUrl, type : "get", }); // This is jQuery 1.8+ // callback handler that will be called on success request.done(function(reply) { console.log("Game on..." + reply); setInterval(function() { if (allow === true) { allow = false; getUpdate(); } }, 500); }); // callback handler that will be called on failure request.fail(function(jqXHR, textStatus, errorThrown) { // log the error to the console console.log("Start - the following error occured: " + textStatus, errorThrown); }); }; function getUpdate() { console.log("Okay let's go..."); if (request) { request.abort();  // abort any pending request } // fire off the request to MatchUpdateController var request = $.ajax({ url : pollUrl, type : "get", }); // This is jQuery 1.8+ // callback handler that will be called on success request.done(function(message) { console.log("Received a message"); var update = getUpdate(message); $(update).insertAfter('#first_row'); }); function getUpdate(message) { var update = "<div class='span-4  prepend-2'>" + "<p class='update'>Time:</p>" + "</div>" + "<div class='span-3 border'>" + "<p id='time' class='update'>" + message.matchTime + "</p>" + "</div>" + "<div class='span-13 append-2 last' id='update-div'>" + "<p id='message' class='update'>" + message.messageText + "</p>" + "</div>"; return update; }; // callback handler that will be called on failure request.fail(function(jqXHR, textStatus, errorThrown) { // log the error to the console console.log("Polling - the following error occured: " + textStatus, errorThrown); }); // callback handler that will be called regardless if the request failed or succeeded request.always(function() { allow = true; }); };  
};

名为Poll的类具有一个方法start() ,该方法带有两个参数。 浏览器使用第一个订阅匹配更新数据供稿,而第二个是用于轮询服务器以获取更新的URL。 从JQuery ready(…)函数调用此代码。

$(document).ready(function() {var startUrl = "matchupdate/subscribe";var pollUrl = "matchupdate/simple";var poll = new Poll();poll.start(startUrl,pollUrl);});

调用start()方法时,它将向服务器发出Ajax请求以订阅匹配更新。 当服务器以简单的“ OK”答复时, request.done(…)处理程序通过使用带有匿名函数作为参数的setInterval(…)启动1/2秒计时器。 此函数使用一个简单的标志“ allow ”,如果为true,则允许调用getUpdate()方法。 然后将allow标志设置为false,以确保不存在重入问题。

getUpdate(…)函数使用上述第二个URL参数对服务器进行另一个Ajax调用。 这次request.done(…)处理程序获取匹配更新并将其转换为HTML,并将其插入到“ first_row ” div之后,以将其显示在屏幕上。

回到场景, 敏捷牛仔公司的首席执行官想打动他的新女友,于是他给她买了一辆保时捷911 。 现在他无法用自己的现金来支付,因为他的妻子会发现发生了什么事,所以他用电视公司交易中的一部分现金来支付。 这意味着他只能负担一名应届毕业生来编写服务器端代码。 这位毕业生可能没有经验,但是他确实重用了MessageMatchMatchReporter类以提供匹配更新。 请记住,将QueueMatch注入MatchReporter 。 调用MatchReporter.start()方法时,它将加载匹配项并读取更新消息,并在其中检查其时间戳,并在适当的时候将其添加到队列中。 如果您想查看MatchReporterMatch等的代码,请查看原始博客 。

然后,研究生将创建一个简单的Spring比赛更新控制器

@Controller() 
public class SimpleMatchUpdateController { private static final Logger logger = LoggerFactory.getLogger(SimpleMatchUpdateController.class); @Autowired private SimpleMatchUpdateService updateService; @RequestMapping(value = "/matchupdate/subscribe" + "", method = RequestMethod.GET) @ResponseBody public String start() { updateService.subscribe(); return "OK"; } /** * Get hold of the latest match report - when it arrives But in the process * hold on to server resources */ @RequestMapping(value = "/matchupdate/simple", method = RequestMethod.GET) @ResponseBody public Message getUpdate() { Message message = updateService.getUpdate(); logger.info("Got the next update in a really bad way: {}", message.getMessageText()); return message; } 
}

SimpleMatchUpdateController包含两个非常简单的方法。 第一个start()仅调用SimpleMatchUpdateService来订阅比赛更新,而第二个getUpdate()SimpleMatchUpdateService请求下一个比赛更新。 看到这一点,您可能会猜到所有工作都是由SimpleMatchUpdateService完成的。

@Service("SimpleService") 
public class SimpleMatchUpdateService { @Autowired @Qualifier("theQueue") private LinkedBlockingQueue<Message> queue; @Autowired @Qualifier("BillSkyes") private MatchReporter matchReporter; /** * Subscribe to a match */ public void subscribe() { matchReporter.start(); } /** * * Get hold of the latest match update */ public Message getUpdate() { try { Message message = queue.take(); return message; } catch (InterruptedException e) { throw new UpdateException("Cannot get latest update. " + e.getMessage(), e); } } }

SimpleMatchUpdateService也包含两个方法。 第一个, MatchReporter subscribe() ,告诉MatchReporter开始将更新放入队列。 第二个getUpdate()Queue删除下一个更新,并将其作为JSON返回给浏览器以显示。

到目前为止,一切都很好; 但是,在这种情况下,队列是由LinkedBlockingQueue的实例实现的。 这意味着,如果浏览器发出请求时没有可用的更新,则请求线程将阻塞queue.take()方法,从而占用宝贵的服务器资源。 可用更新时, queue.take()返回并将Message发送到浏览器。 对于没有经验的研究生培训生来说,一切似乎都很好,并且代码可以上线。 在接下来的周六,这是英超联赛的开始(如果您在美国,则是足球比赛),也是体育日历最繁忙的周末之一,并且有大量用户希望获得有关大型比赛的最新信息。 当然,服务器资源不足,无法处理负载并不断崩溃。 电视公司的总裁对此不太满意,因此召集了敏捷牛仔公司的首席执行官到他的办公室。 他明确表示,如果不解决此问题,血液将流动。 Agile Cowboys的首席执行官意识到了自己的错误,并在与女友吵架后收回了保时捷。 然后,他通过电子邮件向Java / Spring顾问发送电子邮件,如果他要来修复代码,则向他提供保时捷。 Spring顾问不能拒绝这样的提议并接受。 这主要是因为他知道Servlet 3规范通过允许将ServletRequest置于异步模式来解决了这个问题。 这样可以释放服务器资源,但可以保持ServletResponse打开,从而允许其他一些第三方线程完成处理。 他还知道,Spring的家伙们在Spring3.2中想出了一种新技术,称为“延迟结果”,该技术专为这些情况而设计。 同时,Agile Cowboys CEO的前女友仍对失去保时捷感到不安,向他的妻子发送电子邮件,告诉她有关丈夫的外遇的一切……

当这个博客变成达拉斯的一集时,我认为它的时代到此结束。 那么,代码会及时修复吗? Java / Spring顾问会花太多时间驾驶他的新保时捷吗? 首席执行官会原谅他的女朋友吗? 他的妻子会与他离婚吗? 有关这些问题的答案,以及下次有关Spring的DeferredResult技术调整的更多信息, …

您可能已经注意到,示例代码中还有另一个巨大的漏洞,那就是只能有一个订户。 由于这仅是示例代码,而我在谈论的是长时间轮询,而不是实现发布和订阅,因此问题出在“主题之外”。 我稍后可能会(也可能不会)对其进行修复。

该博客随附的代码可在Github上找到:https://github.com/roghughe/captaindebug/tree/master/long-poll

参考:来自Captain Debug's Blog博客的JCG合作伙伴 Roger Hughes 提供的Spring Long Polling Tomcat 。

翻译自: https://www.javacodegeeks.com/2013/08/long-polling-tomcat-with-spring.html

tomcat 轮询

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/347684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

免费网络研讨会:Java应用程序中的吞咽异常

1月30日参加我们的网络研讨会&#xff0c;以发现Java应用程序中的“隐藏”异常。 如果一棵树落在森林中&#xff0c;但是没有写到原木上&#xff0c;它会发出声音吗&#xff1f; 答案是肯定的。 这些类型的错误可能会对用户体验造成严重影响&#xff0c;而没有根本原因的可见性…

Java面向对象(17)--类代码块

静态代码块&#xff1a;用static 修饰的代码块 ①可以有输出语句。 ②可以对类的属性、类的声明进行初始化操作。 ③不可以对非静态的属性初始化&#xff0c;即&#xff1a;不可以调用非静态的属性和方法。 ④ 静态代码块随着类的加载而加载并执行&#xff0c;类加载一次&…

js 和java有关系吗,javascript和JAVA有什么关系

2017-07-28Java调用javascriptpackage co。test;import java。io。FileReader;import java。io。LineNumberReader;import org。mozilla。 javascript。Context;import org。mozilla。javascript。Function;import org。mozilla。javascript。Scriptable;public class JSExplor…

php检测一个变量是否设置函数,php如何判断变量是否有设置的函数

php判断变量是否有设置的函数的方法&#xff1a;可以利用isset()函数来进行判断。isset()函数用于检测变量是否已设置并且非NULL。如果指定变量存在且不为NULL&#xff0c;则返回TRUE&#xff0c;否则返回FALSE。isset() 函数用于检测变量是否已设置并且非 NULL。(推荐教程&…

mockito_吸收Mockito的流利度

mockito我最近发现自己编写了一些代码来集成两个不同的平台。 这些系统之一是基于Java的系统&#xff0c;而另一个虽然不是用Java编写的&#xff0c;却提供了Java API。 我将这些系统分别称为Foo和Bar。 在我编写一行代码之前就很明显了&#xff0c;但是&#xff0c;测试最终…

Java异常处理(1)--异常概述与异常体系结构

在Java语言中&#xff0c;将程序执行中发生的不正常情况称为“异常”。(开发过程中的语法错误和逻辑错误不是异常) Java程序在执行过程中所发生的异常事件可分为两类&#xff1a; ①Error&#xff1a;Java虚拟机无法解决的严重问题。如&#xff1a;JVM系统内部错误、资源耗尽等…

Payara Micro在Oracle应用容器云上

在此博客文章中&#xff0c;我将介绍如何将打包在Payara Microber -jar中的CloudEE Duke应用程序部署到Oracle Application Container Cloud 。 在Oracle Application Container Cloud中进行部署所需的部署工件是一个ZIP归档文件&#xff0c;其中包含应用程序ber-jar和清单文件…

Java异常处理(2)--异常处理机制及自定义异常

在编写程序时&#xff0c;经常要在可能出现错误的地方加上检测的代码&#xff0c;如进行x/y运算时&#xff0c;要检测分母为0&#xff0c;数据为空&#xff0c;输入的不是数据而是字符等。过多的if-else分支会导致程序的代码加长、臃肿&#xff0c;可读性差。因此采用异常处理机…

jaas_受JAAS保护的JAX-RS端点

jaas随着RESTFUL&#xff08;JAX-RS&#xff09;作为创建Web服务端点的“首选”方式的问世&#xff0c;很长一段时间以来&#xff0c;我一直想知道人们如何围绕它实现安全机制。 归根结底&#xff0c;我假设JAX-RS的基础实现是servlet&#xff0c;因此其安全性也可能围绕容器&…

Java多线程(1)--基本概念:程序、进程、线程

程序(program)是为完成特定任务、用某种语言编写的一组指令的集合。即指一段静态的代码&#xff0c;静态对象。 进程(process)是程序的一次执行过程&#xff0c;或是正在运行的一个程序&#xff0c;是一个动态的过程&#xff1a;有它自身的产生、存在和消亡的过程。——生命周…

Java中的Volatile如何工作? Java中的volatile关键字示例

如何在Java中使用Volatile关键字 在Java采访中&#xff0c;什么是volatile变量以及何时在Java中使用volatile变量是Java 采访中一个著名的多线程采访问题 。 尽管许多程序员都知道什么是volatile变量&#xff0c;但是他们在第二部分上失败了&#xff0c;即在Java中何处使用vol…

Java线程的调度及线程的优先级

调度策略 Java的调度方法 同优先级线程组成先进先出队列&#xff08;先到先服务&#xff09;&#xff0c;使用时间片策略。 对高优先级&#xff0c;使用优先调度的抢占式策略。 线程的优先级等级 Thread.MAX_PRIORITY&#xff1a;10 Thread.MIN _PRIORITY&#xff1a;1 Threa…

Spring Boot 2应用程序和OAuth 2 –传统方法

这篇文章是3个系列文章中的第二部分&#xff0c;探讨了如何为基于Spring Boot 2的应用程序启用OSO2提供程序SSO。 3个帖子是&#xff1a; 1. 引导兼容OpenID Connect的OAuth2授权服务器/ OpenID提供程序的方法 2.与OAuth2授权服务器/ OpenID提供程序集成的旧版Spring Boot / …

Java多线程(2)--Thread类继承和Runnable接口创建线程

Java语言的JVM允许程序运行多个线程&#xff0c;它通过java.lang.Thread类来体现。 Thread类的特性 每个线程都是通过某个特定Thread对象的run()方法来完成操作的&#xff0c;经常把run()方法的主体称为线程体&#xff0c;通过该Thread对象的start()方法来启动这个线程&#x…

matlab在电磁场与电磁波中的应用,matlab在电磁场与电磁波学习中的应用.docx

matlab在电磁场与电磁波学习中的应用.docx MATLAB在电磁场与电磁波学习中的应用裴逸菲(燕京理工学院信息科学与技术学院&#xff0c;河北廊坊065201)摘要针对电磁场与电磁波在大学课程中的理论性强、概念抽象的特点&#xff0c;在学习中引入MATLAB软件&#xff0c;利用MATLAB的…

Java多线程(3)--线程的生命周期

JDK中用Thread.State类定义了线程的五种状态 要想实现多线程&#xff0c;必须在主线程中创建新的线程对象。Java语言使用Thread类及其子类的对象来表示线程&#xff0c;在它的一个完整的生命周期中通常要经历如下的五种状态&#xff1a; ①新建&#xff1a; 当一个Thread类或…

m序列自相关matlab代码,m序列的输出及其自相关序列

【例10-2】 设m序列的生成多项式为g(x)1x^3x^4&#xff0c;求&#xff1a;(1)m序列的输出及其自相关序列&#xff1b;(2)脉冲波形成为矩形脉冲p(t){1 0≤t≤Tc 画出m序列信号的自相关函数&#xff1b;{0 其它 &#xff0c;(3)设脉冲波形为升余弦函数(滚降系数a0)&#xff0c;画…

JDK 10:从Java访问Java应用程序的进程ID

StackOverflow.com上一个普遍的问题是&#xff1a;“ Java程序如何获得自己的进程ID&#xff1f; 与该问题相关的几个答案包括解析ManagementFactory返回的String 。 getRuntimeMXBean&#xff08;&#xff09; 。 getName&#xff08;&#xff09; [但是可以提供“任意字符串”…

spring常见面试问题_Spring面试问题

spring常见面试问题另外&#xff0c;请查看我们最新的文章69Spring面试问题与解答–最终清单 。 1&#xff09;什么是春天&#xff1f; 回答&#xff1a; Spring是控件和面向方面的容器框架的轻量级反转。 2&#xff09;解释春天&#xff1f; 回答&#xff1a; 轻巧&#x…

matlab谱系聚类图,如何看懂SPSS聚类分析的树状图/谱系图?

原创&#xff1a; 数据小兵 SPSS统计训练营SPSS聚类分析提供两种类别图形的输出&#xff0c;第一种是软件默认的“冰柱图”&#xff0c;形状类似于冬天屋檐上垂下的冰柱&#xff0c;因此得名。第二种是“树状图”&#xff0c;在新版本软件中也称谱系图&#xff0c;像一个横着生…