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,一经查实,立即删除!

相关文章

单例(Singleton)设计模式应用场景

网站的计数器&#xff0c;一般也是单例模式实现&#xff0c;否则难以同步。 应用程序的日志应用&#xff0c;一般都使用单例模式实现&#xff0c;这一般是由于共享的日志文件一直处于打开状态&#xff0c;因为只能有一个实例去操作&#xff0c;否则内容不好追加。 数据库连接…

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

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

php bloginfo templatedirectory,WordPress函数:bloginfo(显示博客信息)

描述显示你的博客信息&#xff0c;大部分都是显示WordPress管理界面的 用户资料 和 常规设置 中的信息。它可以在模板文件的任何地方使用。一般 bloginfo() 都是用来直接在浏览器中输出内容的。如果你需要在PHP中返回值的话&#xff0c;那么请用 get_bloginfo()。用法<?php…

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…

gson 入门_Google GSON入门

gson 入门在Java世界中&#xff0c;JSON已成为事实上的XML数据交换格式标准&#xff0c;因为它的易用性和传输效率高。 如果您不了解JSON&#xff0c;那就是Javascript对象表示法&#xff0c;这是一种基于文本的数据交换格式&#xff0c;是名称-值的集合&#xff0c;其中名称严…

Java面向对象(18)--final关键字使用

在Java中声明类、变量和方法时&#xff0c;可使用关键字final来修饰,表示“最终的”。 final标记的类不能被继承&#xff0c;提高安全性&#xff0c;提高程序的可读性 如&#xff1a;String类、System类、StringBuffer类。 final标记的方法不能被子类重写 如&#xff1a;Objec…

php 高级搜索下拉框,高级搜索页面advancedsearch.php调用自定义字段

下面跟大家谈的是关于”如何在在高级搜索页面advancedsearch.php调用自定义字段“方法&#xff1a;步骤&#xff1a;找到advancedsearch.php页面。$query "select main.id as aid,main.*,main.description as description1, type.* from $maintable main left join dede2…

创新设计模式:抽象工厂模式

抽象工厂模式是一种创建模式&#xff0c;是与构建器和工厂模式一起最受欢迎的模式之一。 使用创建模式是为了创建对象&#xff0c;而不是直接使用构造函数创建对象。 抽象工厂模式提供了一种封装一组具有共同主题的单个工厂而无需指定其具体类的方法。 采用该模式的目的是使对…

php算法台阶,php如何解决青蛙跳台阶的问题(代码)

本篇文章给大家带来的内容是关于php如何解决青蛙跳台阶的问题(代码)&#xff0c;有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对你有所帮助。一只青蛙一次可以跳上1级台阶&#xff0c;也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后…

Java面向对象(19)--抽象类与抽象方法abstract

用abstract关键字来修饰一个类&#xff0c;这个类叫做抽象类。 用abstract来修饰一个方法&#xff0c;该方法叫做抽象方法。 抽象方法&#xff1a;只有方法的声明&#xff0c;没有方法的实现。以分号结束&#xff1a; 比如&#xff1a;public abstract void talk(); 含有抽象…

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

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

Java面向对象(20)--接口

接口的使用 ①接口使用interface来定义 ②Java中&#xff0c;接口和类是并列的两个结构 ③定义接口中的成员 JDK7及以前:只能定义全局常量和抽象方法 全局常量: public static final修饰的&#xff0c;书写时&#xff0c;可以省略不写 抽象方法: public abstract修饰的&#x…

java轮询文件停止线程,java 运行多线程轮询时,外部停止轮询

1&#xff0c;先建一个Map/*** 创建一个Map用于存放线程id对象集合&#xff0c;主要是用于到达岗亭之后扫码付费&#xff0c;如果人工收费就需要关闭线程&#xff0c;key是停车记录Id&#xff0c;*/public static MapMAPTHREAD new HashMap();2.建一个线程类继承Runnable/*** …

Java面向对象(21)--内部类

当一个事物的内部&#xff0c;还有一个部分需要一个完整的结构进行描述&#xff0c;而这个内部的完整的结构又只为外部事物提供服务&#xff0c;那么整个内部的完整结构最好使用内部类。 在Java中&#xff0c;允许一个类的定义位于另一个类的内部&#xff0c;前者称为内部类&a…

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和清单文件…

认知无线电matlab代码详解,认知无线电频谱感知之功率检测matlab代码.docx

认知无线电频谱感知之功率检测matlab代码能量检测仿真实验代码&#xff1a;clear all;clc;n 5;ps 1;SNR1 -5;SNR2 -8;SNR3 -10;% Sim_Times10000; %Monter-Carlo times% m5;T0.001;% 信号带宽W W5*10^4;% 采样频率Fs 2*W;m T*W;n 2*T*W;% F0W;% Fs2;% Sigsqrt(2)*sin(2…

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

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