閱讀420 返回首頁    go 汽車大全


《Netty 實戰》Netty In Action中文版 第2章——你的第一款Netty應用程序(三)

2.5 構建和運行Echo服務器和客戶端

在這一節中,我們將介紹編譯和運行Echo服務器和客戶端所需的所有步驟。

Echo客戶端/服務器的Maven工程

 

這本書的附錄使用Echo客戶端/服務器工程的配置,詳細地解釋了多模塊Maven工程是如何組織的。這部分內容對於構建和運行該應用程序來說並不是必讀的,之所以推薦閱讀這部分內容,是因為它能幫助你更好地理解本書的示例以及Netty項目本身。

2.5.1 運行構建

要構建Echo客戶端和服務器,請進入到代碼示例根目錄下的chapter2目錄執行以下命令:

mvn clean package

這將產生非常類似於代碼清單2-5所示的輸出(我們已經編輯忽略了幾個構建過程中的非必要步驟)。

代碼清單2-5 構建Echo客戶端和服務器

[INFO] Scanning for projects...
[INFO] -------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] Chapter 2. Your First Netty Application - Echo App
[INFO] Chapter 2. Echo Client
[INFO] Chapter 2. Echo Server
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Chapter 2. Your First Netty Application - 2.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.6.1:clean (default-clean) @ chapter2 ---
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Chapter 2. Echo Client 2.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.6.1:clean (default-clean)
    @ echo-client ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources)
    @ echo-client ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile)
    @ echo-client ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to
    \netty-in-action\chapter2\Client\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources)
    @ echo-client ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory
    \netty-in-action\chapter2\Client\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile)
    @ echo-client ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test)
    @ echo-client ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ echo-client ---
[INFO] Building jar:
    \netty-in-action\chapter2\Client\target\echo-client-2.0-SNAPSHOT.jar
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Chapter 2. Echo Server 2.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.6.1:clean (default-clean)
    @ echo-server ---
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources)
    @ echo-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.3:compile (default-compile)
    @ echo-server ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 2 source files to
    \netty-in-action\chapter2\Server\target\classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources)
    @ echo-server ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory
    \netty-in-action\chapter2\Server\src\test\resources
[INFO]
[INFO] --- maven-compiler-plugin:3.3:testCompile (default-testCompile)
    @ echo-server ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.18.1:test (default-test)
    @ echo-server ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ echo-server ---
[INFO] Building jar:
    \netty-in-action\chapter2\Server\target\echo-server-2.0-SNAPSHOT.jar
[INFO] -------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] Chapter 2. Your First Netty Application ... SUCCESS [ 0.134 s]
[INFO] Chapter 2. Echo Client .................... SUCCESS [ 1.509 s]
[INFO] Chapter 2. Echo Ser........................ SUCCESS [ 0.139 s]
[INFO] -------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------------
[INFO] Total time: 1.886 s
[INFO] Finished at: 2015-11-18T17:14:10-05:00
[INFO] Final Memory: 18M/216M
[INFO] -------------------------------------------------------------------

下麵是前麵的構建日誌中記錄的主要步驟:

  • Maven確定了構建順序:首先是父pom.xml,然後是各個模塊(子工程);
  • 如果在用戶的本地存儲庫中沒有找到Netty構件,Maven將從公共的Maven存儲庫中下載它們(此處未顯示);
  • 運行了構建生命周期中的cleancompile階段;
  • 最後執行了maven-jar-plugin

Maven Reactor的摘要顯示所有的項目都已經被成功地構建。兩個子工程的目標目錄的文件列表現在應該類似於代碼清單2-6。

代碼清單2-6 構建的構件列表

Directory of nia\chapter2\Client\target
03/16/2015  09:45 PM    <DIR>          classes
03/16/2015  09:45 PM             5,614 echo-client-1.0-SNAPSHOT.jar
03/16/2015  09:45 PM    <DIR>          generated-sources
03/16/2015  09:45 PM    <DIR>          maven-archiver
03/16/2015  09:45 PM    <DIR>          maven-status

Directory of nia\chapter2\Server/target
03/16/2015  09:45 PM    <DIR>          classes
03/16/2015  09:45 PM             5,629 echo-server-1.0-SNAPSHOT.jar
03/16/2015  09:45 PM    <DIR>          generated-sources
03/16/2015  09:45 PM    <DIR>          maven-archiver
03/16/2015  09:45 PM    <DIR>          maven-status

2.5.2 運行Echo服務器和客戶端

要運行這些應用程序組件,可以直接使用Java命令。但是在POM文件中,已經為你配置好了exec-maven-plugin來做這個(參見附錄以獲取詳細信息)。

並排打開兩個控製台窗口,一個進到chapter2\Server目錄中,另外一個進到chapter2\Client目錄中。

在服務器的控製台中執行這個命令:

mvn exec:java

應該會看到類似於下麵的內容:

[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------------------------------------------------------
[INFO] Building Echo Server 1.0-SNAPSHOT
[INFO] ----------------------------------------------------------------------
[INFO]
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) >
    validate @ echo-server >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) <
    validate @ echo-server <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ echo-server ---
    nia.chapter2.echoserver.EchoServer
    started and listening for connections on /0:0:0:0:0:0:0:0:9999

服務器現在已經啟動並準備好接受連接。現在在客戶端的控製台中執行同樣的命令:

mvn exec:java

應該會看到下麵的內容:

[INFO] Scanning for projects...
[INFO]
[INFO] -------------------------------------------------------------------
[INFO] Building Echo Client 1.0-SNAPSHOT
[INFO] -------------------------------------------------------------------
[INFO]
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) >
    validate @ echo-client >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) <
    validate @ echo-client <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ echo-client ---
    Client received: Netty rocks!
[INFO] -------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------------
[INFO] Total time: 2.833 s
[INFO] Finished at: 2015-03-16T22:03:54-04:00
[INFO] Final Memory: 10M/309M
[INFO] -------------------------------------------------------------------

同時在服務器的控製台中,應該會看到這個:

Server received: Netty rocks!

每次運行客戶端時,在服務器的控製台中你都能看到這條日誌語句。

下麵是發生的事:

(1)一旦客戶端建立連接,它就發送它的消息——Netty rocks!

(2)服務器報告接收到的消息,並將其回送給客戶端;

(3)客戶端報告返回的消息並退出。

你所看到的都是預期的行為,現在讓我們看看故障是如何被處理的。服務器應該還在運行,所以在服務器的控製台中按下Ctrl+C來停止該進程。一旦它停止,就再次使用下麵的命令啟動客戶端:

mvn exec:java

代碼清單2-7展示了你應該會從客戶端的控製台中看到的當它不能連接到服務器時的輸出。

代碼清單2-7 Echo客戶端的異常處理

[INFO] Scanning for projects...
[INFO]
[INFO] --------------------------------------------------------------------
[INFO] Building Echo Client 1.0-SNAPSHOT
[INFO] --------------------------------------------------------------------
[INFO]
[INFO] >>> exec-maven-plugin:1.2.1:java (default-cli) >
    validate @ echo-client >>>
[INFO]
[INFO] <<< exec-maven-plugin:1.2.1:java (default-cli) <
    validate @ echo-client <<<
[INFO]
[INFO] --- exec-maven-plugin:1.2.1:java (default-cli) @ echo-client ---
[WARNING]
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    . . .
    Caused by: java.net.ConnectException: Connection refused:
    no further information: localhost/127.0.0.1:9999
        at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
        at sun.nio.ch.SocketChannelImpl
        .finishConnect(SocketChannelImpl.java:739)
        at io.netty.channel.socket.nio.NioSocketChannel
        .doFinishConnect(NioSocketChannel.java:208)
        at io.netty.channel.nio
        .AbstractNioChannel$AbstractNioUnsafe
        .finishConnect(AbstractNioChannel.java:281)
        at io.netty.channel.nio.NioEventLoop
        .processSelectedKey(NioEventLoop.java:528)
        at io.netty.channel.nio.NioEventLoop.
        processSelectedKeysOptimized(NioEventLoop.java:468)
        at io.netty.channel.nio.NioEventLoop
        .processSelectedKeys(NioEventLoop.java:382)
        at io.netty.channel.nio.NioEventLoop
        .run(NioEventLoop.java:354)
        at io.netty.util.concurrent.SingleThreadEventExecutor$2
        .run(SingleThreadEventExecutor.java:116)
        at io.netty.util.concurrent.DefaultThreadFactory
        $DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
    . . .
[INFO] --------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] --------------------------------------------------------------------
[INFO] Total time: 3.801 s
[INFO] Finished at: 2015-03-16T22:11:16-04:00
[INFO] Final Memory: 10M/309M
[INFO] --------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:
    exec-maven-plugin:1.2.1:java (default-cli) on project echo-client:
        An exception occured while executing the Java class. null:
        InvocationTargetException: Connection refused:
        no further information: localhost/127.0.0.1:9999 -> [Help 1]

發生了什麼?客戶端試圖連接服務器,其預期運行在localhost:9999上。但是連接失敗了(和預期的一樣),因為服務器在這之前就已經停止了,所以在客戶端導致了一個java.net.ConnectException。這個異常觸發了EchoClientHandlerexceptionCaught()方法,打印出了棧跟蹤並關閉了Channel(見代碼清單2-3)。

2.6 小結

在本章中,你設置好了開發環境,並且構建和運行了你的第一款Netty客戶端和服務器。雖然這隻是一個簡單的應用程序,但是它可以伸縮到支持數千個並發連接——每秒可以比普通的基於套接字的Java應用程序處理多得多的消息。

在接下來的幾章中,你將看到更多關於Netty如何簡化可伸縮性和並發性的例子。我們也將更加深入地了解Netty對於關注點分離的架構原則的支持。通過提供正確的抽象來解耦業務邏輯和網絡編程邏輯,Netty使得可以很容易地跟上快速演化的需求,而又不危及係統的穩定性。

在下一章中,我們將提供對Netty體係架構的概述。這將為你在後續的章節中對Netty的內部進行深入而全麵的學習提供上下文。


[1] Netty的一組受限特性可以運行於JDK 1.6,但是JDK 8或者更高版本則是編譯時必需的,包括運行最新版本的Maven。

[2] 包括Intellij IDEA。——譯者注

[3] 也可以通過HomeBrew或者Scoop來安裝Maven,更加簡單方便。——譯者注

[4] 這裏對於所有的客戶端連接來說,都會使用同一個EchoServerHandler,因為其被標注為@Sharable,這將在後麵的章節中講到。——譯者注

[5] SimpleChannelInboundHandlerchannelRead0()方法的相關討論參見https://github.com/netty/netty/ wiki/New-and-noteworthy-in-5.0#channelread0–messagereceived,其中Netty5的開發工作已經關閉。——譯者注

轉載自 並發編程網 - ifeve.com

最後更新:2017-05-18 20:36:22

  上一篇:go  Clojure世界:如何做性能測試
  下一篇:go  Clojure世界:API文檔生成