Vert.x

Vert.x是一个运行在JVM上的多语言、非阻塞式、事件驱动的应用程序框架

一些显著的特性包括:

  • 多语言支持:Vert.x类似于Node.js,但你可以使用JavaScript,Ruby,Groovy,Java或者Python等来编写你的应用组件(只要能再JVM上运行的常见语言,都可以直接编写基于Vert.x的应用),甚至你可以在一个单独的应用程序中混合使用数种编程语言,一句话概括就是Vert.x让不同的语言可以更容易的在JVM上协作。
  • 异步编程:简单的类似actor的并发模型:Vert.x允许你以单线程方式来编写你的所有代码,你的程序都是基于异步事件且通信无阻塞,这可以避免你可能遇到的大部分多线程编程陷阱(你不需要关注线程间的调用、同步、死锁等繁琐的事情,不再会有synchronized,volatile和显示锁,简单的帮你实现一个非常不简单的事情)。Vert.x提供了一系列的异步API,你在Vert.x中所要做的大部分事情就是设置event handlers(事件处理函数),例如你设置了一个handler用来接受来自TCP socket的数据,当数据到达时这个handler 就会被调用。你也可以是设置handler来接受来自事件总线(event bus)的消息,也可以接受HTTP请求和响应,当一个连接关闭时触发,或者一个定时触发,这都是贯彻Vert.x API的普遍模式,使用传统的同步API,线程可能会阻塞API操作,一旦阻塞线程变无法工作了,一个很好的例子就是从socket中读取数据,当代码等待socket上的数据到达时将不会做其他的事情,这意味着如果我们想要支持一个百万级别的并发连接将需要百万的线程,这肯定是无法接受的。当然作为异步编程代码可读性肯定会很差,特别是当你需要处理来自多个event handler的结果时可能会非常难编程,可能会有很多很多的嵌套,处理这种情况我们可是使用mod-rx-vertx模块(这个模块使用了RxJava)以更好的方式来组织你的事件流。
  • 高扩展:Vert.x继承了JVM的优点,可以无缝的扩展可用内核,无需手动的fork多个服务器,它可以很容易的处理服务模块之间的进程通信,做到水平扩展。
  • 高并发:Vert.x有一个简单的异步编程模型(actor模型),非常适用于非阻塞的应用程序,它可以用最小数量的操作系统线程来达到10s、100s甚至百万级别的并发连接(Vert.x内置了和操作系统内核数量相等的线程数来处理verticles,这样你就可以不必使用更多的线程就可以实现一个完美的非阻塞应用)。Vert.x保证一个verticle实例只会被一个线程同时被执行,这对开发者来说好处多多,因为你可以以单线程的方式来编写代码,同时多个单线程的verticle实例会同时执行(取代多线程方式执行多个verticle实例),相互之间通过发送消息来通信。这让Vert.x酷似actor模型,但也有不同之处,比如Verticles比Actors更加粗粒化。
  • 分布式消息:Vert.x包含一个跨越客户端和服务端的分布式的事件总线(event bus),它不仅能够提供点对点的通信,还提供了发布/订阅机制,通过它你的应用组件可以很轻松的进行相互通信,甚至在浏览器端event bus也被集成到了JavaScript中,这样你就可以构建一个real-time实时的web应用(特别是推送类应用web交互)。通过bus传递的事件可以是任意对象,但是如果你使用JAVA对象,你会遇到序列化和载入类的问题,这种情况下使用JSON来作为事件消息是比较靠谱的。需要注意的是事件是短暂的,它们没有存储在任何一种稳定的存储介质上,因此在传输的过程中可能会丢失,这和JMS不同,JMS强调可靠性,而vert.x的事件总线则把重点放在性能上。
  • 便捷健壮:Vert.x具有健壮性,便捷性但是却不简单,最小化它的配置和模块。
  • 模块化:如何让单独的模块可以分开部署?一种是使用OSGi,但是还未普及,另一种是在一台服务器上部署不同的WAR文件,并让它们通过SOAP来通信,这比较复杂也会带来很大的性能负载,而Vert.x包含了一个非常强劲的模块系统(module),以及公共的模块注册机制(集成了maven功能,你可以将你的代码打包成一个module,然后发布到私服上),所以你可以很简单的重复使用,以及和其他人分享Vert.x的模块。Vert.x中的模块拥有分离的classloader,所以可以视为一个真正的单独的组件,使用合适的模块化方法,你可以把大型系统分解为更小的部分,在vert.x中模块化的概念是基于消息的,而消息又提供了更多优势,这样系统便会仅仅依赖消息而不是依赖于调用特地的方法,可以让你达到松散的耦合。
  • 嵌入式开发和热重部署:Vert.x可以嵌入到你现有的Java应用程序中,vert.x的热重部署机制会让你的开发更加简单,但是还没有相关的插件支持.

基本概念

  • Verticle Vert.x的代码执行包,它可以用JS、Ruby等多语言来编写,在同一个Vert.x实例中可以同时执行多个Verticle,一个应用可能由多个Verticle组成,他们被部署到不同的网络节点上,彼此之间通过在Vert.x的事件总线(event bus)上交换信息来通信。对于具体的verticle可以直接从命令行启动,但是通常会将它打包成modules。
  • Module Vert.x应用程序一般是由一到多个modules组成的,Modules包含了多个verticles,这些verticle可能是由不同的语言来编写的。Modules可以被二次封装和重复使用。 Modules可以包装成任意maven或二进制包依赖,可以发布到vert.x模块注册中心。 Vert.x的模块系统支撑了一个由Vert.x管理社区的生态系统。
  • Vert.x实例 Verticles是运行在一个Vert.x实例上的,一个单独的Vert.x实例是运行在它自己的JVM实例上的。同一时刻可以有多个Verticles运行在同一个Vert.x实例上。 多个Vert.x实例可以同时运行在同一个JVM下,也可以运行在不同的JVM下。这些实例可以以集群的方式来配置,彼此之间通过分布式的event bus来通信。
  • Event Loops 在内部,一个Vert.x实例管理了一小撮线程,这些线程数量是同服务器上有效的CPU核数相匹配的。我们称这些线程为事件循环(Event Loops),它们将围绕是否有事件需要处理做循环,如果有需要处理的事件将会交给适合的handler来处理。这些被循环监控的事件可能是从一个socket读取数据,一个定时器被触发,或者一个HTTP请求被接受。 当一个标准的verticle实例被部署以后,服务器会为这个实例分配一个事件循环(Event Loop),用来处理相关的事件,后续相关的处理也会使用这个线程来处理。当然,因为有可能在同一时间有成百上千的verticles在运行,所以一个单独的Event Loop将会同一时间分配给多个verticles。 我们也称这为多反应堆模式即mulit-reactor pattern。它类似反应堆模式reactor pattern,但是前者至少有一个event loop。 有一个黄金法则:不要阻塞event loop! 前面说过一个单独的event loop可能会服务于多个verticle实例,所以千万不要在你的verticle中阻塞event loop,如果你阻塞了它就意味着这个event loop无法将事件交付给任何其他的handler处理,那么你的程序将会处于停滞状态。所以一下的阻塞代码请不要出现:
    • 1、Thread.sleep()
    • 2、Object.wait()
    • 3、CountDownLatch.await()或者任何其他来自java.util.concurrent的阻塞操作
    • 4、在一个loop循环中spinning自旋
    • 5、执行一个长时间的计算操作
    • 6、调用一个可能会花费大量时间才完成的阻塞的第三方库操作,比如一个JDBC查询
  • 垂直工件 Worker Verticle 既然不能在一个verticle中编写阻塞代码,那么有替代方案么,这里就要介绍Worker模式的Verticles了。 在一个标准的verticle中你永远不能阻塞event loop,但是在我们处理业务时肯定不可避免的遭遇到阻塞场景,或者你真的需要进行一个长时间的计算,典型的例子就是调用一个类似JDBC的标准Java API。 你也可能想直接编写阻塞代码,例如,如果你想要写一个简单的WEB服务,而且你直达你不会有大量的流量,所以不需要扩展很多连接。 对于像上面的这些例子,Vert.x允许你将一个特殊的verticle实例作为一个worker verticle。这个worker verticle不同于标准的verticle,前者不需要分配一个Vert.x event loop线程,它是通过一个叫做worker pool的内部线程池来得到线程来执行的。 和标准的verticle一样,worker verticles也不会被多个线程同时执行,但是也有不同的地方,worcker verticles可以在不同的时间被不同的线程执行,而标准verticle总是会被同一个线程执行。 所以在一个worker verticle中,是允许存在可能会引起阻塞线程的操作的。 通过既支持标准的非阻塞verticle和阻塞worker verticle,Vert.x提供了多样的线程模式以便你能够为你的应用程序使用适当的方式。这比要么阻塞要么非阻塞的单一方式框架要来的实用的多。 需要提醒的是,当你使用worker verticle需要非常小心,比如如果你想要处理高并发的连接,阻塞方式最好少用,它不能做到并发水平扩展。
  • Shared data 虽然消息传递是相当有用,但对于各种类型的应用程序来说这种方式不一定总是最佳的方式。对于一些案例,通过提供一个共享的数据结构可能是更好的方案,在vert.x便是shared data(map和sets),它允许在相同的Vert.x实例中被不同的verticle实例直接访问(数据共享)。
  • API Vert.x提供一系列能直接被verticle调用的API,同时为每个vert.x支持的语言都提供了一份API。 Vert.x 提供2种API,一种是container api 一种则是core api。

  • Container API包含了一些类似下面的操作:
    • 部署和卸载verticles
    • 部署和卸载modules
    • 获取verticle配置
    • 日志功能
  • Core API提供下面一些相关的方法:
    • TCP/SSL 服务器端和客户端
    • HTTP/HTTPS 服务器端和客户端
    • WebSockets服务器端和客户端
    • 分布式的事件总线event bus
    • 一次性定时器和周期定时器
    • 字节操作
    • 流量控制
    • 文件系统访问
    • 共享的map和sets(shared data)
    • 访问配置
    • SockJS

Core

Vert.x core contains fairly low level functionality including support for HTTP, TCP, file system access, and various other features. You can use this directly in your own applications, and it’s used by many of the other components of Vert.x.

Vert.x core provides functionality for things like:

  • Writing TCP clients and servers
  • Writing HTTP clients and servers including support for WebSockets
  • The Event bus
  • Shared data - local maps and clustered distributed maps
  • Periodic and delayed actions
  • Deploying and undeploying Verticles
  • Datagram Sockets
  • DNS client
  • File system access
  • High availability
  • Clustering

Web

Vert.x-Web is a toolkit for writing sophisticated modern web applications and HTTP microservices.

Some of the key features of Vert.x-Web include:

  • Routing (based on method, path, etc)
  • Regular expression pattern matching for paths
  • Extraction of parameters from paths
  • Content negotiation
  • Request body handling
  • Body size limits
  • Cookie parsing and handling
  • Multipart forms
  • Multipart file uploads
  • Sub routers
  • Session support - both local (for sticky sessions) and clustered (for non sticky)
  • CORS (Cross Origin Resource Sharing) support
  • Error page handler
  • Basic Authentication
  • Redirect based authentication
  • Authorisation handlers
  • JWT based authorization
  • User/role/permission authorisation
  • Favicon handling
  • Template support for server side rendering, including support for the following template engines out of the box:
    • Handlebars
    • Jade,
    • MVEL
    • Thymeleaf
  • Response time handler
  • Static file serving, including caching logic and directory listing.
  • Request timeout support
  • SockJS support
  • Event-bus bridge
  • CSRF Cross Site Request Forgery
  • VirtualHost

Data access

Vert.x provides a few different asynchronous clients for accessing various data stores from your application. You don’t have to use these clients - you could use clients direct from the vendor if you prefer (e.g. MongoDB provide their own cool async and reactive clients), but these provide a simple async API which is available in various languages.

MongoDB Client

Mongo is a great match for persisting data in a Vert.x application as it natively handles JSON (BSON) documents.

  • Completely non-blocking
  • Custom codec to support fast serialization to/from Vert.x JSON
  • Supports a majority of the configuration options from the MongoDB Java Driver

JDBC client

This client allows you to interact with any JDBC compliant database using an asynchronous API from your Vert.x application.

Common SQL interface

The common SQL interface is used to interact with Vert.x SQL services.

You obtain a connection to the database via the service interface for the specific SQL service that you are using (e.g. JDBC/MySQL/PostgreSQL).

Redis client

This module allows data to be saved, retrieved, searched for, and deleted in a Redis. Redis is an open source, BSD licensed, advanced key-value store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets and sorted sets. To use this module you must have a Redis server instance running on your network.

Redis has a rich API and it can be organized in the following groups:

  • Cluster - Commands related to cluster management, note that using most of these commands you will need a redis server with version >=3.0.0
  • Connection - Commands that allow you to switch DBs, connect, disconnect and authenticate to a server.
  • Hashes - Commands that allow operations on hashes.
  • HyperLogLog - Commands to approximating the number of distinct elements in a multiset, a HyperLogLog.
  • Keys - Commands to work with Keys.
  • List - Commands to work with Lists.
  • Pub/Sub - Commands to create queues and pub/sub clients.
  • Scripting - Commands to run Lua Scripts in redis.
  • Server - Commands to manage and get server configurations.
  • Sets - Commands to work with un ordered sets.
  • Sorted Sets - Commands to work with sorted sets.
  • Strings - Commands to work with Strings.
  • Transactions - Commands to handle transaction lifecycle.

MySQL / PostgreSQL client

The Async MySQL / PostgreSQL Client is responsible for providing an interface for Vert.x applications that need to interact with a MySQL or PostgreSQL database.

Integration

Mail Client

Vert.x provides a simple SMTP mail client so you can send emails from your applications.

STOMP Client & Server

Vert.x provides an implementation of the STOMP protocol.

JCA Adaptor

Vert.x provides a Java Connector Architecture (JCA) adaptor which allows it to interoperate with any JavaEE application server.

TCP Eventbus Bridge

An eventbus bridge that lets you interact with Vert.x from any application thanks to a TCP socket.

Authentication and Authorisation

Vert.x provides simple APIs for auth in your applications. We also provide a few out of the box implementations.

  • Auth common Authentication means verifying the identity of a user.
  • Authorisation means verifying a user has an authority.
  • JDBC auth We provide an implementation of AuthProvider which uses the Vert.x JDBCClient to perform authentication and authorisation against any JDBC compliant database.
  • JWT auth
  • Shiro auth
  • MongoDB auth
  • OAuth 2

Reactive

Vert.x provides a couple of components to make your applications more reactive.

  • Vert.x Rx
  • Reactive streams
  • Vert.x Sync

Devops

Vert.x offers various component to keep your Vert.x application on track when running in production

  • Metrics using Dropwizard
  • Metrics using Hawkular
  • Shell
  • Docker
  • Stack Manager

Testing

Vert.x-Unit is an unit testing tool-kit especially design to work well with asynchronous code.

Clustering

Vert.x supports clustering and HA out of the box. Cluster group management is implemented in cluster managers which are pluggable. The default cluster manager uses Hazelcast.

  • Hazelcast
  • JGroups

Services

Vert.x services are a simple and effective way to encapsulate reusable functionality for use elsewhere. Services are deployed using a service identifier which decouples the user from details of the implementation.

  • Service Factories
  • Service Proxies
  • SockJS Service Proxies
  • Maven Service Factory
  • HTTP Service Factory

Cloud

  • Vert.x OpenShift Cartridge
  • Vert.x OpenShift Using DIY Cartridge

Advanced

Some of the more advanced or internal bits and pieces. You won’t normally use these directly in your own projects. They’re mainly stuff we use internally.

  • Codegen This is the magic that translates Java APIs into other languages.
  • Docgen Creates asciidoc and API documentation from in-source docs.
  • Codetrans More magic that translates code into other languages (we mainly use this for translating examples)
  • Bridge Common This project contains the data object used by all eventbus bridges.
  • Distro This project builds the various Vert.x distributions.
  • Web-site This is the repository that creates this web-site.
Written on April 12, 2016