前言
早上有人在群上吐槽说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 科普贴