Vertx-Sync 手冊

源文檔
[很有趣的一個庫,一并翻譯了。]

本文依照 知識共享許可協(xié)議(署名-非商業(yè)性使用-禁止演繹) 發(fā)布。


Vertx-sync 是一組工具集,其特點是在不阻塞內(nèi)核線程的同時,允許用戶以同步的方式接收事件、執(zhí)行異步操作。

簡介

比起很多歷史遺留的程序庫,Vert.x的一個關鍵優(yōu)點是完全非阻塞(于內(nèi)核線程而言)--這使它用少量的內(nèi)核線程就可以處理大量的并發(fā)(例如,很多的連接、消息之類),具有良好的可擴展性。

Vert.x非阻塞性的結果是異步的API 。異步API 可以有多種風格,包括像回調(diào)、promise、Rx(Java的風格)。Vert.x在絕大多數(shù)地方使用回調(diào)(盡管它也支持Rx)。

某些情況下,使用異步API 編程比起直接使用同步API 要更具挑戰(zhàn),特別是當你有好幾個操作要按順序完成時。同時,使用異步API 時,錯誤的傳遞也會變得更復雜。

Vertx-sync 可以讓你在熟悉的同步風格下繼續(xù)使用異步API 。

在此,通往自由之路的功臣乃fiber(這個詞國內(nèi)有譯作纖程,類似協(xié)程-coroutine)。Fiber 是超輕量級的線程,并不是對應于底層的那種內(nèi)核線程,它們被阻塞時不會導致內(nèi)核線程也被阻塞。

Vert.x 借助Quasar 庫來實現(xiàn)fiber 。

注意:Vertx-sync 當前只適用于Java 。


SyncVerticle

要使用Vertx-sync 庫,你的代碼需要繼承io.vertx.ext.sync.SyncVerticle類,并重載start()方法和stop()方法(stop 非必需)。

這些方法還必須加上@Suspendable的標注。

寫好的sync verticle,其部署方法和其他verticle完全一樣。


Instrumentation

Vert.x用到了Quasar 庫,這個庫借助字節(jié)碼增強(bytecode instrumentation)的技術實現(xiàn)了fiber 。(字節(jié)碼增強的)工作是在運行時(run-time)由java agent 完成的。

要使這個特性正常工作,需要在啟動JVM 時指定quasar-core jar包為java agent jar包:
-javaagent:/path/to/quasar/core/quasar-core.jar

如果你用的是vertx命令行工具,可以在執(zhí)行vertx前設置環(huán)境變量ENABLE_VERTX_SYNC_AGENTture,這樣可以啟用agent 的配置。

你也可以使用quasar-maven-plugin 達成離線增強(a offline instrumentation, 指非運行時織入字節(jié)碼)的效果。更多細節(jié)請參考 Quasar documentation 。


獲得一次性的異步操作結果

Vert.x 的領域里,很多操作都會接受一個Handler<AsyncResult<T>>作為最后的參數(shù)。例如用Vert.x 的 Mongo 客戶端執(zhí)行一次查詢或者發(fā)送一個event bus 消息然后拿到回應。

Vertx-sync 可以讓你用同步的方式拿到這種一次性的異步操作的結果。

這是通過調(diào)用Sync.awaitResult 方法達成的。

運行這個方法時,需將想要執(zhí)行的異步操作以Consumer的形式指定為其參數(shù);handler 參數(shù)會在運行時傳給此consumer 。

看下面的例子:

EventBus eb = vertx.eventBus();

// Send a message and get the reply synchronously

Message<String> reply = awaitResult(h -> eb.send("someaddress", "ping", h));

System.out.println("Received reply " + reply.body());

上面的例子中,在回應返回前,fiber 會一直被阻塞??;而內(nèi)核線程不會。


獲得一次性的事件

Vertx-sync 也能以同步的方式獲得一次性的事件,例如定時器的觸發(fā),或者end handler(關于end handler 的例子可以參見Vert.x 核心包文檔中 HTTP 服務器與客戶端 一節(jié)) 的執(zhí)行。這是通過Sync.awaitEvent 方法達成的。

看下面的例子:

long tid = awaitEvent(h -> vertx.setTimer(1000, h));

System.out.println("Timer has now fired");

事件流

很多時候,Vert.x 的handler 接收到的是事件流,例如event bus 消息的消費者(consumer)、HTTP 服務器里的HTTP 服務端請求(server request)。

Vertx-sync 使你能以同步的方式從這種流中接收事件。

你需要一個同時實現(xiàn)了Handler Receiver接口的HandlerReceiverAdaptor 類實例。Sync.streamAdaptor 方法可以創(chuàng)建這樣一個實例。

你可以把它當成一個普通的handler ,然后可以用實現(xiàn)自Receiver 接口的方法來同步地接收事件。

下面是一個 event bus 消息消費者的例子:

EventBus eb = vertx.eventBus();

HandlerReceiverAdaptor<Message<String>> adaptor = streamAdaptor();

eb.<String>consumer("some-address").handler(adaptor);

// Receive 10 messages from the consumer:
for (int i = 0; i < 10; i++) {

  Message<String> received1 = adaptor.receive();

  System.out.println("got message: " + received1.body());

}

使用FiberHandler

如果你想在一般的handler 中使用fiber --例如Http 服務器的請求handler ,那得首先把這個一般的handler 轉換為fiber handler 。

Fiber handler 會在fiber 里運行那個一般的handler 。

看例子:

EventBus eb = vertx.eventBus();

vertx.createHttpServer().requestHandler(fiberHandler(req -> {

  // Send a message to address and wait for a reply
  Message<String> reply = awaitResult(h -> eb.send("some-address", "blah", h));

  System.out.println("Got reply: " + reply.body());

  // Now end the response
  req.response().end("blah");

})).listen(8080, "localhost");

更多示例

examples repository 這里有一打示例,展示了vertx-sync 的用法(官方示例簡單明了,不妨一覽)。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容