Vert.x 快速入门和进阶使用
Vert.x 快速入门
vertx简介
- vertx 的现状和背后支持的组织
- vertx 是 eclipse基金会的一个顶级项目,目前社区非常活跃,是在国外非常火的一个框架
- vertx的核心思想
- Reactive : 事件驱动式编程模型 reactive组织宣言
- vertx生态系统完善
- 和spring 进行对比 | 项目 | Spring | Vertx | | —- | —- | —- | | 核心框架 | spring-core | vertx-core | | Web开发 | spring-webmvc | vertx-web | | jdbc框架 | spring-jdbc | vertx-jdbc-client | | redis | spring-data-redis | vertx-redis-client | | 微服务 | spring-cloud | vertx-hazelcast |
vertx核心功能点
1. 使用reactive模型快速构建简单web应用
vertx 构建简单 web应用分为三步
- 创建并配置Vertx对象实例
- 创建并配置HttpServer对象实例
- 使用回调方式编写业务逻辑代码
完整示例
public class VertxMain {private static final Logger logger = LoggerFactory.getLogger(VertxMain.class);public static void main(String[] args) {VertxOptions vertxOptions = new VertxOptions().setEventLoopPoolSize(8);Vertx vertx = Vertx.vertx(vertxOptions);HttpServerOptions httpServerOptions = new HttpServerOptions();HttpServer httpServer = vertx.createHttpServer(httpServerOptions);httpServer.requestHandler((req)->{req.bodyHandler((buf)->{String stringData = buf.toString();logger.info("data : {0}",stringData);});req.response().setChunked(true);req.response().write("hello world").end();}).listen(8088,(vo)->{if(vo.succeeded()){logger.info("server success !");}else{logger.info("server failed !");}});}}
2. 内置微服务/分布式支持EventBus
eventBus简介
- eventBus 官方对的定义是vertx的”神经系统”,用来模糊掉系统相互调用时候的强耦合\硬编码的部分.
- eventBus 将各个逻辑模块化,并且支持不同语言编写的模块相互通信
- event bus支持发布/订阅模式,点对点模式,和请求/响应模式。
EventBus 使用方法
EventBus 的使用方法非常简单,只需要在上面实现的简单服务器加上几行就可以实现了
public class EventBusServer {private static final Logger logger = LoggerFactory.getLogger(EventBusServer.class);public static void main(String[] args) {VertxOptions vertxOptions = new VertxOptions();Vertx vertx = Vertx.vertx(vertxOptions);EventBus eventBus = vertx.eventBus();eventBus.consumer("event_bus_1",(msg)->{logger. info("this is server 1 address : {0}",msg.body());msg.reply("this is server get the message");}).completionHandler((res)->{if(res.succeeded()){logger.info("comple sucess!");}else{logger.info("comple error!");}});HttpServerOptions httpServerOptions = new HttpServerOptions();HttpServer httpServer = vertx.createHttpServer(httpServerOptions);httpServer.requestHandler((req)->{req.bodyHandler((msg)->{DeliveryOptions options = new DeliveryOptions();options.addHeader("some-header", "some-value");eventBus.request("event_bus_1",msg.toString(),(message)->{System.out.println(message.result().body());});req.response().end("hello world");});}).listen(8088,(vo)->{if(vo.succeeded()){logger.info("lisence sucess!");}else{logger.info("lisence error!");}});}}
EventBus 扩展到分布式模式
Vertx 内置了一个接口ClusterManager,通过这个接口可以自己实现 分布式逻辑
Vertx 官方提供了一个默认的ClusterManager实现 - Hazelcast
Hazelcast 简介
Hazelcast 是由Hazelcast公司开发和维护的开源产品,可以为基于jvm环境运行的各种应用提供分布式集群和分布式缓存服务。类似golang的etcd,不过可以嵌入到java中运行可以做”服务发现治理”,”分布式存储”的底层依赖.
Vertx 嵌入 Hazelcast 实现分布式非常简单,只需要在EventBus上面增加几行代码就能实现
<dependency><groupId>io.vertx</groupId><artifactId>vertx-hazelcast</artifactId><version>version</version></dependency>
server
public class EventBusClusterServer {private static final Logger logger = LoggerFactory.getLogger(EventBusClusterServer.class);public static void main(String[] args) {//创建ClusterManger对象ClusterManager mgr = new HazelcastClusterManager();//设置到Vertx启动参数中VertxOptions options = new VertxOptions().setClusterManager(mgr);Vertx.clusteredVertx(options, res -> {if (res.succeeded()) {Vertx vertx = res.result();EventBus eventBus = vertx.eventBus();eventBus.consumer("event_bus_2",(msg)->{logger. info("this is server 1 address : {0}",msg.address());logger.info("data: {0}",msg.body());}).completionHandler((result)->{if(result.succeeded()){logger.info("comple sucess!");}else{logger.info("comple error!");}});} else {// failed!logger.info("create cluster error!");}});}}
client
public class EventBusClusterClient {private static final Logger logger = LoggerFactory.getLogger(EventBusClusterClient.class);public static void main(String[] args) {//创建ClusterManger对象ClusterManager mgr = new HazelcastClusterManager();//设置到Vertx启动参数中VertxOptions options = new VertxOptions().setClusterManager(mgr);Vertx.clusteredVertx(options, res -> {if (res.succeeded()) {Vertx vertx = res.result();EventBus eventBus = vertx.eventBus();HttpServer httpServer = vertx.createHttpServer();httpServer.requestHandler((requst)->{requst.bodyHandler((buf)->{eventBus.send("event_bus_2",buf.toString());requst.response().end("hello word");});}).listen(8088,(vo)->{if(vo.succeeded()){logger.info("lisence sucess!");}else{logger.info("lisence error!");}});} else {// failed!logger.info("create cluster error!");}});}}
3. 插件化代码组织方式
vertx支持基于Verticle接口的方式组织代码,沿用一种插件化编程的思想,最大限度的提高功能或者代码逻辑组织过程中的灵活度
插件化思想的历史
插件化思想最早是来源于android开发,早期的android开发因为android jvm的问题存在64K方法数魔咒-android的Dalvik vm的可执行文件规范限制了单个.dex文件最多引用的方法数是65536个。
为了解决这个问题,有人想想出了利用java热部署的能力开发插件化功能,支持插件化的app可以在运行时加载和运行class文件,这样便可以将app中一些不常用的功能模块做成插件,减小了安装包的大小和函数数量 , 并且实现了app功能的动态扩展
vertx 引入插件化开发同样非常简单 共需要两部
- 构造好Verticle接口实现类
- Vertx加载这个实现类
import io.vertx.core.AbstractVerticlepublic class HelloWorldHttpVerticle extends AbstractVerticle {@Overridepublic void start() throws Exception {System.out.println("hello world");}}public class VertxVerticle {public static void main(String[] args) {Vertx vertx = Vertx.vertx();vertx.deployVerticle("test.java", (v) -> {if (v.succeeded()) {System.out.println("ok java");}});}}
4. 基于jvm的多语言支持
vertx的多语言支持其实依赖于 Vertx的插件化部署和jvm的多语言支持
例子 groovy Verticle 部署
import io.vertx.core.AbstractVerticleclass HelloWorldHttpVerticle extends AbstractVerticle {void start() {for(int a in 0..199){println a;}}void stop() {println("Stopping")}}public class VertxVerticle {public static void main(String[] args) {Vertx vertx = Vertx.vertx();vertx.deployVerticle("test.groovy", (v) -> {if (v.succeeded()) {System.out.println("ok java");}});}}
vertx 基础部分总结
vertx 提供了四大特性
- 高性能 - 底层netty / 异步化编程
- EventBus内置分布式 Hazelcast
- Verticle插件化 高度扩展性
- 多语言支持 依赖jvm
vertx进阶 - 实用vertx 实现一个简单的在线函数运行平台(Faas平台)
一个Faas需要的东西
- 支持函数运行
- 分布式调用(函数及服务)
- 多语言支持 (多种语言编写函数)
Vertx 和Faas 需求的对比
- 函数运行 - vertx Verticle 可以实现
- 分布式调用 - vertx Verticle 可以内置的使用EventBus实现分布式
- 多语言支持 - vertx 天然支持多语言
实现 - >
非阻塞式处理的新方式
Vertx编码的首要原则就是不要阻塞它。根据中文文档的显示,route.handler()是阻塞的,所以一开始,我的代码结构基本上是这样的:
route.handler(routingContext->{vertx.executeBlocking(future->{//业务处理},asyncResult->{//返回结果})})
其中future的lambada负责获取结果传入future,asyncResult负责向response写入结果。
但是新版的VertxHttp中(我目前使用3.8.1),route增加了blockingHandler方法,自己就帮我们这样调用了,所以编码时可以简化为:
route.blockingHandler(routingContext->{//业务处理并返回结果})
这么写的好处除了精简之外,最大的好处就是返回可以根据业务处理的情形变化,如果正常,返回结果,如果异常,返回错误消息。
参考
https://github.com/reactiverse/reactive-pg-client
https://github.com/gxzqaz/vertx-admin
