Ratpack可快速开发异步响应式的Java Web应用

15-09-27 banq
Ratpack是一款类似Node.JS但是更强的基于JVM多线程多核的Java Web框架,可以快速有效地开发基于Http异步的高性能Web应用,它使用Netty作为其事件驱动引擎。

Ratpack主要瞄准基于JVM的异步编程快速化,Ratpack的处理模型类似Node.js,如下图:


四核CPU机器中,每个CPU一个线程,对应一个事件循环Event Loop,Ratpack适合解决CPU-bound类型应用,也就是耗费CPU的应用,当它启动一个event loop时,使用的是非堵塞方式,每个线程一个event loop,对应每个CPU,如果你有需要更多负载处理,你可以增加CPU核数量即可,这有点类似于Servlet应用,每个请求会启动得一个新的线程来处理这个请求,但是Servlet这种模型在应对大量请求时,会启动大量线程,CPU忙于在这些线程间进行上下文切换,严重影响了性能。

通过引入Netty,Ratpack创建了一个Event Loop Group,也就是事件循环组,将类似Node.js的单线程Event Loop于每个CPU核绑定,而Node.js则需要Cluster之类外加框架进行这种多核多Event Loop启动,每个Event Loop会接受客户端Http请求,它们会异步委托给Ratpack进行处理。

当前,JVM领域建立非堵塞 异步Web应用有一些问题,许多JVM库包不是基于异步的,比如JDBC,而Ratpack可以使得任何API变成异步使用,通过其执行模型,Ratpack能够平滑地在Event Loop之间调度工作量,非异步如JDBC之类库包能被包装进入异步装置,也就是说,可以将它们的处理放在请求线程池之外的地方进行,减少请求借用线程池线程的时间。当调用完成后,处理会返回给Event Loop。

这个流程一个重要的特性是:当堵塞调用返回时,它们的处理将被返回到原来启动计算的那个线程,这样就不需要CPU对线程之间进行额外的上下文切换,通过暂停线程然后再继续的方式处理数据,也就是说,任何数据都会在堵塞之前被计算好,放入CPU缓存中处于待命状态,这就会导致更好性能和非常高的效率,在32核机器中,测试一个简单“hello world” 应用,可以达到每秒一百万的请求量。

另外,JVM上的异步编程是非常难的,这已经是臭名昭著,因为虚拟机并没有实现Continuation概念,.使用的是non-deterministic, 这种模型不适合Web应用,会导致超时等待,而且难以定位发生的问题。Ratpack提出一种处理流processing stream概念,非常类似于continuation. 对于每个promise类型(代表某个数据值会在稍后时间才能变得可用,也就是稍后才能用这个数据,这个数据不是立即计算出来的),你都可以使用框架创建一个异步操作,你能创建sub-processing stream,它是一种continuation思想实现,这些流是一个完整的链条,以FIFO顺序执行,这个流是启动时有一个标志, 这样框架能够决定这个流什么时候结束,如果在这个sub-stream中出现错误,比如是某种安静的致命错误,Ratpack会注意到发生的处理,然后通知客户端没有响应了,也就是有一种可提供确定性行为的机制。

Ratpack需要Java 8, Netty, Google Guava 和 Reactive Streams.

Ratpack: Simple, lean & powerful HTTP apps

InfoQ:Ratpack 1.0 Launches Aiming to make Asynchronous Programming Easier on the JVM

[该贴被admin于2015-09-28 07:59修改过]

8
sinaID53244
2015-09-27 21:25
非常不错的理念,点赞一下!

lileiqx
2015-09-28 09:21
Vert.x 有什么区别?

banq
2015-09-28 12:52
2015-09-28 09:21 "@lileiqx"的内容
和 Vert.x 有什么区别? ...

Ratpack应该比Vert.x考虑更全面,让异步编程更容易,这句话应该是针对vert.x说的。

wldst
2015-09-29 00:20
好新的东东,感觉不错。

flyzb
2015-09-29 00:37
前段时间研究过spring boot ,发现使用Embed的jetty或tomcat都有一个严重性能问题,一个空rest调用竟然要消耗几百毫秒,让人难以接受。其他框架比如Qbit的rest性能也差不多,而Ratpack的rest性能基本在10ms左右。

banq
2015-09-30 08:25
参考:

Node.js的事件轮询Event Loop原理解释

tecentID6034F
2016-05-06 11:11
板桥,有没有入门资料

banq
2016-05-07 11:04
2016-05-06 11:11 "@tecentID6034F"的内容
板桥,有没有入门资料 ...

Ratpack最好和RxJava一起使用,因为Ratpack的执行模型是串行异步,不是并行异步,另外在微服务中通过RxJava可以将Ratpack的Promise模型隐藏起来,代码不会再严重依赖Ratpack。

在其他系统中,“异步”和”并行“是可交换的,同时具备的,比如你发出3个异步GET请求,三个请求都好像是同时发出的,也就是说:在任何一个请求得到回应之前,其他两个请求肯定是已经也发出了。

但是Ratpack并不是这么工作的,你发出异步3个GET请求,Ratpack 会等待第一个完成后再发出第二个。

Ratpack Executions: Async + Serial, Not Parallel一文详细解释这种机制。

在一个执行过程ratpack实现所有工作都是在同一个线程,,这种工作方式是充分串行的. 这就暗示:如果你使用ratpack对后端微服务进行Http请求,你的请求将是一个挨着一个发出的,即使你使用的是完整非堵塞http API。

为了实现真正异步+并发,使用RxJava的Observable工作在Ratpack的Execution模型之上。

关于Ratpack使用方式,提供两个参考:

Ratpack’s execution model

在一个Stream中使用Akka Streams, Ratpack, Reactor 和RxJava的代码:

https://github.com/smaldini/ReactiveStreamsExamples/blob/master/src/main/java/org/reactivestreams/examples/Interop101.java

Lesson learned with Ratpack and RxJava

[该贴被banq于2016-05-07 11:16修改过]

猜你喜欢