
我們看到了熟悉的netty,但是兩個些許比較陌生的名字,vertx和undertow。最近這些天,看了一下這兩個框架的東西,覺得設計的各方面非常棒。
2. http://vertx.io/
Vert.x is a lightweight, high performance application platform for the JVM that's designed for modern mobile, web, and enterprise applications.
3.http://undertow.io/
Undertow is a flexible performant web server written in java, providing both blocking and non-blocking API’s based on NIO.
4.本篇文章以最入門的例子來探索二者的用法,后續還會深入源碼進行解析(使用了Java8的Lambda)
package com.mavsplus.example.vertx;
import io.vertx.core.Vertx;
import io.vertx.core.eventbus.EventBus;
import io.vertx.core.eventbus.MessageConsumer;
import io.vertx.core.file.FileSystem;
import io.vertx.core.http.HttpClient;
import io.vertx.core.http.HttpClientOptions;
import io.vertx.core.http.HttpMethod;
import io.vertx.core.http.HttpServer;
import io.vertx.core.http.HttpServerOptions;
/**
* Vert.x例子
*
* <pre>
* 設計思路上可以從BIO->NIO理解,如BIO中的connect/read/write方法都是阻塞操作,而NIO模式下如果沒有結果則方法立即返回
* </pre>
*
* @author landon
* @since 1.8.0_25
*/
public class Vertx3Example {
public void useFile() {
Vertx vertx = Vertx.factory.vertx();
FileSystem fs = vertx.fileSystem();
// copy過程為純異步操作,異步回調在lambda執行
// 1.游戲開發過程中通常需要異步回調給主線程進行處理
// 2.對于此實現完全可以使用guava的線程池進行異步回調處理
// 3.完全可以用顯示的異步線程池處理,即IO操作交給異步線程,IO操作完畢后交給主線程進行處理
// 4.個人更傾向于異步回調的方式用消息進行處理
// 5.當然可以使用vertx,在完成的handler進行回調主線程進行處理
fs.copy("foo.txt", "bar.txt", res -> {
// 輸出異步完成調用線程
System.out.println(String.format("callback thread:%s", Thread.currentThread().getName()));
// 判斷異步操作是否成功
if (res.succeeded()) {
System.out.println("fs.copy successed!");
} else {
System.out.println("fs.copy failed!");
// 如果失敗的話判斷異常
if (res.failed() && res.cause() != null) {
res.cause().printStackTrace();
vertx.close();
}
}
});
}
// 用vertx做embedded的httpserver/client挺方便
// 實際使用需要壓力測試和其他方面測試 或者和其他如undertow進行比較
public void useHttp() {
Vertx vertx = Vertx.factory.vertx();
// builder模式
HttpServerOptions httpServerOptions = new HttpServerOptions().setMaxWebsocketFrameSize(1000000);
HttpServer httpServer = vertx.createHttpServer(httpServerOptions);
// 監聽,監聽選項由HttpServerOptions提供,默認port:80,host:0.0.0.0
// 注:調用listen前必須設置requestHandler
httpServer.requestHandler(request -> {
request.response().end("Hello,Vertx!");
}).listen(listen -> {
if (listen.succeeded()) {
System.out.println("The httpServer is now listenning now");
} else {
System.out.println("The httpServer failed to bind!");
}
});
HttpClientOptions httpClientOptions = new HttpClientOptions();
HttpClient httpClient = vertx.createHttpClient(httpClientOptions);
// 必須調用end,調用end前必須設置responseHandler
httpClient
.request(HttpMethod.GET, "http://127.0.0.1:80")
.handler(
response -> {
System.out.println("response statusMessage:" + response.statusMessage() + " statusCode:"
+ response.statusCode());
response.bodyHandler(body -> {
System.out.println("response body:" + body);
});
}).end();
}
// The event bus implements publish / subscribe, point to point messaging
// and request-response messaging
public void useEventBus() {
Vertx vertx = Vertx.vertx();
EventBus eb = vertx.eventBus();
// subscribe_訂閱消息
MessageConsumer<String> consumer = eb.consumer("nba.sport", message -> {
System.out.println("I have receive a msg:" + message.body());
// reply
message.reply("how interesting!");
});
consumer.completionHandler(res -> {
if (res.succeeded()) {
System.out.println("The handler registration has reached all nodes");
} else {
System.out.println("Registration failed");
}
});
// publish_發布消息
eb.publish("nba.sport", "curry shot a 3-p ball!");
// 發送消息_注冊了reply_handler
eb.send("nba.sport", "lbj dunk!", ar -> {
if (ar.succeeded()) {
System.out.println("Receieved reply:" + ar.result().body());
}
});
}
public static void main(String[] args) {
Vertx3Example example = new Vertx3Example();
// example.useFile();
// example.useHttp();
example.useEventBus();
}
}
package com.mavsplus.example.undertow;
import io.undertow.Undertow;
import io.undertow.util.Headers;
/**
* Undertow例子
*
* @author landon
* @since 1.8.0_25
*/
public class UndertowExample {
public void helloWorld() {
// builder模式,使用lambda,如果HttpHandler接口顯示的加上函數式接口就更好了
// 即只要接口中有一個方法就可以使用lambda
Undertow server = Undertow.builder().addHttpListener(80, "localhost").setHandler(exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello,World!");
}).build();
server.start();
}
public static void main(String[] args) {
UndertowExample example = new UndertowExample();
// 瀏覽器地址欄輸入 http://127.0.0.1/ 默認80端口 頁面輸出:Hello,World!
example.helloWorld();
}
}
import io.undertow.Undertow;
import io.undertow.util.Headers;
/**
* Undertow例子
*
* @author landon
* @since 1.8.0_25
*/
public class UndertowExample {
public void helloWorld() {
// builder模式,使用lambda,如果HttpHandler接口顯示的加上函數式接口就更好了
// 即只要接口中有一個方法就可以使用lambda
Undertow server = Undertow.builder().addHttpListener(80, "localhost").setHandler(exchange -> {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/plain");
exchange.getResponseSender().send("Hello,World!");
}).build();
server.start();
}
public static void main(String[] args) {
UndertowExample example = new UndertowExample();
// 瀏覽器地址欄輸入 http://127.0.0.1/ 默認80端口 頁面輸出:Hello,World!
example.helloWorld();
}
}
結束語:只是展示了一下用法,尤其是vertx,框架設計的非常好,后續會根據源碼進行解析。敬請期待后續系列!
附:本人最近正在學習的一些開源框架,有興趣的可以一起交流:
disruptor http://lmax-exchange.github.io/disruptor/
hornetq http://hornetq.jboss.org/
rocketmq https://github.com/alibaba/RocketMQ
vertx http://vertx.io/
undertow http://undertow.io/
mina3/netty5/xnio
protobuf/thrift
artemis
flume