Vert.x 快速入门和进阶使用

Vert.x 快速入门

vertx简介

  • vertx 的现状和背后支持的组织

    • vertx 是 eclipse基金会的一个顶级项目,目前社区非常活跃,是在国外非常火的一个框架
  • vertx的核心思想

  • 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应用分为三步


    1. 创建并配置Vertx对象实例

    1. 创建并配置HttpServer对象实例

    1. 使用回调方式编写业务逻辑代码

完整示例

  1. public class VertxMain {
  2. private static final Logger logger = LoggerFactory.getLogger(VertxMain.class);
  3. public static void main(String[] args) {
  4. VertxOptions vertxOptions = new VertxOptions().setEventLoopPoolSize(8);
  5. Vertx vertx = Vertx.vertx(vertxOptions);
  6. HttpServerOptions httpServerOptions = new HttpServerOptions();
  7. HttpServer httpServer = vertx.createHttpServer(httpServerOptions);
  8. httpServer.requestHandler((req)->{
  9. req.bodyHandler((buf)->{
  10. String stringData = buf.toString();
  11. logger.info("data : {0}",stringData);
  12. });
  13. req.response().setChunked(true);
  14. req.response().write("hello world").end();
  15. }).listen(8088,(vo)->{
  16. if(vo.succeeded()){
  17. logger.info("server success !");
  18. }else{
  19. logger.info("server failed !");
  20. }
  21. });
  22. }
  23. }

2. 内置微服务/分布式支持EventBus

eventBus简介

  • eventBus 官方对的定义是vertx的”神经系统”,用来模糊掉系统相互调用时候的强耦合\硬编码的部分.
  • eventBus 将各个逻辑模块化,并且支持不同语言编写的模块相互通信
  • event bus支持发布/订阅模式,点对点模式,和请求/响应模式。

EventBus 使用方法

EventBus 的使用方法非常简单,只需要在上面实现的简单服务器加上几行就可以实现了

  1. public class EventBusServer {
  2. private static final Logger logger = LoggerFactory.getLogger(EventBusServer.class);
  3. public static void main(String[] args) {
  4. VertxOptions vertxOptions = new VertxOptions();
  5. Vertx vertx = Vertx.vertx(vertxOptions);
  6. EventBus eventBus = vertx.eventBus();
  7. eventBus.consumer("event_bus_1",(msg)->{
  8. logger. info("this is server 1 address : {0}",msg.body());
  9. msg.reply("this is server get the message");
  10. }).completionHandler((res)->{
  11. if(res.succeeded()){
  12. logger.info("comple sucess!");
  13. }else{
  14. logger.info("comple error!");
  15. }
  16. });
  17. HttpServerOptions httpServerOptions = new HttpServerOptions();
  18. HttpServer httpServer = vertx.createHttpServer(httpServerOptions);
  19. httpServer.requestHandler((req)->{
  20. req.bodyHandler((msg)->{
  21. DeliveryOptions options = new DeliveryOptions();
  22. options.addHeader("some-header", "some-value");
  23. eventBus.request("event_bus_1",msg.toString(),(message)->{
  24. System.out.println(message.result().body());
  25. });
  26. req.response().end("hello world");
  27. });
  28. }).listen(8088,(vo)->{
  29. if(vo.succeeded()){
  30. logger.info("lisence sucess!");
  31. }else{
  32. logger.info("lisence error!");
  33. }
  34. });
  35. }
  36. }

EventBus 扩展到分布式模式

Vertx 内置了一个接口ClusterManager,通过这个接口可以自己实现 分布式逻辑

Vertx 官方提供了一个默认的ClusterManager实现 - Hazelcast

Hazelcast 简介

Hazelcast 是由Hazelcast公司开发和维护的开源产品,可以为基于jvm环境运行的各种应用提供分布式集群和分布式缓存服务。类似golang的etcd,不过可以嵌入到java中运行可以做”服务发现治理”,”分布式存储”的底层依赖.

Vertx 嵌入 Hazelcast 实现分布式非常简单,只需要在EventBus上面增加几行代码就能实现

  1. <dependency>
  2. <groupId>io.vertx</groupId>
  3. <artifactId>vertx-hazelcast</artifactId>
  4. <version>version</version>
  5. </dependency>

server

  1. public class EventBusClusterServer {
  2. private static final Logger logger = LoggerFactory.getLogger(EventBusClusterServer.class);
  3. public static void main(String[] args) {
  4. //创建ClusterManger对象
  5. ClusterManager mgr = new HazelcastClusterManager();
  6. //设置到Vertx启动参数中
  7. VertxOptions options = new VertxOptions().setClusterManager(mgr);
  8. Vertx.clusteredVertx(options, res -> {
  9. if (res.succeeded()) {
  10. Vertx vertx = res.result();
  11. EventBus eventBus = vertx.eventBus();
  12. eventBus.consumer("event_bus_2",(msg)->{
  13. logger. info("this is server 1 address : {0}",msg.address());
  14. logger.info("data: {0}",msg.body());
  15. }).completionHandler((result)->{
  16. if(result.succeeded()){
  17. logger.info("comple sucess!");
  18. }else{
  19. logger.info("comple error!");
  20. }
  21. });
  22. } else {
  23. // failed!
  24. logger.info("create cluster error!");
  25. }
  26. });
  27. }
  28. }

client

  1. public class EventBusClusterClient {
  2. private static final Logger logger = LoggerFactory.getLogger(EventBusClusterClient.class);
  3. public static void main(String[] args) {
  4. //创建ClusterManger对象
  5. ClusterManager mgr = new HazelcastClusterManager();
  6. //设置到Vertx启动参数中
  7. VertxOptions options = new VertxOptions().setClusterManager(mgr);
  8. Vertx.clusteredVertx(options, res -> {
  9. if (res.succeeded()) {
  10. Vertx vertx = res.result();
  11. EventBus eventBus = vertx.eventBus();
  12. HttpServer httpServer = vertx.createHttpServer();
  13. httpServer.requestHandler((requst)->{
  14. requst.bodyHandler((buf)->{
  15. eventBus.send("event_bus_2",buf.toString());
  16. requst.response().end("hello word");
  17. });
  18. }).listen(8088,(vo)->{
  19. if(vo.succeeded()){
  20. logger.info("lisence sucess!");
  21. }else{
  22. logger.info("lisence error!");
  23. }
  24. });
  25. } else {
  26. // failed!
  27. logger.info("create cluster error!");
  28. }
  29. });
  30. }
  31. }

3. 插件化代码组织方式

vertx支持基于Verticle接口的方式组织代码,沿用一种插件化编程的思想,最大限度的提高功能或者代码逻辑组织过程中的灵活度

插件化思想的历史

插件化思想最早是来源于android开发,早期的android开发因为android jvm的问题存在64K方法数魔咒-android的Dalvik vm的可执行文件规范限制了单个.dex文件最多引用的方法数是65536个。

为了解决这个问题,有人想想出了利用java热部署的能力开发插件化功能,支持插件化的app可以在运行时加载和运行class文件,这样便可以将app中一些不常用的功能模块做成插件,减小了安装包的大小和函数数量 , 并且实现了app功能的动态扩展

vertx 引入插件化开发同样非常简单 共需要两部

  1. 构造好Verticle接口实现类
  2. Vertx加载这个实现类
  1. import io.vertx.core.AbstractVerticle
  2. public class HelloWorldHttpVerticle extends AbstractVerticle {
  3. @Override
  4. public void start() throws Exception {
  5. System.out.println("hello world");
  6. }
  7. }
  8. public class VertxVerticle {
  9. public static void main(String[] args) {
  10. Vertx vertx = Vertx.vertx();
  11. vertx.deployVerticle("test.java", (v) -> {
  12. if (v.succeeded()) {
  13. System.out.println("ok java");
  14. }
  15. });
  16. }
  17. }

4. 基于jvm的多语言支持

vertx的多语言支持其实依赖于 Vertx的插件化部署和jvm的多语言支持

例子 groovy Verticle 部署

  1. import io.vertx.core.AbstractVerticle
  2. class HelloWorldHttpVerticle extends AbstractVerticle {
  3. void start() {
  4. for(int a in 0..199){
  5. println a;
  6. }
  7. }
  8. void stop() {
  9. println("Stopping")
  10. }
  11. }
  12. public class VertxVerticle {
  13. public static void main(String[] args) {
  14. Vertx vertx = Vertx.vertx();
  15. vertx.deployVerticle("test.groovy", (v) -> {
  16. if (v.succeeded()) {
  17. System.out.println("ok java");
  18. }
  19. });
  20. }
  21. }

vertx 基础部分总结

vertx 提供了四大特性

  1. 高性能 - 底层netty / 异步化编程
  2. EventBus内置分布式 Hazelcast
  3. Verticle插件化 高度扩展性
  4. 多语言支持 依赖jvm

vertx进阶 - 实用vertx 实现一个简单的在线函数运行平台(Faas平台)

一个Faas需要的东西

  1. 支持函数运行
  2. 分布式调用(函数及服务)
  3. 多语言支持 (多种语言编写函数)

Vertx 和Faas 需求的对比

  1. 函数运行 - vertx Verticle 可以实现
  2. 分布式调用 - vertx Verticle 可以内置的使用EventBus实现分布式
  3. 多语言支持 - vertx 天然支持多语言

实现 - >

轻量级函数运行时引擎

非阻塞式处理的新方式

Vertx编码的首要原则就是不要阻塞它。根据中文文档的显示,route.handler()是阻塞的,所以一开始,我的代码结构基本上是这样的:

  1. route.handler(routingContext->{
  2. vertx.executeBlocking(future->{
  3. //业务处理
  4. },asyncResult->{
  5. //返回结果
  6. })
  7. })

其中future的lambada负责获取结果传入future,asyncResult负责向response写入结果。
但是新版的VertxHttp中(我目前使用3.8.1),route增加了blockingHandler方法,自己就帮我们这样调用了,所以编码时可以简化为:

  1. route.blockingHandler(routingContext->{
  2. //业务处理并返回结果
  3. })

这么写的好处除了精简之外,最大的好处就是返回可以根据业务处理的情形变化,如果正常,返回结果,如果异常,返回错误消息。

参考

https://github.com/reactiverse/reactive-pg-client
https://github.com/gxzqaz/vertx-admin

https://github.com/eclipse-vertx/vertx-sql-client