Play!中使用HTTP异步编程
本章译者:@Sam Liu (译者未留下自己的主页,请Sam Liu见此文,加入群168013302联系‘大黄蜂@翻译play’)
这一章主要讲解如何运用异步模式实现典型的长连接(long-polling)、流(streaming)和 推送方式(Comet-style
) 的编程,以便于响应数以千万计的并发请求。
延缓(Suspending) HTTP 请求
Play主要是用于处理很短的请求。它使用一个固定的线程池来处理用户的HTTP请求。为获得最佳效果,这个线程池当然是越小越好。我们一般用@处理器数+1@这个比较恰当的值来作为默认的池大小。
这也就意味着如果一个请求持续很长时间(比如等待一个长时间的计算)它就会阻塞线程池并且降低服务的响应能力。当然你也可以给池中增加更多的线程,但是那会浪费很多的资源而且池的大小总不可能是无限的。
设想一个聊天服务,当各个浏览器终端发出请求等待显示新的消息。这些请求一般都会很长(通常都要好几秒钟)这必然会阻塞线程池。如果你打算同时支持100个人聊天,那你就要准备至少100个线程。好吧这不算什么,但是如果是1000个呢?10000个呢?
为了解决这类总是,Play允许你临时延缓(suspend)一个请求。这个HTTP请求将保持连接,但会被推出线程池稍后再试。你可以告诉Play在适当的延迟后或得到一个@Promise@的返回值后再次处理这个请求。
Tip
. 你可以看一个实例:@samples-and-tests/chat@.
例如,这个action会处理一个很长时间的job并且等到完成后再返回结果到HTTP response:
public static void generatePDF(Long reportId) {
Promise<InputStream> pdf = new ReportAsPDFJob(report).now();
InputStream pdfStream = await(pdf);
renderBinary(pdfStream);
}
这里我们使用了@await(…)@来让Play延缓处理这个请求,直到返回@Promise@的结果。
Continuations
为了重新获得之前响应其他请求的线程,框架必须暂停执行你的代码。在Play之前的版本使用的是@waitFor(…)@,也就是现在所说的@await(…)@,用它来延缓你的action,稍后再回来执行。
为了更方便地处理异步的代码,我们来介绍一下continuations。Continuations可能让你的代码很自然地暂停后再重新开始。于是你可以象下命令一样来写你的代码,如下:
public static void computeSomething() {
Promise<String> delayedResult = veryLongComputation(…);
String result = await(delayedResult);
render(result);
}
实际上在这儿,你的代码会被分为两步,在两个不同的线程中来执行。但正如你所看到的,在你的代码中是感觉不到的。
你可以使用 await(…)
和 continuations 来写一个循环:
public static void loopWithoutBlocking() {
for(int i=0; i<=10; i++) {
Logger.info(i);
await("1s");
}
renderText("Loop finished");
}
即使是在开发模式,默认只有一个线程来处理请求,Play也可以在同一时间并行地运行这些循环。
HTTP 输出流
现
在你可以运行这类循环而不必担心阻塞线程,同时你肯定还想每当取得一部分有效的结果时就把结果发到浏览器客户端。这就是@Content-
Type:Chunked@这个HTTP输出类型的作用。它可以使你用多个chunks来分批发送HTTP结果。浏览器则会马上显示出收到的结果。
使用 await(…)
和 continuations, 你现在就可以实现它了:
public static void generateLargeCSV() {
CSVGenerator generator = new CSVGenerator();
response.contentType = "text/csv";
while(generator.hasMoreData()) {
String someCsvData = await(generator.nextDataChunk());
response.writeChunk(someCsvData);
}
}
即使这个CSV的生成要耗费一个小时,Play也可以用一个线程同时处理多次请求,并且每当有最新的结果时就返回给客户端。
使用 WebSockets
WebSockets是一个连接浏览器和应用服务的双向通信通道。在浏览器一边,你可以用“ws://”打开一个socket通道:
new Socket("ws://localhost:9000/helloSocket?name=Guillaume")
而在Play这边,你可以声明一个WS的route:
WS /helloSocket MyWebSocket.hello
MyWebSocket
是一个 WebSocketController
。 一个 WebSocket 的 controller 和一个标准的 HTTP controller 类似,但也有一些不同的概念:
- 它有一个请求 request 对象,但却没有 response 返回对象。
- 它可以访问 session,但是只读的。
- 它没有
renderArgs
, routeArgs
或 flash scope 。
- 它只能从 route 路径或 QueryyString 路径字串中读取参数。
- 它有两个通信通道: inbound 输入 和 outbound 输出。
当客户端连接 ws://localhost:9000/helloSocket
socket 通道,Play 就会运行 MyWebSocket.hello
action 方法。一旦 MyWebSocket.hello
action 方法退出,这个 socket 通道就关闭了。
下面是一个非常简单的socket例子:
public class MyWebSocket extends WebSocketController {
public static void hello(String name) {
outbound.send("Hello %s!", name);
}
}
在这个例子中,客户端连接socket,收到“Hello Guillaume”的消息,然后这个 socket 就关闭了。
当然了通常你并不想马上关闭这个 socket。而使用 await(…)
可以很容易地保持连接。
如下是一个非常简单的 Echo 响应服务:
public class MyWebSocket extends WebSocketController {
public static void echo() {
while(inbound.isOpen()) {
WebSocketEvent e = await(inbound.nextEvent());
if(e instanceof WebSocketFrame) {
WebSocketFrame frame = (WebSocketFrame)e;
if(!e.isBinary) {
if(frame.textData.equals("quit")) {
outbound.send("Bye!");
disconnect();
} else {
outbound.send("Echo: %s", frame.textData);
}
}
}
if(e instanceof WebSocketClose) {
Logger.info("Socket closed!");
}
}
}
}
在上面的例子中,多层嵌套的“if“ 和 ”cast“ 写起来很烦而且极易出错。在这儿就体现出Java的糟糕之处。即使象这样一个简单的示例都这么难处理,如果碰到更复杂的情况,比如你要组合多个数据流,并且有更多的事件类型,那将会是一场恶梦。
因此我们要介绍一个Java的简单匹配模式,是在 play.libs.F
这个函数式编程的库中。
那么之前的Echo的例子就可以重写为下面这样:
public static void echo() {
while(inbound.isOpen()) {
WebSocketEvent e = await(inbound.nextEvent());
for(String quit: TextFrame.and(Equals("quit")).match(e)) {
outbound.send("Bye!");
disconnect();
}
for(String msg: TextFrame.match(e)) {
outbound.send("Echo: %s", frame.textData);
}
for(WebSocketClose closed: SocketClosed.match(e)) {
Logger.info("Socket closed!");
}
}
}
继续这个话题
接下来, 实现 Ajax 请求
.
相关推荐
2. **异步编程**:Play Framework基于Akka框架,支持非阻塞I/O和异步处理,提高了Web应用的并发性能。 3. **路由系统**:Play Framework的路由文件定义了URL到Action的映射,允许开发者灵活地控制请求处理逻辑。 4...
5. **异步编程**:Play基于Akka框架,支持非阻塞I/O和异步处理,这使得它在处理高并发请求时表现优秀。通过Future和Promise对象,你可以编写高效的并发代码。 6. **测试支持**:Play提供了内置的测试工具,如...
10. **异步编程**:Play支持异步Jobs、预定义任务和HTTP下的异步编程,如使用Continuations、Callbacks和HTTP响应流,以及WebSockets,提高了系统的并发能力。 11. **测试**:Play提供了丰富的测试工具,包括单元...
而"playframework-2.7.9"可能是一个解压后的目录,其中包含了框架的全部源代码、库文件、示例项目、构建脚本等。 Play Framework的核心特性包括: 1. **异步编程模型**:Play Framework利用Akka Actor系统实现非...
2. **异步编程模型**:Play Framework 使用非阻塞I/O和事件驱动模型,使得它在处理高并发请求时表现优秀,特别适合构建实时Web应用。 3. **路由系统**:Play 的路由文件定义了URL到控制器方法的映射,提供了声明式...
Play-Utils 模块是为 Play Framework 设计的一个强大且实用的工具集合,它极大地提升了开发者在使用 Play Framework 进行 Java Web 开发时的效率和便利性。Play Framework 是一个开源的、基于 MVC(模型-视图-控制器...
2. **异步编程**:Play 使用非阻塞I/O,这使得它在处理高并发请求时表现优秀。通过Akka框架,Play 支持事件驱动的编程模型,提高了系统的响应速度和资源利用率。 3. **RESTful风格**:Play 鼓励开发符合REST原则的...
- **数据库访问**:学习如何在Play应用程序中使用JPA、Slick或Ebean等ORM工具进行数据库操作。 - **模板和视图**:学习使用模板引擎创建动态视图。 - **测试**:了解Play提供的测试工具和测试策略,编写单元测试和...
1. **异步编程模型**:Play Framework使用Akka Actor系统,支持非阻塞I/O和事件驱动编程,这使得它能处理大量并发请求,提高了应用程序的性能。 2. **热重载**:在开发过程中,Play框架支持代码的实时更新,无需...
在描述中提到的压缩包中,你将找到关于PlayFramework的使用教程和相关代码示例,这对于学习和理解这个框架非常有帮助。 1. **MVC架构**: PlayFramework基于MVC设计模式,使得开发者可以清晰地分离业务逻辑、数据...
2. **异步编程模型**:Play Framework基于Akka Actor模型,采用非阻塞I/O,提高了Web应用的并发性能。这在处理大量并发请求时尤其有利,降低了服务器资源的消耗。 3. **路由系统**:Play Framework的路由系统将URL...
通过采用一种叫做“响应式编程”的模式,Play! Framework 能够让开发者快速地开发出可扩展的应用程序。此框架在设计上注重简化开发流程,使得即使是初学者也能快速上手。 #### 二、Play! Framework 2 的特点 1. **...
文件列表中,“HTTP-Proxy-Using-Play-Framework-and-WS-API.pdf”可能是一个详细的教程或者技术文档,涵盖了如何使用Play Framework和WS API实现HTTP代理的步骤。而“LogOn.aspx?rp=%2FKB%2Fwebservices%2F1038969%...
对于异步编程,Play Framework采用了Akka Actor系统,这是基于消息传递的并发模型,能够很好地处理高并发场景。Akka的使用让Play可以构建高度响应式的应用,避免了传统阻塞I/O可能带来的性能瓶颈。 在测试方面,...
4. **异步I/O**:Play利用Akka框架的反应式编程模型,实现了非阻塞I/O,提高了并发处理能力。 5. **模板引擎**:Play内置了模板引擎,允许开发者使用简单的语法编写HTML,同时支持嵌入Java或Scala代码,实现动态...
10.在HTTP下进行异步编程 - 89 - 暂停http请求 - 89 - Continuations - 90 - 回调Callbacks - 91 - HTTP response流 streaming - 92 - 使用WebSockets - 92 - 11.在play框架里使用Ajax - 94 - 通过jsAction标签使用...
2. **异步编程模型**:Play Framework 基于Akka框架,采用非阻塞I/O模型,这使得它在处理高并发请求时性能优秀。 3. **路由系统**:路由是Play的核心部分,它定义了HTTP请求如何映射到应用中的Action。在`conf/...
文档提及Playframework版本为1.2.3,该版本使用Maven作为构建工具,允许开发者使用Maven插件来管理项目依赖和构建过程。Play框架使用约定优于配置的方法,这意味着它为项目的布局和约定了一些默认的设置,例如把模型...
你可以在这里找到关于模板引擎、异步编程、测试、安全性和国际化等方面的内容。它是深入理解Play框架并提升开发技能的重要资源。 5. **Play-framework最新教程** 最新教程可能涵盖框架的最新版本更新,以及与先前...
Play Framework 是一个开源的Web应用框架,主要使用Java和Scala语言开发,基于MVC(Model-View-Controller)设计模式。这个框架强调简洁、反应式和模块化开发,旨在提高开发者的生产力,使得构建高性能、易测试且可...