原创

Vert.x简介、原理与HelloWorld

Vert.x 简介

官方文档

http://vertx.io/docs/vertx-core/java/

关于Vert.x

Vertx,是一个基于JVM、轻量级、高性能的应用平台,非常适用于移动端后台、互联网、企业应用架构。

Vertx,基于Netty全异步通信,并扩展出了很多有用的特性。

Vertx,是基于事件总线设计的高性能架构,保证应用中不同部分以一种非堵塞的线程安全方式通讯。

Vertx,是借鉴Erlang和Akka架构设计,能充分利用多核处理器性能并实现高并发编程需求的框架。

Vert.x特点

支持多种编程语言

目前支持Java、JavaScript、Ruby、Python、Groovy、Clojure、Ceylon等,并提供友好的API接口。以上技术栈的工程师可以非常容易的学习和使用Vert.x 架构。

异步无锁编程

经典的多线程编程模型能满足很多Web开发场景,但随着移动互联网并发连接数的猛增,多线程并发控制模型性能难以扩展,同时要想控制好并发锁需要较高的技巧,目前Reactor异步编程模型开始跑马圈地,而Vert.x就是这种异步无锁编程的一个首选。

对各种IO的丰富支持

目前Vert.x的异步模型已支持TCP、UDP、FileSystem、DNS、EventBus、Sockjs等,基本满足绝大多数系统架构需求。

分布式消息传输

Vert.x基于分布式Bus消息机制实现其Actor模型,我们的业务逻辑如果依赖其他Actor则通过Bus简单的将消息发送出去就可以了。EventBus事件总线,可以轻松编写分布式解耦的程序,具有很好的扩展性。

EventBus也是Vert.x架构的灵魂所在。

生态体系日趋成熟

Vertx归入Eclipse基金会门下,异步驱动已经支持了Postgres、MySQL、MongoDB、Redis等常用组件,并且有若干Vertx在生产环境中的应用案例。

Vertx是轻量级的

vertx的核心代码包只有650kB左右,同时提供丰富的扩展插件,满足各类需求。

Vertx并不是一个Web容器

Vertx并不是一个Web Server,它是一种异步编程框架,你可以将自己基于vert.x的应用程序放置到任何你想放置的Web容器中部署运行,可以非常方便的和Spring,Spring Boot,Spring Cloud,Nodejs等语言混编。

模块化

Vertx本身内置强大的模块管理机制,当你写完一个Vert.x业务逻辑的时候,你可以将其打包成module,然后部署到基于Maven的仓库里,与现有主流的开发过程无缝结合。

支持WebSocket

支持WebSocket协议兼容SockJS , 可以非常方便的实现web前端和服务后端长连接通信,是轻量级web聊天室应用首选解决方案。

使用简单

这里的简单意味着你编写的代码是完全基于异步事件的,类似Node.JS,与此同时.你不需要关注线程上的同步,与锁之类的概念,所有的程序都是异步执行并且通信是无阻塞的。

良好的扩展性

因为基于Actor模型,所以你的程序都是一个点一个点的单独在跑,一群点可以组成一个服务,某个点都是可以水平扩展,动态替换,这样你的程序,基本就可以达到无限制的水平扩展。

高并发性

vert.x是一个事件驱动非阻塞的异步编程框架,你可以在极少的核心线程里占用最小限度的硬件资源处理大量的高并发请求。

此并发并非JDK库的并发,当你Coding的时候,不再关注其锁,同步块,死锁之类的概念,你就可以随性所欲的写自己的业务逻辑,Vert.x本身内置三种线程池帮你处理。

目前,该框架国内用的还不太多,但是国外比较多,如英孚教育、Hulu、以及做JVM监控的一家公司jClarity等。Google group上的话题也比较多,非常活跃,属于技术极客圈里热门话题。

如果你是技术小白,可以通过学习Vertx拓宽你的技术栈;如果你是架构师,可以借鉴Vertx的架构设计思路,更好的提升自我的架构能力,也为公司未来的技术选型,多一种选择和考量。

Vertx原理解析

本小节主要讲一些理论性的东西,核心是想讲明白Vertx的体系结构,verticle和vertx的关系,以及verticles 之间是如何通信和运行的,很枯燥的一章。建议大家先大体看看,不用立刻理解(也不可能),带着疑问继续读后面的几个章节。

Vertx应用在很大程度上是通过定义事件处理程序。应用之间通过事件总线传递消息,异步响应。

Vertx的编程框架可以简单的理解为:

verticle是vert.x中可被部署运行的最小代码块,可以理解为一个verticle就是一个最小化的业务处理引擎。 一个应用程序可以是单个verticle或者由EventBus通信的多个verticles构成。

verticle被发布部署后,会调用其内部的start方法,开始业务逻辑处理,完成后会调用stop方法,对该代码块执行销毁动作。

Verticles在Vert.x实例中运行。 一个Vertx可以承载多个verticles,每个Vert.x实例在其私有的JVM实例运行。 一台服务器可以运行一个或多个Vert.x实例(建议运行Vertx实例的数量和CPU核数正相关)。

一个Vert.x实例,保证其承载的verticles实例总是在同一个线程执行, 并发Vert.x 是单线程的。

在内部,Vert.x实例维护一组线程(通常为CPU核心数)是在执行一个事件循环。

虽然你可能会认为,共享数据和可扩展性截然相反。 Vert.x提供了一个共享的MAP和跨在同一Vert.x实例中运行verticles传递不可改变的数据共享一套设施,这时候数据是可变的唯一真正的 。

Vert.x使用相对较少的线程来创建一个事件循环和执行verticles。 但在某些情况下,需要verticle做一些要么昂贵计算,或可能阻塞,如连接到数据库。 当发生这种情况Vert.x可以让你标记verticle实例作为worker verticle 。

Vert.x确保worker verticles将永远不会被同时执行。

Vert.x系统的体系结构

在这里插入图片描述

客户端请求处理流程

请求在vert.x框架中被插入到一个事件队列中,耗时的任务将被委托给长任务处理线程进行处理,保证线程不被耗时的IO操作进行阻塞等待。
在这里插入图片描述

EventBus通信模型

事件循环线程和长任务处理线程通过EventBus进行通信。
在这里插入图片描述

部分名词对照表:

Vert.x Core名词中英对照表

  • handler:事件处理器
  • event loop:事件循环(线程)
  • verticle:Vert.x的专有名词。指代Vert.x中基本的功能单元,一个Vert.x应用应该是由一组verticles构成的。
  • worker:顾名思义,干活的(线程)。对应文档中有worker thread pool,worker verticle(Vert.x里的work verticle与标准版verticle区别较大)。
  • event bus:事件总线

Vert.x核心功能是最底层且相当简洁的,没有诸如数据库存取、认证、高级web等功能,你可以在Vert.x ext(扩展包)找到以上这些组件。

Vert.x Core提供的功能:

  • 编写TCP客户端和服务器
  • 编写 HTTP 客户端和服务器包括 Websocket 支持
  • 事件总线(Event bus)
  • 共享的数据-本地的map和分布式的map
  • 定时和延时运行
  • 部署和非部署 Verticles
  • Sockets
  • DNS 客户端
  • 文件系统
  • 高可用性
  • 集群

准备工作

知识储备

在使用Vert.x框架进行编码前,需要掌握以下知识:

  • Java基础:不要求了解Java EE或者是Java ME的知识,但是需要你对Java有所了解
  • Maven:要知道什么Maven是做什么用的,以及如何使用Maven
  • 互联网的基础知识:知道什么是网络协议,尤其是TCP,HTTP协议

目标

建立一个基本的HTTP服务器,并监听8080端口,对于任何发往该服务器以及端口的请求,服务器会返回一个Hello World字符串。

构建项目

首先新建一个Maven项目,一个基本的Maven项目目录结构如下所示:

├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   └── resources
│   └── test
│       └── java

在项目中添加以下依赖

<properties>
        <vertx.version>3.4.2</vertx.version>
        <main.class>cn.yzstu.Main</main.class>
    </properties>
    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.2</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>${main.class}</Main-Class>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                            <artifactSet />
                            <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

HelloWorld

Main.java

package cn.yzstu;

import io.vertx.core.Vertx;

/** * @author Baldwin */
public class Main {
   
    public static void main(String[] args) {
   
        Vertx vertx = Vertx.vertx();
        vertx.deployVerticle(VerticleExample.class.getName());
    }
}

VerticleExample.java

package cn.yzstu;

import io.vertx.core.AbstractVerticle;

/** * @author Baldwin */
public class VerticleExample extends AbstractVerticle {
   
    @Override
    public void start() {
   
        vertx.createHttpServer().requestHandler(req -> {
   
            req.response()
                    .putHeader("content-type", "text/plain")
                    .end("Hello World!");
        }).listen(8080);
    }
}

启动

进入target目录,执行以下命令

java -jar ./vertx-1.0-SNAPSHOT-prod.jar

等待执行成功,然后访问localhost:8080
在这里插入图片描述

进阶

我们也可以使用Launcher来替代Main类,这也是官方推荐的方式,在pom.xml中加入main.verticle属性,并将该属性值设置为maven-shade-plugin插件的manifestEntries的Main-Verticle对应的值,最后修改main.class为io.vertx.core.Launcher。

修改pom文件如下

<properties>
        <vertx.version>3.4.2</vertx.version>
        <main.class>io.vertx.core.Launcher</main.class>
        <main.verticle>cn.yzstu.VerticleExample</main.verticle>
    </properties>
    <dependencies>
        <dependency>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-core</artifactId>
            <version>${vertx.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.2</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.2</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <manifestEntries>
                                        <Main-Class>${main.class}</Main-Class>
                                        <Main-Verticle>${main.verticle}</Main-Verticle>
                                    </manifestEntries>
                                </transformer>
                            </transformers>
                            <artifactSet />
                            <outputFile>${project.build.directory}/${project.artifactId}-${project.version}-prod.jar</outputFile>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

重新打包运行,打印日志

八月 10, 2021 12:06:36 上午 io.vertx.core.impl.launcher.commands.VertxIsolatedDeployer
信息: Succeeded in deploying verticle

访问localhost:8080可以获取到同样的结果

总结

第一步的HelloWorld并不难,难的是理解Vertx的运行原理与编码后续过程编码中的一些细节。无论如何,欢迎来到Vertx的世界!

正文到此结束