如果你對Node.js感興趣,Vert.x可能是你的下一個大事件:一個建立在JVM上一個類似的架構企業制度。 這一部分介紹Vert.x是通過兩個動手的例子(基於Vert.x 2.0)。 當Node.js出現,許多開發者興奮的感到可以用不尋常的方法來構建可擴展的伺服器端應用程式。 而不是開始,將服務使 ...
如果你對Node.js感興趣,Vert.x可能是你的下一個大事件:一個建立在JVM上一個類似的架構企業制度。 這一部分介紹Vert.x是通過兩個動手的例子(基於Vert.x 2.0)。
當Node.js出現,許多開發者興奮的感到可以用不尋常的方法來構建可擴展的伺服器端應用程式。 而不是開始,將服務使用多線程的請求重量級的容器。Node.js是啟動多個輕便單線程的伺服器和流量路由到他們。
現在,類似的框架已經出現,它的伺服器部署在一個JVM中,使用JVM設施來管理流量輕量級伺服器進程。 本批中的開源Java項目 ,您將瞭解Vert.x,事件驅動的架構類似的Node.js,是建立在JVM系列還擴展它在某些重要的新途徑。
Vert.x亮點
Vert.x應用程式是事件驅動,非同步和單線程的。 Vert.x過程通過事件匯流排,這是Vert.x的事件驅動架構的內置一塊通信。 結合非同步處理,單線程組件和事件匯流排產生高度的可擴展性,並編寫單線程應用對習慣於多線程併發Java的人來說是一種解脫。 可以說,Vert.x的最好的部分是其模塊化的基於JVM的架構。 Vert.x應用程式可以運行在幾乎所有的操作系統,並且可以使用任何支持的JVM相容的編程語言來編寫。 一個Vert.x應用可完全在單一語言編寫,也可以是用不同的編程語言模塊的跨界混搭。 Vert.x模塊集成了Vert.x事件匯流排上。
在Vert.x基於事件的編程
Vert.x的基於事件的編程模型的標準和獨特的功能組合。 Vert.x應用在很大程度上是通過定義事件處理程式。 不同於傳統的基於事件的應用程式,但是,Vert.x應用保證不被阻塞。 而不是打開一個socket到伺服器,請求資源,然後等待(阻塞)的響應,Vert.x發送到應用程式非同步地響應,通過事件處理程式,並通過事件匯流排傳遞消息寫入。
Vert.x的編程框架包括一些白話,這將有助於更好的瞭解,通過兩個演示應用程式在本文的後面:
-
一個verticle是部署在Vert.x.單位 每個verticle包含啟動它的主要手段。 一個應用程式可以是單個verticle或者可以由與彼此經由事件匯流排通信的多個verticles的。
-
Verticles在Vert.x實例中運行。 每個Vert.x實例在其自己的JVM實例運行,並且可以承載多個verticles。 一個Vert.x實例確保verticles彼此通過運行每個在其自己的類載入器分離,所以沒有修改一個靜態變數是另一個實例的風險。 主機可以運行一個單一的Vert.x實例或多個的。
-
一個Vert.x實例,保證每個verticle實例總是在同一個線程執行。 併發Vert.x 是單線程的。
-
在內部,Vert.x實例維護一組線程(通常為CPU核心數)是在執行一個事件迴圈 :檢查,看看是否有工作要做,做到這一點,去睡覺。
-
Verticles通過使用事件匯流排傳遞消息通信。
-
雖然你可能會認為,共用數據和可擴展性截然相反。 Vert.x提供了一個共用的MAP和跨在同一Vert.x實例中運行verticles傳遞不可改變的數據共用一套設施,這時候數據是可變的唯一真正的 。
-
Vert.x使用相對較少的線程來創建一個事件迴圈和執行verticles。 但在某些情況下,需要verticle做一些要麼昂貴計算,或可能阻塞,如連接到資料庫。 當發生這種情況Vert.x可以讓你標記verticle實例作為worker verticle 。Vert.x確保worker verticles將永遠不會被同時執行,所以要他們保持在最低水平,但他們在那裡幫助你,當你需要他們,在這種情況下,將由後臺執行的線程池執行。
圖1示出Vert.x系統包括Vert.x實例,verticles,JVM中,伺服器主機,以及事件匯流排的體繫結構。
圖1. Vert.x系統的體繫結構
Vert.x核心服務和模塊
Vert.x功能可以分為兩類:核心服務和模塊核心服務是可從verticle直接調用並包括用於TCP / SSL,HTTP和網路套接字的客戶端和伺服器上的服務。 服務來訪問Vert.x事件匯流排; 定時器,緩衝區,流量控制,文件系統訪問,共用maps 和 sets,訪問配置,SockJS伺服器,以及部署和取消部署verticles。 核心服務是相當靜態的,預計不會改變,因此所有其他的功能由模塊提供。
Vert.x應用和資源可以很容易地打包成模塊,並通過Vert.x共用的公共模塊庫 。 與模塊的交互是通過Vert.x事件匯流排非同步:用JSON發送模塊的消息,你的申請將得到答覆。 模塊和集成通過服務匯流排之間的這種脫鉤意味著模塊可以在任何支持的語言編寫和其它任何支持的語言使用。 所以,如果有人寫在Ruby中,你想在你的Java應用程式使用這個模塊,是完全可以的!
編寫一個基於Java的Vert.x Web伺服器
一個基本的Web伺服器應用程式和消息傳遞系統。 首先下載vert.x 寫這篇文章的是2.0.0.final。 當地解開並添加它的bin文件夾到你的PATH 。 請註意,您需要安裝Java 7,如果你還沒有。
如果你是一個Maven的人跟我一樣,那麼你可以簡單以下的依賴添加到您的POM文件:
清單1. Maven的POM對Vert.x
<dependency>
<groupId> io.vertx </groupId>
<artifactId> vertx-core </artifactId>
<version> 2.0.0-final </version>
</dependency>
<dependency>
<groupId> io.vertx </groupId>
<artifactId> vertx-platform </artifactId>
<version> 2.0.0-final </version>
</dependency>
清單2顯示了Server.java文件內容
清單2. Server.java
package com.geekcap.vertxexamples;
import org.vertx.java.core.Handler;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.deploy.Verticle;
public class Server extends Verticle {
public void start() {
vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest req) {
String file = req.path().equals("/") ? "index.html" : req.path();
req.response.sendFile("webroot/" + file);
}
}).listen(8080);
}
}
前幾行清單2導入所需的Vert.x類:
-
Handler是所有處理器的基類!
-
HttpServerRequest代表Vert.x.伺服器端的HTTP請求 這個類的一個實例將為由伺服器處理的每個請求創建,然後傳遞到通過您的應用程式Handler實例(你會使用已註冊HttpServer )。
-
Verticle是在Vert.x應用程式部署的基本單位。 為了使用Vert.x,你需要擴展Verticle類和重寫start()方法,這你的Verticle 入口點。
註意vertx清單2中的變數: 該Verticle類定義vertx作為受保護的成員變數(繼承Verticle),它提供了訪問Vert.x運行。 該vertx變數的類型的Vertx,這暴露了以下方法:
-
createHttpClient()創建一個HTTP / HTTPS客戶端
-
createHttpServer()創建一個HTTP / HTTPS伺服器
-
createNetClient()創建了一個TCP / SSL客戶端
-
createNetServer()創建了一個TCP / SSL伺服器
-
creatSockJSServer()創建一個包裝了HTTP伺服器SockJS伺服器
-
eventBus()提供事件匯流排您的應用程式訪問
-
fileSystem()提供對文件系統的應用程式訪問
-
sharedData()提供應用程式訪問共用數據對象,它可以被用來共用Verticles之間的數據
清單2中的代碼創建一個新的HTTP伺服器,檢索其請求處理程式的參考,並將請求處理程式到新創建的HttpServerRequest處理程式。 該Handle介面定義了一個方法命名handler()並使用泛型定義實例傳遞給它的類定義的類型; 在這種情況下HttpServerRequest 。 該HttpServerRequest然後定義以下欄位:
-
method 是一個String包含給定請求的方法中,如GET , POST , PUT , DELETE ,等等。
-
path 是一個String包含所請求的路徑,如/index.html 。
-
query 是一個String包含查詢參數,如遵循以下問號部分: ?key=value 。
-
response 是一個基準HttpServerResponse表示對HTTP請求的響應。
-
uri 為請求的完整URI。
清單2完成對通過映射一個空的請求- “ / ” -到index.html ,然後調用HttpServerResponse的sendFile()方法來告訴Vert.x流指定的文件返回給調用者。
綜上所述, Server級訪問Vert.x運行時,要求它創建一個新的HTTP伺服器,並註冊一個Handler (即期望一個HttpServerRequest變數)的HttpServer 。 在處理器的handle()方法時, Server類從位於文件系統提供文件服務webroot目錄,這是相對的。
構建web伺服器
讓我們來構建示例應用程式,那麼我們將使用Vert.x執行它。 此項目的Maven的POM文件顯示清單3所示。
清單3. Maven的POM構建Web伺服器
<project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion> 4.0.0 </modelVersion>
<groupId> com.geekcap </groupId>
<artifactId> vertx-examples </artifactId>
<version> 1.0-SNAPSHOT </version>
<packaging> jar </packaging>
<name> vertx-examples </name>
<url> http://maven.apache.org </url>
<properties>
<project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId> org.apache.maven.plugins </groupId>
<artifactId> maven-compiler-plugin </artifactId>
<version> 2.0.2 </version>
<configuration>
<source> 1.6 </source>
<target> 1.6 </target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId> io.vertx </groupId>
<artifactId> vertx-core </artifactId>
<version> 2.0.0-final </version>
</dependency>
<dependency>
<groupId> io.vertx </groupId>
<artifactId> vertx-platform </artifactId>
<version> 2.0.0-final </version>
</dependency>
<dependency>
<groupId> junit </groupId>
<artifactId> junit </artifactId>
<version> 4.11 </version>
<scope> test </scope>
</dependency>
</dependencies>
</project>
兩個依賴添加到POM文件是vertx-code和vertx-platform的,這是需要開發的Java應用程式Vert.x。要構建這個應用程式,請執行以下Maven命令:
mvn clean install
這將產生一個名為vertx-examples-1.0-SNAPSHOT.jar,將需要在你的CLASSPATH,以啟動您的verticle。這個示例應用程式提供了在發現網路資源Web根目錄相對於該應用程式的啟動目錄。因此,你需要創建一個webroot的目錄,並建立一些資源從它服務。要啟動這個verticle,執行vertx在Vert.x的應用bin目錄,如下所示:
$VERTX_HOME/bin/vertx run com.geekcap.vertxexamples.Server -cp vertx-exampl
該vertx命令接受幾個選項,包括我們使用它的人,運行。這是一個擴展類的只是名字Verticle和包含的start()方法和一個可選的參數集。在這種情況下,我們設置CLASSPATH使用-cp參數,並傳入JAR,我們剛剛創建的文件。伺服器將啟動,但不輸出任何內容到屏幕上,但你可以將瀏覽器指向的網址:HTTP://localhost:8080。
對於我的例子中,我創建了一個簡單的HTML文件,該文件說:“Hello, Vert.x”,將其命名為index.html的,並把它放在我的根目錄的目錄。這裡是我的輸出:
$ curl http://localhost:8080
<html><html>
<head><title>Hello, Vert.x</title></head><head><title>Hello, Vert.x</title></head>
<body><body>
<p>Hello, Vert.x</p><p>Hello, Vert.x</p>
</body></body>
</html></html>
與Vert.x通信
Vert.x的最重要的特點之一是它的事件匯流排。所述Vert.x事件匯流排允許verticles,可能用不同的編程語言,在使用任意點對點通信彼此通信或發佈/訂閱消息。在本節中,你會得到怎樣的功能使用這兩種方法的不同verticles整合的感覺。
在我們開始之前,你為什麼要使用消息在一個更傳統的基於事件的編程模型?一方面,消息支持的用不同的編程語言應用程式和組件的集成。這也使鬆散耦合,這意味著您可以編寫代碼的多個任務為中心的作品,而不是單一的,複雜的程式。最後,verticles之間的非同步通信提高了系統的可擴展性。非同步通信允許您定義系統的容量,因為它的發展。消息可能備份您的系統負荷增加,但他們最終會被處理。Vert.x對分散式事件匯流排的支持也給了你啟動額外verticles以處理增加的負載的選項。
為了建立一個Vert.x消息系統,則需要獲得該事件匯流排。通過執行啟動eventBus()上的方法vertx類的實例:
EventBus eb = vertx.eventBus();
一旦你連接到EventBus您可以通過以下兩種方式之一發佈消息:
-
publish()發佈一個消息給使用地址發佈/訂閱消息,這意味著每subscriber到給定的地址將接收發佈的消息。地址只是一個String,所以你要選擇有意義的事,但在什麼時候是這兩個出版商和用戶配置為使用相同的字元串。如果你熟悉Java消息系統(JMS),publish()起同樣地作用,發佈消息到一個topic。
-
send()發送消息到使用地址點對點的消息,這意味著只有一個訂戶將接收該消息。如果有多個用戶的地址,然後Vert.x將使用迴圈演算法發送消息。使用迴圈演算法的優點是可擴展性:如果你沒有足夠的資源在一個Vert.x實例來支持你的負擔,那麼你可以簡單地啟動其他Vert.x實例,並登記他們作為聽眾指定的地址。
發佈/訂閱VS點對點通信
在發佈/訂閱消息模型中,發佈者將消息發送到被廣播到所有用戶的一個話題。使用發佈/事件驅動的架構訂閱了點至點的消息意味著組件只對所發生事件的發佈負責。發佈商並不需要知道它的訂閱者,以便廣播到它們。圖2是一個典型的Vert.x的流程圖發佈/訂閱消息架構。
圖2.發佈/訂閱消息
在點 - 點通信,將消息從發佈者直接通過一個隊列發送給消費者。點對點的消息是一個很好的選擇,當你想消息消耗正好一次時,或者當兩個組件要非同步地相互通信。點 - 點消息架構顯示在圖3。
圖3.點對點通信
我們將使用Vert.x在下麵的章節探討兩個郵件系統。
發佈/訂閱消息的例子
清單4更新我原來的伺服器類(清單1)在幾個方面。首先,它部署了一個所謂的新verticle AuditVerticle通過調用(如清單5中定義)deployVerticle()的方法容器實例,其被定義為母體的一部分Verticle類,提供了通向容器verticle中運行;因此,它是部署新verticles適當的位置。
清單4. Server.java 點至點消息
package com.geekcap.vertxexamples;
import org.vertx.java.core.Handler;import org.vertx.java.core.Handler;
import org.vertx.java.core.eventbus.EventBus;import org.vertx.java.core.eventbus.EventBus;
import org.vertx.java.core.http.HttpServerRequest;import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.logging.Logger;import org.vertx.java.core.logging.Logger;
import org.vertx.java.platform.Verticle;import org.vertx.java.platform.Verticle;
public class Server extends Verticle {public class Server extends Verticle {
public void start() {public void start() {
// Create our dependent verticles// Create our dependent verticles
container.deployVerticle("com.geekcap.vertxexamples.AuditVerticle");.deployVerticle("com.geekcap.vertxexamples.AuditVerticle");
// Create an HTTP Server that serves files// Create an HTTP Server that serves files
vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest req) {public void handle(HttpServerRequest req) {
Logger logger = container.logger();Logger logger = container.logger();
if (logger.isDebugEnabled()) {if (logger.isDebugEnabled()) {
logger.debug("Received a request for resource: " + req.path());.debug("Received a request for resource: " + req.path());
}}
logger.fatal("Where are my logs!?!?");.fatal("Where are my logs!?!?");
logger.info("Here is an info message");.info("Here is an info message");
// Serve up our files// Serve up our files
String file = req.path().equals("/") ? "index.html" : req.path();String file = req.path().equals("/") ? "index.html" : req.path();
req.response().sendFile("webroot/" + file);.response().sendFile("webroot/" + file);
// Let's tell the world (via the event bus) that we received a request// Let's tell the world (via the event bus) that we received a request
EventBus eb = vertx.eventBus();EventBus eb = vertx.eventBus();
eb.publish( "com.geekcap.vertxexamples.Server.announcements", "We received a request for resource: " + req.path() );.publish( "com.geekcap.vertxexamples.Server.announcements", "We received a request for resource: " + req.path() );
}}
}).listen(8080);}).listen(8080);
}}
}}
清單4執行deployVerticle()來部署AuditVerticle。所述deployVerticle()方法部署一個標準Verticle到容器上,它保持它自己的事件迴圈。處理傳入的HTTP請求(如清單1所示)之後,清單4將消息發佈到事件匯流排。第一,它獲得通過接入到事件匯流排vertx實例變數的話,就執行eventBus()方法。一旦有EventBus對象將調用其發佈方法,這是一個發佈/訂閱的時尚門戶發佈的消息。
消息松耦合
在過去的三年裡,我以事件驅動的架構工作過,而且我發現,發佈/訂閱消息,有時也被稱為topic,是一個偉大的方式,以鬆散耦合的系統。信息發佈者不需要知道他們的用戶,所以新用戶可以在任何時候加入不影響發行人。
清單5顯示了源代碼AuditVerticle類。
清單5. AuditVerticle.java
package com.geekcap.vertxexamples; com.geekcap.vertxexamples;
import org.vertx.java.core.Handler;import org.vertx.java.core.Handler;
import org.vertx.java.core.eventbus.EventBus;import org.vertx.java.core.eventbus.EventBus;
import org.vertx.java.core.eventbus.Message;import org.vertx.java.core.eventbus.Message;
import org.vertx.java.core.logging.Logger;import org.vertx.java.core.logging.Logger;
import org.vertx.java.platform.Verticle;import org.vertx.java.platform.Verticle;
public class AuditVerticle extends Verticle {public class AuditVerticle extends Verticle {
@Override@Override
public void start() {public void start() {
// Let's register ourselves as a listener to Server notifications// Let's register ourselves as a listener to Server notifications
EventBus eb = vertx.eventBus();EventBus eb = vertx.eventBus();
Handler<Message> auditHandler = new Handler<Message>() {Handler<Message> auditHandler = new Handler<Message>() {
@Override@Override
public void handle(Message message) {public void handle(Message message) {
Logger logger = container.logger();Logger logger = container.logger();
logger.info( "AuditVerticle here, someone requested resource: " + message.body() );.info( "AuditVerticle here, someone requested resource: " + message.body() );
}}
};};
eb.registerHandler( "com.geekcap.vertxexamples.Server.announcements", auditHandler );.registerHandler( "com.geekcap.vertxexamples.Server.announcements", auditHandler );
}}
}}
該AuditVerticle清單5的行為很像一個報告引擎:它監聽來自“announcements” server類,然後寫出來的那些作為信息的日誌信息。如果感興趣的東西在發生伺服器類,它可以將它發佈到其announcements的topic,不同的用戶可以做不同的事情,比如記錄的消息或在Hadoop集群中供以後分析插入。
清單5然後創建一個處理程式線上實例(創建一個匿名內部類,並分配給一個變數,而無需創建一個單獨的文件中的類)記錄消息。接著,註冊一個處理程式的“com.geekcap.vertxexamples.Server.announcements通過調用”地址EventBus的registerHandler()方法。現在,在任何時候伺服器類將消息發佈到該目的地,AuditHandler的handle()方法將被調用。
點 - 點通信實例
當要僅由單個消費者或作為機構組件相互非同步通信進行處理的消息的點至點的消息時使用,也可以。在這一節中,我通過創建依賴於一個worker verticle做的工作是一個新的類演示了後者,然後該worker verticle通信的結果返回給伺服器2。
清單6顯示了源代碼Server2類。
清單6. Server2.java
package com.geekcap.vertxexamples; com.geekcap.vertxexamples;
import org.vertx.java.core.Handler;import org.vertx.java.core.Handler;
import org.vertx.java.core.eventbus.EventBus;import org.vertx.java.core.eventbus.EventBus;
import org.vertx.java.core.eventbus.Message;import org.vertx.java.core.eventbus.Message;
import org.vertx.java.core.http.HttpServerRequest;import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.logging.Logger;import org.vertx.java.core.logging.Logger;
import org.vertx.java.deploy.Verticle;import org.vertx.java.deploy.Verticle;
import java.util.concurrent.ConcurrentMap;import java.util.concurrent.ConcurrentMap;
public class Server2 extends Verticle {public class Server2 extends Verticle {
public void start() {public void start() {
// Create our dependent verticles// Create our dependent verticles
container.deployWorkerVerticle("com.geekcap.vertxexamples.MyWorkerVerticle");.deployWorkerVerticle("com.geekcap.vertxexamples.MyWorkerVerticle");
// Start a server that handles things with point-to-point messaging// Start a server that handles things with point-to-point messaging
vertx.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {.createHttpServer().requestHandler(new Handler<HttpServerRequest>() {
@Override@Override
public void handle(final HttpServerRequest req) {public void handle(final HttpServerRequest req) {
// Set a shared variable// Set a shared variable
ConcurrentMap<String, String> map = vertx.sharedData().getMap("mymap");ConcurrentMap<String, String> map = vertx.sharedData().getMap("mymap");
map.put("mykey", "myvalue");.put("mykey", "myvalue");
// Let's send a message to a worker verticle and wait for it to respond// Let's send a message to a worker verticle and wait for it to respond
EventBus eb = vertx.eventBus();EventBus eb = vertx.eventBus();
eb.send("request.worker", req.path, new Handler<Message<String>>() {.send("request.worker", req.path, new Handler<Message<String>>() {
@Override@Override
public void handle(Message<String> message) {public void handle(Message<String> message) {
Logger logger = container.getLogger();Logger logger = container.getLogger();
logger.info( "Received a reply from our worker: " + message.body );.info( "Received a reply from our worker: " + message.body );
req.response.headers().put("Content-Length", Integer.toString(message.body.length()));.response.headers().put("Content-Length", Integer.toString(message.body.length()));
req.response.write(message.body);.response.write(message.body);
}}
});});
}}
}).listen(8080);}).listen(8080);
}}
}}
該Server2類通過部署一個工人verticle開始。worker verticles是 從在它們不包含事件外表和預期由事件匯流排消息來觸發標準verticles不同。worker verticles由獲得訪問Vert.x部署容器並調用其deployWorkerVerticle()方法。
接著,Server2獲得訪問EventBus通過調用,再次eventBus()的方法vertx實例變數。此時的Server2調用的send()方法,它是通往在點對點方式發送消息。在這種情況下,將請求發送路徑到一個命名為“request.worker ”。到的第一個參數的send()方法是目的地,第二個參數是數據發送到目的地,和一個可選的第三個參數是一個處理程式能夠由消息的接收者被回調。
該MyWorkerVerticle,這是清單7所示,旨在構建指定的請求路徑的響應和發送響應返回給Server2上的處理程式。該處理程式記錄的響應,然後寫入該響應返回給HttpServerRequest發起的動作。我們能夠寫回之前HttpServerRequest我們需要指定HTTP 內容長度的響應,這是我們返回的字元串只是長度。
另外兩個Vert.x的功能被添加到Server2類:
-
日誌記錄:該容器變數命名的方法getLogger()提供了訪問Vert.x的記錄。此記錄是非常相似的log4j的,並提供了方法,如debug() ,info() ,和fatal()記錄在不同的日誌記錄級別的消息。預設情況下,日誌信息將被回顯到標準輸出和將被寫入一個文件名 為vertx.log位於TMPDIR -defined目錄。
-
共用數據:verticles之間共用數據是通過執行sharedData()的方法來實現vertx實例,然後調用的共用數據訪問方法之一。在清單4中,我們存儲在數據MAP是通過調用檢索的GetMap() ; 你同樣可以找回共用數據的設置通過調用GETSET() 。所有在Vert.x實例verticles的訪問使用相同的模式相同的共用數據,所以它是為你verticles之間共用不可變數據的一種方式。
清單7顯示了源代碼MyWorkerVerticle類。
清單7. MyWorkerVerticle.java
package com.geekcap.vertxexamples;
import org.vertx.java.core.Handler;
import org.vertx.java.core.eventbus.EventBus;
import org.vertx.java.core.eventbus.Message;
import org.vertx.java.core.logging.Logger;
import org.vertx.java.platform.Verticle;
import java.util.concurrent.ConcurrentMap;
public class MyWorkerVerticle extends Verticle {
@Override
public void start() {
// Register a listener
EventBus eb = vertx.eventBus();
Handler<Message> workerHandler = new Handler<Message>() {
@Override
public void handle(Message message) {
Logger logger = container.logger();
logger.info( "MyWorkerVerticle just received a request for: " + message.body() );
// Examine our shared map
ConcurrentMap<String, String> map = vertx.sharedData().getMap("mymap");
logger.info( "Shared data: " + map.get( "mykey" ) );
message.reply( "<html><head><title>Worker Response</title></head><body>Hello, from the worker verticle</body></html>" );
}
};
eb.registerHandler( "request.worker", workerHandler );
}
}
該MyWorkerVerticle類創建一個新的處理程式與實例handle()從處理消息的方法Server2的類。從清單6中的傳遞給一個參數召回的send()方法是一個處理程式,可以通過郵件收件人調用實例。清單7調用message.reply() ,它發送一個響應返回給始發者(在該示例中是伺服器2的處理程式)。
該MyWorkerVerticle類獲得訪問EventBus,然後註冊其處理程式以偵聽發送到“request.worker”目標的消息,以完成迴圈。
至於功能性,MyWorkerVerticle簡單地構造一個HTML文檔,並返回它回到Server2類。可以通過連接到一個資料庫或讀取數據從另一個伺服器以檢索與該建立響應中的數據建立在這個例子。
而且你會發現,MyWorkerVerticle從檢索共用數據vertx的sharedData()map。
結論
隨著企業系統的複雜演變,融合已經成為了軟體開發人員的編程最大的挑戰之一。Vert.x解決一體化的幾種方法複雜:首先,它是圍繞一個事件匯流排,鬆散的耦合verticles同時支持多種編程語言構建的。不管代碼是用Java編寫的,ruby,python,或JavaScript,可以無縫通過Vert.x事件車內集成。此外,該事件匯流排本身支持非同步消息和事件驅動架構,它產生的高可擴展性和松耦合。
本文展示Vert.x,其獨特的語言,那它結合打造高度可擴展的企業級解決方案的核心組件的概述。我展示兩個web伺服器和寫入Vert.x一個消息傳送系統中,採用後者的例子來開發一種發佈/訂閱消息和點至點的消息的解決方案。在後者的例子中,我還證明事件記錄,共用數據,以及標準和worker verticles之間的差異。雖然這篇文章介紹中,我談到了一些,說明Vert.x,類似的Node.js,但它主要功能是建立在JVM的一個解決方案。我希望啟發你,更多地瞭解Vert.x,它解決了類型的編程挑戰。h