第2章 Vertx架构组成

本章要点

  • Vert.x的总体架构。
  • Vert.x组成部件对象。
  • ·Vert.x模块的工作原理。
  • ·vert. x Verticle的工作原理
  • ·Vert.x的事件总线工作原理。

学习任何框架都需要首先了解框架的组成部分有哪些,每个组成部分完成什么功能,各个组成部分是如何关联,如何相互协作的,每个组成部件对外提供的API有哪些。在了解和掌握框架的组成后,就可以使用框架提供的API编写各个组成组件,并最终装配到一个完成具体业务功能的应用项目中。
本章详细介绍Vert.x框架的总体结构,它的各个组成部分担当的职责,以及它的运行机制。
通过本章的学习,能对Vert.x有一个整体的理解,为将来使用vert.x编程打下良好的基础。

2.1Vert.x的总体架构


vert.x是一个用于编写下一代异步、可伸缩、并发性企业级应用的服务器端框架,在JVM上实现了一个与Node.js类似,但却全面超越Node.js的应用开发服务器平台。当今移动互联网飞速发展,移动客户端和社交网络等成为新趋势,作为一个新崛起的企业级应用框架, vert.x必须适应这种发展趋势,提供支持分布式、可伸缩、可群集的各种服务器技术,如 Http Web、TCP服务、 WebSocket服务、数据推送、消息驱动等
Vert.x内部提供以上技术的实现组件、APIl、协议等,以及与操作系统交互的各种进程和线程管理模块。 图2-1展示了Vert.x框架的总体结构,在下面的各节中逐步分解各个组成部分,并进行详细的介绍。Vert.x建立在Java虚拟机JVM基础之上,使用Java语言编写,并提供了对各种语言的编程API,如 JavaScript、Java、Ruby等。
第2章 Vertx架构组成_第1张图片

Vert.x工作在JVM的一个进程内,一台服务器主机可以有多个Vert.xJVM进程,每个vert.x进程称为一个vert.x实例(Vert. x Instance),所有vert.x组件的部署和运行都在此实例管理之下。
Vert.x内部的详细结构如图2-2所示。
第2章 Vertx架构组成_第2张图片

2.2vert.x实例Instance


Vert.x框架的核心是Vert.x实例,所有的 Verticle都运行在Vert.x实例中。Vert.x启动后,Vert.x框架会在JVM的进程内创建一个实例线程,并在此线程内创建Vert.x实列对象。
一个Vert.x实例可以同时并发运行多个 Verticle, 在一个主机上可以同时运行多个vert.x实例,也可以在一个分布式环境中部署多个实例,组成实例的集群,用以满足超大并发用户的访问处理。
Vert.x应用中实例与其他组件的关系如图2-3所示。

第2章 Vertx架构组成_第3张图片
在服务器端 JavaScript编程中可以使用如下代码取得vert.x实例对象。

var vertx-require(vertx");

在即将发布的最新版V3.0中,不需要编程获得Vert.x实例对象,而是自动获得,直接用Vert.x对象即可。

2.3vert.x容器Container


在vert.x实例中管理模块和 Verticle组件部署的对象是Vert.x容器,通过容器对象可以通过编程方式部署模块和 Verticle。
在Vert.x的应用开发中,通常编写一个主启动 Verticle,在主 Verticle内取得Vert.x器对象,再通过容器对象的部署方法,部署项目中的其他模块,如图2-3所示的应用组成。
Vert.x应用的设计原则就是**只有一个主启动 Verticle,**其余的 Verticle都要按照功能类封装到不同的模块中。程序2-1演示的是一个使用 Javascript编写的主启动 Verticle
程序2-1:app.js//主启动 Verticle
//视频监控系统服务器端总启动程序
//取得Vert.x容器对象

var container- require(" vertx/container");
//载入 Web server模块
container deploy Module("io. vertx-mod-web-server 20.0-final",(
port:8080,
host:"192.168.1.100",
bridge: true
inbound permitted: L
I address: 'city. oa. meeting business user. add',
I address: 'city. oa. meeting. dao. user')
//载入DAO层模块
address:'city oa. meeting. db'y
container deploy Module("com. city, oa. meeting-dao-mysql");
I address: 'city. oa. meeting. dao. room'y
//载人人员 Business层模块
I address: 'city. oa. meeting business room. list'y
container deploy Module("com. city. oa. meeting"business-user"):
address: 'city. oa. meeting. dao. meeting)
//载入会议室 Business层模块
I address: 'city. oa. meeting business. meeting. list')
container deploy Module("com. city. oa. meeting-business"room"):
I address: 'city. oa. meeting. dao. meetinguser'y
//载入会议 Business层模块
I address: 'city. oa. meeting business. meetinguser userlist',
container deploy Module("com. city. oa. meeting-bi
I address: 'city. oa. meeting. videoshow'y
//载入会议 Business层模块
address: 'city. oa. meeting. session-manager')
containerdeploy Module("com. city. oa. meeting-business-meetinguser"):
I address: 'city. oa. meeting. session-cleanup'

实际Vert.x应用开发中推荐使用 JavaScript语言开发,其简单、方便和快捷特点,尤其是 JavaScript内置的函数回调和闭包功能是vert.x异步模式编程的最佳选择,而使用Java编程量要大大超出 JavaScript,并且异步编程不是Java的强项;

当编写数据库操作的 Verticle时,可以选择Java实现,并结合 Spring和 Hibernate框架完成复杂的CRUD功能,如表关联操作等,最终将得到的数据操作结果以JSON形式封装到事件中,通过 Event bus发送给其他使用 Javascript编写的 Verticle。

2.4Vert.x工件Verticle

Verticle是vert.x应用基本的编程单元,类似于Java应用的 class类,HTML应用的页面,Vert.x应用的功能都由 Verticle编程实现。目前还没有合适的中文名称来命名Verticle,我们不妨就使用其英文名称,或称之为工件。

Verticle可以使用不同的编程语言实现,并且这些由不同编程语言实现的 Verticle可以封装到一个模块中,进而部署到一个Vert.x应用中。但是实际项目开发中,尽可能使用单一的语言编程,不要使用过多的语言,导致项目难以维护。Vert.x应用最佳编程语言是javaAscript。关于 Verticle详细的信息和编程,本书第4章将进行详细讲解。

2.5模块 Module


Vert.x应用开发中不要单独编写和部署大量独立的 Verticle,造成系统的结构混乱,难以维护,而是将 Verticle根据功能的分类打包到不同的模块中,最终按模块来部署所有的Verticle,模块本身不能运行,实际运行的还是模块中的 Verticle。
vert.x中的模块可以引用其他的模块,也可以被其他模块引用。模块一般打包成zip玉缩文件,可以发布到 Maven仓库供其他项目下载和引用,而 Verticle无法实现这种机制,只能通过拷贝和粘贴方式移植到其他项目中,实际应用开发中一定要把 Verticle封装到模块里。
Vertx官方提供了模块的注册和检索机制,在网址http://modulereg.vertx.io/上有

2.6事件循环 Event Loop


Vert.x启动后,在JVM的进程中创建一个vert.x实例对象,每个Vert.x实例都管理个小的线程集合, 每个线程针对服务器CPU上的一个处理器内核,每个线程都实现了1个事件循环, 这个事件循环称为 Event Loop。当部署一个Vert.x应用实例(又称为Verticle)时,服务器会选择一个事件循环分配给该实例。接下来针对该实例的任务都会通过该线程进行分配。由于在某一时刻可能会有成千上万个 Verticle在运行,因此在同一时刻会将单个事件循环指定给多个 Verticle。

vert.x实例启动后,会处于一个无限循环的事件监测处理过程中,并有一个称为 Event Loop的对象负责事件的监测,每个 Event Loop都在一个单独的线程内。
Vert.x实例会自动创建一个 Event Loop的线程池,并根据主机CPU内核数,自动确定 Event Loop的线程个数,每个线程执行一个 Event Loop

如在一个采用 Intel Xeon e7 8837 8核 CPU的服务器上运行Vert.x,则自动创建8个 Event Loop线程,并保存到线程池中,总的并发处理能力可达40万个连接请求,这是其他传统架构的服务器产品,如 Java EE、MS.NET等根本无法实现的,它们要达到类似的处理能力,至少需要十几台这样 的服务器,由此可见Vert.x的并发处理的卓绝能力。

Event Loop能确保事件在循环中轮回,例如在TCP编程时,它会确认 socket是否有数据可读事件,如果有,Vert.x将调用相应的 Verticle定义的事件处理器。 Event Loop的工作原理如图2-6所示。
第2章 Vertx架构组成_第4张图片

当一个普通 Verticle部署到vert.x实例中时, Vert.x容器会自动将Verticle关联到个 Event Loop线程中。以后此 Verticle的所有工作完全由此 Event Loop进行分发。而Worker verticle部署时,不会与 Event Loop关联,而是在单独的线程池中,与 Event loop的线程池并发存在,都在Vert.x实例的管理之下。

因为一个 Event Loop线程要服务众多的 Verticle实现并发的连接处理,所以Vert.x应用开发最需要强调的是所有普通 Verticle都要运行在异步、非阻塞模式下,通过回调方式接收并处理 Event Loop派发的事件,不能阻塞 Event Loop线程,否则 Event Loop会无法进行事件的派发工作,导致所有的 Verticle不能进行事件处理,导致应用处于停顿状态,无法响应用户的请求。

使用 JavaScript编写 Verticle时问题不大,关键是使用Java编写普通 Verticle时要注
意,一定不能在Java方法内部执行如下操作
(1)Thread. sleep()
(2)Object. waitO()
(3)无限循环
(4)需要长时间的算法计算。
(5)调用其他工作在阻塞模式的对象方法,如JDBC数据库操作,文件IO读写。

如果以上情况确实无法避免,要将 Verticle部署为 Worker verticle,让其运行在自己单
独的线程池内,不会阻塞 Event Loop线程,这也是vert.x提供 Worker verticle的根本
原因。

2.7事件总线 Event bus


vert.κ中 Verticle的工作是完全独立的,不能像传统的Java程序那样直接调用其他对象的方法,因此 Verticle之间是完全松耦合的。这种松耦合的设计极大地提高了Vert.x应用的可维护性,当修改一个 Verticle的方法代码时,不会影响任何其他的 Verticle。

Vert.x的事件总线工作模式,对熟悉了传统应用开发的程序员来讲确实需要一个适应的过程,对于广大的分析和设计人员也是巨大的挑战。因为使用传统的面向对象的分析和设计理念与方法,尤其是UML成果的表达都是对象间的依赖和关联,而Vert.x中所有的Verticle都是无关联的,非耦合的,这也是未来异步应用开发者需要解决的问题之1。

Verticle的运行在Vert.x实例单线程内,通过 Event Loop进行运行调度。 Verticle之间的相互调用和数据传递,都通过在事件总线( Event bus)对象上发送事件和接收事件来完成。

vert.x的事件总线对象通过事件的传输实现 Verticle之间的调用和数据传递,每种事件在事件总线上都有一个地址( address), Verticle通过在事件总线上对指定地址发送事件,并在事件中附带动作参数和数据参数,实现对其他 Verticle的调用。

Verticle同时在事件总线上对指定地址注册事件监听处理器,完成事件的接收和处理,
事件总线的工作原理如图2-7所示。
第2章 Vertx架构组成_第5张图片

事件总线不但在一个Vert.x实例内实现Ⅴ erticle之间的事件传递,而且可以实现分布式结构,即事件总线可以延伸到另一个Vert.x实例,实现复杂的分布式vert.x应用,这是大型应用系统必不可少的能力,如大型的电子商务网站、微信服务器、数据推送平台、云计算平台等。事件总线甚至延伸到Web客户端浏览器内部,Web客户端内的 JavaScript程序通过事件总线与服务器端的Ⅴ erticle的相互调用,实现客户端和服务器双向的事件和数据传输,可以实现与 WebSocket功能相同的实时Web系统( Real Time Web Application-RTWP)。比Websocket更先进的特点是客户端之间可以通过 Event Bus实现直接通信,不必像Websocket同时需要有 Client端和 Server端,而且需要完成复杂的连接验证握手过程。分布式事件总线的工作原理如图2-8所示。
第2章 Vertx架构组成_第6张图片
Vert.x事件总线上支持3种模式的事件发布机制。
(1)发布/订阅模式( Publish/ Subscribe)
此模式支持同时向多个 Verticle接收者发送事件。此模式的工作原理如图2-9所示。
第2章 Vertx架构组成_第7张图片

**发布/订阅模式一般用于信息的发布,**如股票行情的显示、期货交易的数据显示、通知通
实时发布,实现向多个连接客户实时同步发送信息。

(2)点对点模式(per-to-peer)
此模式下,事件只能有一个接收 Verticle,此模式的工作原理如图2-10所示。
第2章 Vertx架构组成_第8张图片
此模式用于日常的业务管理,如登录处理,增加、修改、删除业务数据处理等,实际项目
中业务层 Verticle调用DAO层 Verticle完成数据增加到数据库,此时只有一个 Verticle完
成功能即可,不需要群发功能。

(3)点对点请求回复模式( Peer-to- Peer request/ response)

此模式是在点对点模式基础上,增加由事件接收者在处理事件后向发送者回复处理信
息的功能
。在开发Vert.x业务应用时,此模式是使用最多的。如下代码演示了在事件总线
上注册事件处理器,在处理器内部采用点对点方法send发送数据库操作事件到下级接收者,
接收下级事件处理的回复结果 result,再通过 responder( result)把结果回复给上级发送者

var container= require('vertx/container')
ar event Bus=require('vertx/event bus)
//在 Event bus上定义系统管理员DAO接收事件
eventBus. register Handler("city. oa. lesson. dao. user", function(args, responder)
//在 Event bus上发送事件,并接收回复数据 result,
event Bus. send("city. oa. lesson. dao", sqlaction, function( result)
//将结果回复给发送者
responder( result);

2.8共享数据区(Shared Data area


Ⅴert.x中没有全局变量概念,各个 Verticle要访问共享的数据,可以采用数据库存储或外部文件读写方式完成,但是这些操作都会工作在阻塞模式,导致系统的性能严重下降。

再一个解决方案就是每个 Verticle定义自己的局部变量,保存需要共享的数据,当一个Verticle更新的一个共享数据后,其要向其他 Verticle发布更新消息事件,其他 Verticle接收到更新事件后,更新自己的局部变量值。如果访问共享数据的 Verticle过多,其事件的发送和处理需要较大的处理量,也会导致系统性能的下降。

为解决共享问题,vert.x提供两种类型的共享数据对象,一个是类似 Java map类型的容器结构,另一个是类似Java语言的Set容器结构的共享对象。具体创建这两种容器对象的个数没有限制。在一个Vert.x的实例内,所有的 Verticle都可以对这两种类型的共享容器对象进行读写,现数据的共享,并且数据保存在Vert.x实例的缓存中,系统的性能会有极大的改善。通常在开发企业级应用时,可以将登录用户的信息保存这些共享容器对象内,实现多个Verticle高效的数据共享方式。在以后的 Verticle编程时会详细介绍共享数据的读写操作。

2.9 Http服务器和客户端


Vert.x框架内部内置了HTTP服务器和HTTP客户端的组件API,可以非常简单地实现 Http Web服务器,实现Web内容的请求/响应。但此 Web server只能实现静态的HTML页面内容的响应,无法处理动态页面技术,如JSP、ASP、ASP.NET和PHP等,这些动态Web页面是由专门的服务器平台实现的。

Vert.x应用开发中根本没有必要使用这些动态页面技术,通过延伸到客户端的事件总线,在客户端内使用 JavaScript可以实现与服务器端 Verticle的实时双向数据通信,结合客户端的各种 JavaScript框架,如 jQuery、 jQueryUI、 jQuery EasyU、Dojo等,可以实现丰富多彩的数据显示、表单提交等功能,并且Vert.x在性能上要全面超越以上各种动态页面技术,且能适应移动互联网众多客户的高并发连接请求。这也开启了未来淘汰JSP、ASP
JSF、ASP.NET动态页面技术的序幕,让我们开发者拭目以待

2.10TCP服务器和客户端


Vert.x框架提供了 TCP Server和 TCP Client的实现API,开发者使用API可以非常简单且快捷地创建TCP服务器和TCP客户端,编程代码极其简洁,比起传统的Java和C#等语言要高效得多。**无论TCP服务器还是客户端都以非阻塞、异步和事件模式工作,提高了TCP服务的处理响应速度,且工作在单线程模式,避免了传统语言复杂的多线程处理机制。**在本书的第7章详细讲解了TCP服务器和客户端的编程与应用。

2.11 WebSocket服务器和客户端


Vert.x也内置了 WebSocket的服务器和客户端API,可以非常简单地实现 WebSocket的服务器端和客户端编程。对于使用支持HTML5浏览器的客户可以直接使用HTML5内置的 WebSocket aPi与服务器端 WebSocket Server通信,再通过事件总线与服务器端的 Verticle进行调用和数据传输,实现一个高效的分布式Vert.x企业级应用,其工作原理如图2-11所示。本书的后续章节会详细介绍 WebSocket服务器和客户端的编程。

第2章 Vertx架构组成_第9张图片

2.12 SockJS


vert.x框架还提供了 SockS的服务器端和客户端实现,可以使用 SockS实现服务器端或客户端的 WebSocket完全相同的功能。
现在 WebSocket已经成为HTML5的内置标准协议,实现客户端和服务器端高效和实时的双向的数据通信,使得Web应用跨入了实时应用领域。但是 WebSocket要求客户端浏览器支持HTML5标准,现在有大量的用户依然使用IE6、IE7或IE8等版本较低的浏览器,无法满足 WebSocket的要求。对这些用户如果Web应用使用HTML的 WebSocketAPI则无法运行,除非强制他们升级到支持HTML5的浏览器。

如何在现有的旧浏览器中支持 WebSocket、 SockS是最佳的解决方案。 SockS完全模拟了 WebSocket的API接口,实现了与 Websocket相同的双向实时通信,且可以工作在任何浏览器上,而且更重要的是 Web Socket无法通过企业内置的网关和防火墙,但 SockS却没有此限制,因此可以使用 Socks去替代 WebSocket,即使浏览器支持 WebSocket也应如
此,且 SockS编程要比 Websocket编程更简单。本书的第10章中详细讲解了 Socks的服务器端和客户端的编程与应用

本章小结
理解Vert.x总体架构组成,可以帮助我们更好地理解Vert.x应用各个组成部分,以及它们之间的关系,帮助我们在设计Vert.x的应用时,使用最佳的方案来实现最佳的性能,以满足客户的需求。本章简要且全面地介绍了Vert.x的架构组成,以及每个组成部件实现的

出自清华大学出版社《Vert.x应用开发实例教程》吕海东、张坤 编著

你可能感兴趣的:(Vert.x)