使用Vert.x構建Web伺服器和消息系統

来源:http://www.cnblogs.com/miaoqing/archive/2016/06/14/5584360.html
-Advertisement-
Play Games

如果你對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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.prototype和__proto__ 所有對象的__proto__都指向其構造器的prototype,即constructor的原型 2.變數作用域的問題 通常認為在當前作用域中找不到變數值時會到其父作用域中去尋找,這種說法是不准確的,應該是會到創建這個函數的作用域中去找 3.settimeo ...
  • JavaScript一直沒有模塊體系,但是伴隨著ES6的到來,module隨之而來。ES6module提倡一個js文件就是一個模塊的概念,主要包括兩個命令:export和import,用於模塊向外提供介面(export)和引入其他模塊介面(import)。該隨筆分為四部分:1、ES6module概述... ...
  • 下載地址:https://www.sublimetext.com/3 安裝Package Control Zend Coding 插件 參考文章 原文鏈接:http://www.cnsecer.com/460.html 官方文檔:http://docs.emmet.io/customization/ ...
  • 最近為了實現一個屬性下拉框被Ext框架折騰了好幾天。。 所以,首先要說的是,不管你要做什麼系統、強烈建議你不要選擇Ext。據我這幾天的搜索,應該這個框架現在用的人也很少了。 Ext框架的缺陷:框架沉重、擴展性差(與其他js框架相比)、各版本差別大(Ext3、4、5不相容)。 現在進入正題,這幾天研究 ...
  • Sequelize是一個基於promise的關係型資料庫ORM框架,這個庫完全採用JavaScript開發並且能夠用在Node.JS環境中,易於使用,支持多SQL方言(dialect),。它當前支持MySQL,、MariaDB、SQLite、PostgreSQL、Sql Server 資料庫。 目前 ...
  • 1.嵌入另一張HTML文檔 iframe 元素允許在現有的HTML文檔中嵌入另一張文檔。下麵代碼展示了iframe元素的用法: 在這個例子里,創建一個 name 屬性為 myframe 的 iframe 。這樣就創建了一個名為 myframe 的瀏覽上下文。然後就可以把這個瀏覽上下文與其他元素(具體 ...
  • nodejs npm常用命令 npm是一個node包管理和分發工具,已經成為了非官方的發佈node模塊(包)的標準。有了npm,可以很快的找到特定服務要使用的包,進行下載、安裝以及管理已經安裝的包。 1、npm install moduleNames:安裝Node模塊安裝完畢後會產生一個node_m ...
  • [1]定義 [2]生存期 [3]顯式創建 [4]轉型函數 [5]比較運算 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...