Skip to content

Latest commit

 

History

History
89 lines (56 loc) · 8.12 KB

File metadata and controls

89 lines (56 loc) · 8.12 KB

介绍

本指南简要的介绍了 Vertx 的异步编程,主要针对使用主流非异步 Web 开发框架和库(例如 Java EE , Spring)的开发人员。

关于本指南

我们假定读者熟悉 Java 编程语言以及它的生态系统。

我们将从一个由关系型数据库和服务器端页面渲染支持 Wiki Web 应用程序开始;然后我们将通过几个步骤改进应用程序,直到它成为具有"实时"[1]特征的现代单页面应用。 在整个过程中,你将会学到:

  1. 使用模板技术设计一个服务端渲染的 Web 应用,并且使用关系型数据库来持久化数据。

  2. 清晰地抽离出每个技术组件,作为一个可以重复使用的事件处理单元被称为 verticle

  3. 抽取 Vert.x 的服务,以便于设计在同一 JVM 进程内或集群中的分布式节点之间进行无缝通信的 verticles。

  4. 使用异步操作测试代码。

  5. 与暴露 HTTP/JSON Web API的第三方服务集成。

  6. 对外提供 HTTP/JSON Web API。

  7. 使用 HTTPS 来保护和控制访问、Web 浏览器会话验证用户身份以及第三方客户端应用的 JWT 令牌。

  8. 借助当下流行的 RxJava 库及它在 Vert.x 集成的反应式编程来重构一些代码。

  9. 客户端采用 AngularJS 来开发单页面应用程序。

  10. 使用统一的 Vert.x 事件总线集成在 SockJS 上的实时 Web 编程。

Note
本文档和代码示例的源码可以 https://github.com/vert-x3/vertx-guide-for-java-devs 获得。 我们欢迎提交问题报告,反馈以及推送请求!

什么是 Vert.x?

Eclipse Vert.x 是一个在 JVM 上构建响应式应用程序的工具包。 — Vert.x 官网

Eclipse Vert.x (以下简称 Vert.x ) 是 Eclipse 基金会下的一个开源项目。 Vert.x 于 2012 年由 Tim Fox 发起的。

Vert.x 不是一个框架,而是一个工具包:它的核心库定义编写异步网络应用程序的基础 API,然后你可以选择一些对应用有用的模块(例如,数据库连接,监控,身份验证,日志,服务发现,集群支持等等)。 Vert.x 基于 Netty 项目 - 一个为 JVM 设计的高性能异步网络库。 如果需要的话,Vert.x 允许你访问 Netty 的内部结构。但是通常来说,使用 Vert.x 提供的高层次 API 会更有利于你编写代码,同时又不会有性能上的损失,相比较 原生 Netty来说。

Vert.x 不会强制要求任何包或者构建环境。因为 Vert.x core 本身就是一个常规的 Jar 包,能够作为 jar 包(单个 jar 包已经包含了所有的依赖) 的方式被嵌入到应用之中,甚至可以在流行的组件框架和应用容器中部署使用。

由于 Vert.x 生来就是为了设计异步通信,因此相比较于 Java servlets 或者 java.net socket classes 这类同步的 API 来说,Vert.x 使用较少的线程就能处理更多的并发网络连接。Vert.x 对多种类型的应用都有用:高容量消息/事件处理、微服务、API 网关、包括为移动应用提供的 HTTP APIs 等等。Vert.x 及其相关生态为构建端到端响应式应用提供了各种技术工具。

尽管听起来 Vert.x 仅适用于要求苛刻的应用,但正如本手册将要展示的 Vert.x 对传统 Web 应用也同样适用。我们将会看到,代码看上去会相对比较容易理解,即便是处理突发的流量洪峰,采用 异步事件处理 方式编写的代码都能轻松处理。

最后但值得一提的是,Vert.x 支持多种流行的 JVM 语言:Java、 Groovy、Scala、Kotlin、JavaScript、Ruby 和 Ceylon。Vert.x 支持多语言的目标不仅仅是通过 API 的访问,而是确保每一种语言都可以采用其特有的语言特性、以符合语言习惯的方式来访问 API (例如:使用 Scala 的 futures 来替换 Vert.x 的 future)。Vert.x 也能很好地支持在一个应用中,采用同步的 JVM 语言来开发不同的技术模块。

Vert.x 核心概念

在 Vert.x 中有两个需要掌握的核心概念:

  1. 什么是 verticle

  2. event bus 如何使不同的 verticles 之间通信

线程和编程模型

很多网络库和框架都依赖一种简单的线程策略:每一个网络客户端都被分配一个线程用于处理连接,并且在该连接在断开前,会一直负责处理客户端的请求。使用 Servlet 或者 由 java.iojava.net 包编写的网络程序都是这种类型。尽管这种 同步I/O 线程模型的代码相对简洁容易理解,但系统线程开销极大,在高负载的情况下,操作系统内核 仅在线程调度 上就会耗费大量时间。在大量并发请求的时候,可扩展性极差。在这种情况下,我们需要转向 异步I/O ,Vert.x 在这方面提供了坚实的基础。

Vert.x 中部署的单元被称作 Verticle 。Verticle 是基于 事件循环 来处理到来的事件,事件可以是接收网络缓冲、计时事件或者来自其它 Verticle 的消息。在异步编程模型中,事件循环是非常典型的一类:

event loop

每个事件都应在 合理时间 内得到处理,不应该阻塞事件循环。这意味着当在事件循环中执行的时候, 线程阻塞 操作不应该被响应,就像在处理图形用户接口(例如,卡住 Java 或者 Swing 界面,去处理一个很慢的网络请求)的时候一样。在本手册的后面将会看到,Vert.x 提供了许多在事件循环外来处理阻塞操作的机制。当发现事件循环中正在处理一个 耗时太长 事件时,Vert.x 会在日志中发出警告。为了匹配应用相关的需求,这个特性也是可以配置的(例如:当应用运行在比较慢的 Iot ARM 主板上的时候)。

每一个事件循环都运行在线程上。默认情况下,一个 CPU 核心线程上运行着2个事件循环。直接结果就是一个常规的 Verticle 将始终在同一个线程上处理事件,因此无需使用线程协调机制来调整 Verticle 的状态(例如:Java class fields)。

Verticle 可以进行一些配置(例如:证书、网络地址等等),并且能够被部署多次:

verticle threading config

传入的网络数据将会接收线程收到,并以事件的方式传递给相应的 Verticle 处理。当一个 Verticle 作为一个网络服务器被部署多次时,事件将会采用轮询方式被分发给 Verticle 实例,好处在于有利于在处理大量并发网络请求时最大化 CPU 的利用率。最后,Verticle 只有简单的 开始 和 结束 的生命周期,并且 Verticle 可以部署其它的 Verticle 。

事件总线

在 Vert.x 中,Verticle 将代码组织成可部署的单元。Vert.x 事件总线 是不同的 Verticle 之间通过异步消息传递进行通信的主要工具。例如,假定我们有一个 Verticle 正在处理 HTTP 请求,另外一个 Verticle 负责管理数据库访问。事件总线允许 HTTP Verticle 发送请求给数据库 Verticle 来执行 SQL 查询,并将结果返回给 HTTP Verticle:

event bus

事件总线允许传递任何类型的数据,尽管当下 JSON 是首选的交换格式 - 因为它允许以不同语言编写的 Verticle 进行通信,更一般地说, JSON 是一种流行的通用半结构化数据封装文本格式。

消息能以自由格式的字符串的方式发送到 目的地。事件总线支持下面几种通信模式:

  1. 点对点消息

  2. 请求 - 响应消息

  3. 发布 - 订阅广播消息

事件总线允许 Verticle 透明地通信,不仅仅限于在同一个 JVM 进程中:

  • 当打开网络集群模式的时候,事件总线是 分布式的 ,因此消息可以发送给在其它应用节点上运行的 Verticle

  • 当处理第三方应用通信时,可以通过简单的 TCP 协议来访问事件总线

  • 事件总线也可以通过通用的消息投递桥接器暴露(例如:AMQP、Stomp)

  • SockJS bridge 允许 Web 应用就像其它 Verticle 一样,基于事件总线在运行于浏览器中的 JavaScript 无缝地接收和发布消息


1. 请注意 在Web技术环境中广泛使用的术语"实时"不应该与特定操作系统的 硬件软件 的实时相混淆。