geek的技术日志,记录每一次技术思考的闪光点。

Vert.x 科普贴

前言

早上有人在群上吐槽说Spring 成本高,入手难,新手才用Spring啥啥的。我就怼了他们,然后顺便了解了一下,假如没有Spring,有什么是可以替代的。

如上图,Vert.x是仅次于SpringMVC的(做这图的人有点傻逼,居然吧Spring boot也单独拎出来),Vert.x大概是Spring一半的样子吧。

Vert.x背景

Vert.x是Eclipse基金会下的一个开源的Java开发框架,Vert.x是一个基于JVM,支持多种编程语言,轻量级,高性能的异步非阻塞的编程框架。使用Vert.x可以开发Web API 接口,互联网应用,移动端后台等。

Vertx能干什么?

1.Web开发
 可以实现类似于PHP,Servlet等的Web开发
 
2.TCP/UDP开发
 底层基于netty,可以开发异步非阻塞的高效的TCP服务器
 
3.提供对WebSocket的支持
 可以做网络聊天室,动态推送等。
 
4.提供对SSL的支持
 可以开发https协议的服务
 
5.通过EventBus可以实现发布订阅
 
6.支持微服务开发
 提供服务的注册与发现、配置中心、断路器等
 
7.支持主流的数据和消息的访问
 redis mongodb rabbitmq kafka 等
 
8. 分布式锁,分布式计数器,分布式map的支持

简单来说,就是Spring能干的东西Vert.x他都能干,然后还有支持多语言和异步的优势。现在最新的Spring也支持异步非阻塞了,所以他唯一的优势就是支持多语言了。但对比Spring,劣势就多着啦。

快速体验

下面实现一个HttpServer,实现使用浏览器访问,给浏览器返回一个 SUCCESS的功能来快速感受下Vert.x。下面这个类可以直接运行,而不需要使用tomcat进行部署,就可以直接通过浏览器来进行访问。非常类似于nodejs,但是比nodejs的性能要高很多。请求的地址为:http://localhost。

public class MyHttpServer extends AbstractVerticle {
 
 public static void main(String[] args) {
 // 创建服务
 MyHttpServer verticle = new MyHttpServer();
 Vertx vertx = Vertx.vertx();
 
 // 部署服务,会执行MyHttpServer的start方法
 vertx.deployVerticle(verticle);
 }
 
 @Override
 public void start() throws Exception {
 // 在这里可以通过this.vertx获取到当前的Vertx
 Vertx vertx = this.vertx;
 
 // 创建一个HttpServer
 HttpServer server = vertx.createHttpServer();
 
 server.requestHandler(request -> {
 // 获取到response对象
 HttpServerResponse response = request.response();
 
 // 设置响应头
 response.putHeader("Content-type", "text/html;charset=utf-8");
 
 // 响应数据
 response.end("SUCCESS");
 
 });
 
 // 指定监听80端口
 server.listen(80);
 }
}

下面具体看看什么是Vert.x

简单说,Vert.x就是一堆的jar包,提供了一系列的编程API接口。通过这些API,可以进行异步编程。

快速理解异步编程

什么是异步编程?异步编程是Vert.x的一大特性,也是Vert.x的核心,异步编程非常好理解,写过ajax吗,看下面代码,$.ajax方法并不会阻塞,而是直接向下执行,等到远程服务器响应之后,才会回调success方法,那么这时候success方法才会执行。ajax下面的代码不会等到success方法执行完毕之后再执行,这就是所谓的异步。

console.log("1");
 
$.ajax({
 "url" : "/hello",
 "type" : "post",
 "dataType" : "json",
 "success" : function(val) {
 console.log("2");
 }
});
 
console.log("3");

 
Vert.x可以开发Web应用,但Vert.x不仅仅是一个Web开发框架,他更像Spring,是一个技术栈(Vert.x生态可以查看https://github.com/vert-x3/vertx-awesome),或者说是一个Vert.x生态体系。在这个体系中,Vert.x只是提供了Web开发的能力。下面对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
可以说,很多的spring能做的事情,Vertx也都能实现。那么既然如此,Spring如此强大,社区如此活跃,为何还会有Vertx呢?他们之前区别的核心点就只有一个,Spring的操作是同步的,Vertx的操作是异步的。异步带来了更高的性能,但同时也带来了编码和调试的复杂度,但不得不说异步可能是未来的一个趋势,至少在Java实现高性能服务器上的一个趋势。

在Java领域,做Web开发我们一般有很多的选择,比如使用原生的Servlet,比如使用SpringMVC,再比如使用Struts等等总之你有很多的选择。在国内,目前来讲,SpringMVC作为Spring体系下的Web层架构,是深受企业青睐的,绝大部分的企业可能都在使用SpringMVC。而对于我们今天要说的Vert.x这个Web层框架,却很少有人知道,但它却是仅次于SpringMVC,排名第二的一个Web层框架。

Vert.x的一些优势

Vert.x就像是跑在JVM之上的Nodejs,所以Vert.x的第一个优势就是这是一个异步非阻塞框架。上面也提到了异步,我们使用ajax来演示的异步,下面使用Vert.x请求远程地址一个代码,可以看到和ajax非常像!

System.out.println("1")
 
WebClient
 .create(vertx)
 .postAbs(REQUEST_URL) // 这里指定的是请求的地址
 .sendBuffer(buffer, res -> { // buffer是请求的数据
 
 if (res.succeeded()) { 
 // 请求远程服务成功
 System.out.println("2")
 
 } else {
 // 请求失败
 resultHandler.handle(Future.failedFuture("请求服务器失败..."));
 }
 });
 
System.out.println("3")
这段代码的执行效果和上面的JavaScript执行的结果是类似的,同样是先打印 1,再打印 3,最后打印 2。

异步也是Vert.x于其他的JavaWeb框架的主要区别。我们这里先不去讨论异步的优势与他的实现原理,只要先知道,Vert.x和JavaScript一样,是一个异步执行的就可以了。

Vert.x和JDK8

Vert.x必须运行在JDK8上,JDK8提供了lambda表达式,可以简化匿名内部类的编写,可以极大的挺高代码的可读性。

上面的代码中看到 在 sendBuffer 这一行里有一个 -> 这种形式。这个是Java代码吗? 是的。是JDK8提供的lambda表达式的形式。用于简化匿名内部类的开发。有兴趣的朋友可以了解一下lambda表达式,在使用Vertx进行项目开发时有大量的匿名内部类,因此很多情况会用到。

Vertx支持多种编程语言。Vert.x有一个口号大概是:“我们不去评判那个编程语言更好,你只要选择你想要使用的语言就可以了”。也就是说,在Vert.x上,可以使用JavaScript,Java,Scala,Ruby等等,下面是官网的一个截图

不依赖中间件。Vert.x的底层依赖Netty,因此在使用Vert.x构建Web项目时,不依赖中间件。像Node一样,可以直接创建一个HttServer。就像我们上面第一个例子,可以直接运行main方法,启动一个Http服务,而不需要使用类似于Tomcat的中间件。不依赖中间件进行开发,相对会更灵活一些,安全性也会更高一些。

完善的生态。Vert.x和Spring的对比,有一种使用MacOS和Windows对比的感觉。Vert.x和庞大的Spring家族体系不同,Vert.x提供数据库操作,Redis操作,Web客户端操作,NoSQL数据库的一些操作等常用的结构,很清新,很简洁,但足够使用。下面是从官网截取的一个提供的客户端工具。

为微服务而生。Vert .x提供了各种组件来构建基于微服务的应用程序。通过EventBus可以非常容易的进行服务之间的交互。并且提供了HAZELCAST来实现分布式。

当然了,除了一些优势以外,要在项目中选择使用Vert.x还要考虑一些问题,这里不展开说明,只是根据个人的使用经验提出一些点。

  • Vert.x使用JDK8的Lambda,所以要使用Vert.x首先需要对JDK8比较熟悉。当然,对于一个开发者,现在JDK已经出到JDK11了,JDK8的特性也理应该学习一下

  • 对于复杂的业务,可能会遇到Callback Hell问题(解决方案也有很多)

  • 由于异步的特征、契约创建、更高级的错误处理机制使得开发过程会相对更复杂。(来自并发编程网)

Vert.x技术体系

上面也提到了,Vert.x和Spring一样,也有着完善的生态,具体可以查看https://github.com/vert-x3/vertx-awesome 我们可以看到,每一块内容都提供了多种的实现,有官方支持的版本还有社区版本。下面我们具体介绍下技术体系中官方支持的版本。

(1)核心模块

Vert.x核心模块包含一些基础的功能,如HTTP,TCP,文件系统访问,EventBus、WebSocket、延时与重复执行、缓存等其他基础的功能,你可以在你自己的应用程序中直接使用。可以通过vertx-core模块引用即可。

(2)Web模块

Vert.x Web是一个工具集,虽然核心模块提供了HTTP的支持,但是要开发复杂的Web应用,还需要路由、Session、请求数据读取、Rest支持等等还需要Web模块,这里提供了上述的这些功能的API,便于开发。

除了对Web服务的开发以外,还提供了对Web客户端请求的支持,通过vertx-web-client即可方便的访问HTTP服务。有朋友可能会有疑惑,我明明可以使用JDK提供的URL来请求HTTP服务啊。使用Vert.x一定要注意,Vert.x是一个异步框架,请求HTTP服务是一个耗时操作,所有的耗时,都会阻塞EventBus,导致整体性能被拖垮,因此,对于请求Web服务,一定要使用Vert.x提供的vertx-web-client模块

(3)数据访问模块

Vert.x提供了对关系型数据库、NoSQL、消息中间件的支持,传统的客户端因为是阻塞的,会严重影响系统的性能,因此Vert.x提供了对以上客户端的异步支持。具体支持的数据访问如下:

MongoDB client,JDBC client,SQL common,Redis client,MySQL/PostgreSQLclient

(4)Reactive响应式编程

复杂的异步操作,会导致异步回调地狱的产生,看下面的代码,这是我在Vert.x提供的例子中找到的,我们不去管这段代码干了啥,只是看后面的}就很惊讶了,如果操作更为复杂一些,会嵌套的层次更多,通过reactive可以最小化的简化异步回调地狱。

// create a test table
execute(conn.result(), "create table test(id int primary key, name varchar(255))", create -> {
 // start a transaction
 startTx(conn.result(), beginTrans -> {
 // insert some test data
 execute(conn.result(), "insert into test values(1, 'Hello')", insert -> {
 // commit data
 rollbackTx(conn.result(), rollbackTrans -> {
 // query some data
 query(conn.result(), "select count(*) from test", rs -> {
 for (JsonArray line : rs.getResults()) {
 System.out.println(line.encode());
 }
 
 // and close the connection
 conn.result().close(done -> {
 if (done.failed()) {
 throw new RuntimeException(done.cause());
 }
 });
 });
 });
 });
 });
});

再看一个使用Reactive2构建的多步操作的代码,paramCheckStep,insertPayDtlStep,requestStep等等都是异步方法,但这里就很好的处理了异步回调的问题,不再有那么多层的大括号,代码结构也geng

public void scanPay(JsonObject data, Handler<AsyncResult<JsonObject>> resultHandler) {
 paramCheckStep(data) // 参数校验
 .flatMap(this::insertPayDtlStep) // 插入流水
 .flatMap(x -> requestStep(x, config)) // 请求上游
 .flatMap(this::cleanStep) //参数清理
 .subscribe(ok -> {
 logger.info("成功结束");
 resultHandler.handle(Future.succeededFuture(ok));
 },
 err -> {
 logger.error("正在结束", err);
 resultHandler.handle(Future.failedFuture(err));
 }
 
 );
}

(5)整合其他模块

邮件客户端

Vert.x提供了一简单STMP邮件客户端,所以你可以在应用程序中发送电子邮件。

STOMP客户端与服务端

Vert.x提供了STOMP协议的实现包括客户端与服务端。

Consul Client

consul是google开源的一个使用go语言开发的服务发现、配置管理中心服务。内置了服务注册与发现框 架、分布一致性协议实现、健康检查、Key/Value存储、多数据中心方案。

RabbitMQ Client  Kafka Client

消息队里的客户端支持

JCA适配器

Vert.x提供了Java连接器架构适配器,这允许同任意JavaEE应用服务器进行互操作。

(6)认证与授权

Vert.x提供了简单API用于在应用中提供认证和授权。

Auth common 通用的认证API,可以通过重写AuthProvider类来实现自己的认证

JDBC auth 后台为JDBC的认证实现

JWT auth 用JSON Web tokens认证实现

Shiro auth 使用Apache Shiro认证实现

MongoDB auth MongoDB认证实现

OAuth 2 Oauth2协义认证实现

htdigest auth 这个是新增一种认证的支持

(7)微服务

Vert.x提供多个组件构建基于微服务的应用程序。

比如服务发现(Vert.x Service Discovery)、断路器(Vert.x Circuit Breaker)、配置中心(Vert.x Config)等。

 

Vert.x 案例代码:https://github.com/happy-fly

实话说,找Vert.x的资料时候,找遍了大大小小的网站,发现市面上关于Vert.x的文档除了官方文档外,几乎找不到其他资料。 Vert.x真不是个主流的选择,以此忠告在Vert.x上踩坑的朋友,赶紧脱坑。因为笔者能力有限,文章中难免会有错误和疏漏,如果您对文章有意见或者好的建议,可以加首页右上角的QQ群进行技术讨论。
 

打赏作者

未经允许不得转载:极客技术 » Vert.x 科普贴

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址