領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多我們很高興地宣佈,經過長時間的內部孵化,我們正在釋出一個用於 JVM 非同步應用程式的基礎框架,我們稱之為 Reactor。它為 Java、Groovy 和其他 JVM 語言提供了抽象,使構建事件和資料驅動的應用程式變得更容易。它也確實很快。在適度的硬體上,使用最快的非阻塞 Dispatcher 每秒可以處理超過 15,000,000 個事件。其他排程器也可用,為開發人員提供從執行緒池風格、長時間執行的任務執行到非阻塞、高容量任務排程的多種選擇。GitHub 倉庫在此:https://github.com/reactor/reactor。
Reactor,顧名思義,深受著名的 Reactor 設計模式的影響。但它也受到其他事件驅動設計實踐以及多年來開發的幾種出色的基於 JVM 的解決方案的影響。Reactor 的目標是將這些想法和模式濃縮成一個簡單且可重用的基礎,以使事件驅動程式設計變得更加容易。
Reactor 的抽象為開發人員提供了一套工具,不僅可以開發,還可以組合應用程式,以更有效地利用系統資源——這在雲中執行時尤為重要——並減少或消除至今困擾大多數非同步應用程式的巢狀回撥(恰當地稱為“回撥地獄”)的混亂。
雖然由於其固有的靈活性,您可以用 Reactor 做很多事情,但它實際上被設計為需要高吞吐量執行相對較小的無狀態非同步處理塊的應用程式的基礎框架。現代應用程式中非人類生成資料的巨大數量很容易壓垮傳統的單執行緒阻塞設計模型。從生成位置資訊流的移動應用程式,到傳送大量幾何資料的計算機化製造機器,再到挖掘即時日誌以生成業務指標的大資料應用程式:現代資料驅動的應用程式需要比傳統命令式阻塞應用程式通常能提供的更好的資源利用率和更高的吞吐量。
這就是為什麼Spring XD 專案(以及 Spring Integration 和 Spring Batch 等其他 Spring 生態系統專案)打算利用 Reactor。將 Reactor 的非同步排程與 Spring Integration 基於 NIO 的 TCP 介面卡結合起來,提供高吞吐量的 syslog 和 MQTT 攝取,這只是一個例子。
Reactor 的 reactor-core 模組中三個最基礎的元件是 Selector、Consumer 和 Event。可以透過使用 Selector 將 Consumer 分配給 Reactor,Selector 是一個簡單的抽象,用於在查詢要為 Event 呼叫的 Consumer 時提供靈活性。提供了一系列預設選擇器。從普通字串到正則表示式再到 Spring MVC 風格的 URL 模板。
這是一些示例程式碼,展示了使用 Reactor 建立事件驅動應用程式是多麼容易。
// This helper method is like jQuery’s.
// It creates a Selector instance so you don’t have
// to construct one using 'new Selector("parse")'
import static reactor.Fn.$;
Reactor reactor = R.create();
// Register interest in events published to key "parse"
reactor.on($("parse"), new Consumer<Event<String>>() {
public void call(Event<String> ev) {
service.handleEvent(ev);
}
});
// Send an event to this Reactor and trigger all actions
// that match the given Selector
reactor.notify("parse", Fn.event("Hello World!"));
Reactor 分發包中包含一個名為 reactor-groovy 的模組。它包含一個 Groovy 繫結,提供富有表現力的語法、使用 @CompileStatic 進行編譯時檢查、將 Closure 隱式轉換為 Consumer,以及其他 Groovy 特有的省時功能。
// Assign a Closure as a Consumer
reactor.on($('hello')) { Event<String> ev ->
if(ev.headers['specialHeader']) { // Events can have metadata
doSomethingWith(ev.data)
}
}
// Use Groovy helpers for notify
reactor.notify for: 'hello', data: 'Hello World!', specialHeader: 'specialValue'
最好的部分是:我們無需犧牲效能。相同的 JVM 最佳化適用於 Groovy 程式碼,也適用於 Java 程式碼。我們持續(有些人會說“執著地”)對排程程式碼進行微基準測試,使其儘可能快,併為 Java 和 Groovy 使用者提供儘可能高的吞吐量。
Reactor 還設計為與Java SE 8 的 lambda 表示式友好,Reactor 中的許多元件都可以用 lambda 替換,使您的 Java 程式碼更加簡潔。我們還發現使用 Java 8 lambda(和方法引用)會帶來略高的吞吐量。當 Java 8 釋出正式版時,您無需等待 Reactor 支援它。它會“Just Work (tm)”。
// Use a POJO as an event handler
class Service {
public <T> void handleEvent(Event<T> ev) {
// handle the event data
}
}
@Inject
Service service;
// Use a method reference to create a Consumer<Event<T>>
reactor.on($("parse"), service::handleEvent);
// Notify consumers of the 'parse' topic that data is ready
// by passing a Supplier<Event<T>> in the form of a lambda
reactor.notify("parse", () -> {
slurpNextEvent()
});
Executor、Event Loop、Actor、分散式——在事件驅動程式設計中最重要的用例之一——任務排程,有多種形式。Reactor 支援多種事件驅動程式設計風格。除了傳統的回撥式 Consumer 介面,Reactor 還對 Promises/A+ 規範進行了解釋,使得處理延遲值和消費者變得非常容易。
巢狀回撥在像 Java 這樣的命令式語言中雖然直接易用,但當應用程式的複雜性增加時,維護起來就變得困難。Reactor 的 Composable 和 Promise 都旨在輕鬆組合操作。您可以將 Composable 串聯成一系列操作,用於轉換值、將資料儲存到資料儲存、聚合值等等。由於它們是可串聯的,您可以透過型別安全的方式在純 Java 中完成所有這些操作。這是一個使用 Composable 輕鬆串聯一系列非同步執行任務的快速示例,這些任務在資料流透過 Composable 時對其進行轉換和過濾。
Composable<Integer> c = new Composable<>()
.map(new Function<Integer, Integer>() {
public Integer apply(Integer i) {
return i % 2;
}
})
.filter(new Function<Integer, Boolean>() {
public Boolean apply(Integer i) {
return i == 0;
}
})
.consume(new Consumer<Integer>() {
public void accept(Integer eveni) {
// work with only even numbers here
}
});
Composable 的每一步都是一個潛在的非同步任務。對 map、filter 和 consume 的呼叫會在前一步的值可用時分配要執行的任務——無需回撥地獄。
對於任何排程問題,都沒有萬能的解決方案。Reactor 提供了不同風格的 Dispatcher,因為每個非同步應用程式在應用程式的不同部分都有不同的排程需求。例如,當攝取大量資料時,Reactor 會希望使用基於久負盛名的 Disruptor RingBuffer 的高速非阻塞 Dispatcher。但如果 Reactor 正在向資料庫伺服器發出阻塞呼叫或將資料塊儲存在 S3 中,它會希望利用吞吐量較低的工作池 Dispatcher。Reactor 提供了多種選項,因此您可以為工作選擇合適的工具。
如果內建的 Dispatcher 實現不符合您的需求,那麼 Reactor 提供了一個堅實的基礎,您可以在其上構建適合您問題領域的自己的 Dispatcher。
Grails 是一個用於 JVM 的全棧 Web 應用程式框架。憑藉其成熟的程式碼庫和蓬勃發展的社群,Grails 仍然面臨著新的架構挑戰。事件透過platform-core 外掛引入 Grails。但事件功能如此強大,以至於這個功能確實應該屬於核心;因此,從 2.3 版本開始,Grails 應用程式將擁有一個內建的、極其強大且易於使用的、基於約定的事件 API,它與 platform-core 外掛中的當前實現非常相似。這個事件 API 將建立在 Reactor 的基礎上。
將事件整合到 Grails 中的目標是針對新型開發——尤其是“即時 Web”和大規模、非阻塞應用程式開發。結合非同步 GORM 功能,事件 API 將成為強大的盟友。訪問大資料儲存的複雜查詢——因此處理時間很長——可以在結果準備就緒時透過將其直接推送到瀏覽器來做出響應。
我們將在未來幾個月內努力為SpringOne做準備,屆時我們的許多大型、快速和可擴充套件的資料解決方案將大放異彩。如果您還沒有計劃參加,您絕對應該去!我們將有一個關於 Reactor 的會議,以及如何使用它來建立大規模、高吞吐量的事件驅動應用程式。
但我們離不開您的幫助!這項努力只有在您幫助我們為 JVM 上的大型、快速、事件驅動的應用程式開發建立一個充滿激情和活躍的社群時才能成功。如果您有興趣,請檢視 GitHub 上的原始碼,檢視 reactor-quickstart 中的一些示例程式碼,報告您發現的任何問題,在 StackOverflow 上使用標籤 #reactor 提問關於 Reactor 的問題,加入 reactor-framework Google Groups 郵件列表的討論,或者fork 倉庫以幫助新增功能、調整以獲得更高的吞吐量並貢獻新的想法。
我們很樂意在那裡見到您!