1. 程式人生 > 實用技巧 >vert.x入門

vert.x入門

>>> hot3.png

Vert.x是一個輕量級的高效能JVM應用平臺,基於它可開發各種移動,Web和企業應用程式。一個主要特點是可使用多種語言編寫應用,如Java, JavaScript, CoffeeScript, Ruby, Python 或 Groovy等等,它的簡單actor-like機制能幫助脫離直接基於多執行緒程式設計。它是基於Netty和Java 7的NIO2的編寫的。

  當前業界遭遇C10K問題,當併發連線超過10,000+以上時使用傳統技術會引發暫停,移動裝置或視訊聲音如類似微信這樣的實時聊天,都是屬於長任務連線Long-lived。

  通常Tomcat會在100個併發長請求(這個請求要求做很多事長任務)下堵塞,而Vertx將長任務委託給另外一個執行緒來執行,從而不會堵塞當前執行緒,與NodeJS的原理非常類似,如下圖:

10000244_y7J4.png

   事件迴圈的執行緒和長任務工作執行緒之間是通過事件匯流排EventBus通訊的,這個事件匯流排是一個JVM之中,如下圖:

10000244_KYj1.png

   圖中每個Verticle是一個執行緒,符合單寫原則,避免了寫爭奪。匯流排可以拓展到客戶端邊的Javascript,可以在客戶端和伺服器端分發事件,可以如下圖在多個客戶端或伺服器端:

10000244_seHR.png

   下圖是在一個Web應用中,多層之間也可以通過EventBus通訊實現呼叫:

10000244_D6Na.png

程式碼演示

   下面是一個伺服器的Java程式碼:

public class ServerExample extends Verticle { public void start() { vertx.createHttpServer().requestHandler( new Handler<HttpServerRequest>() {
public void handle(HttpServerRequest req) { System.out.println("Got request: " + req.uri()); req.response().headers().set("Content-Type", "text/html; charset=UTF-8"); req.response().end("<html><body><h1>Hello from vert.x!</h1></body></html>"); } }).listen(8080); } }

  groovy版本:

package http vertx.createHttpServer().requestHandler { req -> req.response.end"<html><body><h1>Hello from vert.x!</h1></body></html>" }.listen(8080, "localhost")

  Javascript版本:

var vertx = require('vertx') vertx.createHttpServer().requestHandler( function(req){ req.response.end("<html><body><h1>Hello from vert.x!</h1></body></html>"); }).listen(8080);

WebScoket實現

  WebSocket是Web伺服器端向客戶端推送資訊的協議,使用vert.x實現如下:

vertx.createHttpServer().websocketHandler { ws -> ws.dataHandler { data -> ws.writeTextFrame(data.toString()) } }.requestHandler { req -> if (req.uri == "/") req.response.sendFile "websockets/ws.html" }.listen(8080)

  瀏覽器客戶端通過JS呼叫:

<script> var socket; if (window.WebSocket) { socket = new WebSocket("ws://localhost:8080/myapp"); socket.onmessage = function(event) { alert("Received data from websocket: " + event.data); } socket.onopen = function(event) { alert("Web Socket opened!"); }; socket.onclose = function(event) { alert("Web Socket closed."); }; } else { alert("Your browser does not support Websockets. (Use Chrome)"); } function send(message) { if (!window.WebSocket) { return; } if (socket.readyState == WebSocket.OPEN) { socket.send(message); } else { alert("The socket is not open."); } } </script>

   SocketJS是一種處理客戶端和伺服器通訊的框架,能夠在客戶端提供類似websocket的API,支援JSON-Polling, XHR-Polling/Streaming。

<html> <head> <title>SockJS Test</title> <script src="http://cdn.sockjs.org/sockjs-0.3.4.min.js"></script> </head> <body> <script> var sock = new SockJS('http://localhost:8080/testapp'); sock.onopen = function() { console.log('open'); }; sock.onmessage = function(e) { console.log('message', e.data); alert('received message echoed from server: ' + e.data); }; sock.onclose = function() { console.log('close'); }; function send(message) { if (sock.readyState === SockJS.OPEN) { console.log("sending message") sock.send(message); } else { console.log("The socket is not open."); } } </script> <form οnsubmit="return false;"> <input type="text" name="message" value="Hello, World!"/> <input type="button" value="Send SockJS data" οnclick="send(this.form.message.value)"/> </form> </body> </html>

伺服器端建立一個SocketJS的Server:

def server = vertx.createHttpServer() // Serve the index page server.requestHandler { req -> if (req.uri == "/") req.response.sendFile 'sockjs/index.html' } // The handler for the SockJS app - we just echo data back vertx.createSockJSServer(server).installApp(prefix: '/testapp') { sock -> sock.dataHandler { buff -> sock << buff } } server.listen(8080)

訊息模型

   使用vert.x可以實現1:N和1:1的訊息模型。Publish/subscribe如下:

10000245_sMum.png

JS程式碼如下:

var eb = require("vertx/event_bus"); var console = require("vertx/console"); var vertx = require("vertx") vertx.setPeriodic(1000, function sendMessage() { eb. publish('news-feed', 'some news!'); })

訂閱者:

var eb = require("vertx/event_bus"); var console = require("vertx/console"); eb. registerHandler("news-feed", function(message) { console.log('Received news ' + message); });

一對一的佇列方式:

10000245_gW7U.png

釋出者JS程式碼如下:

var eb = require("vertx/event_bus"); var console = require("vertx/console"); var vertx = require("vertx") vertx.setPeriodic(1000, function sendMessage() { eb. send('ping-address', 'ping!', function(reply) { console.log("Received reply: " + reply); }); })

訂閱者程式碼如下:

var eb = require("vertx/event_bus"); var console = require("vertx/console"); eb.registerHandler("ping-address", function(message, replier) { console.log('Received message ' + message); // Now reply to it replier('pong!'); });

共享資料

  訊息傳遞是非常有用的。然而,它並不總是在所有型別的應用程式解決併發的最好選擇。快取也是最流行的解決方式之一。如果只有一個Verticle有一一個快取,這是非常低效的。當其他Verticles需要快取,每個Verticle應該共享相同的快取資料。 因此,Vert.x提供全域性訪問共享的MAP的方式,稱為 Shared Map。 共享的是不變性資料。

與NodeJS比較

10000245_pAge.png

安裝使用

   vertx使用了invokeDynamic in JDK7.因此需要JDK7環境。從http://vertx.io/downloads.html下載,解壓,將bin目錄加入環境PATH中。在windows環境可以執行vertx version

比如建設一個JS編寫的伺服器程式碼:

load('vertx.js'); vertx.createHttpServer().requestHandler(function(req) { req.response.end("Hello World!");}) .listen(8080, 'localhost');

在命令列只有執行下面命令可啟動這個伺服器:

$ vertx run server.js

在瀏覽器開啟http://localhost:8080,可看到hello World

轉載於:https://my.oschina.net/dongwq/blog/191900