本章要点
学习任何框架都需要首先了解框架的组成部分有哪些,每个组成部分完成什么功能,各个组成部分是如何关联,如何相互协作的,每个组成部件对外提供的API有哪些。在了解和掌握框架的组成后,就可以使用框架提供的API编写各个组成组件,并最终装配到一个完成具体业务功能的应用项目中。
本章详细介绍Vert.x框架的总体结构,它的各个组成部分担当的职责,以及它的运行机制。
通过本章的学习,能对Vert.x有一个整体的理解,为将来使用vert.x编程打下良好的基础。
Vert.x工作在JVM的一个进程内,一台服务器主机可以有多个Vert.xJVM进程,每个vert.x进程称为一个vert.x实例(Vert. x Instance),所有vert.x组件的部署和运行都在此实例管理之下。
Vert.x内部的详细结构如图2-2所示。
在服务器端 JavaScript编程中可以使用如下代码取得vert.x实例对象。
var vertx-require(vertx");
在即将发布的最新版V3.0中,不需要编程获得Vert.x实例对象,而是自动获得,直接用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。
Verticle是vert.x应用基本的编程单元,类似于Java应用的 class类,HTML应用的页面,Vert.x应用的功能都由 Verticle编程实现。目前还没有合适的中文名称来命名Verticle,我们不妨就使用其英文名称,或称之为工件。
Verticle可以使用不同的编程语言实现,并且这些由不同编程语言实现的 Verticle可以封装到一个模块中,进而部署到一个Vert.x应用中。但是实际项目开发中,尽可能使用单一的语言编程,不要使用过多的语言,导致项目难以维护。Vert.x应用最佳编程语言是javaAscript。关于 Verticle详细的信息和编程,本书第4章将进行详细讲解。
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所示。
当一个普通 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的根本
原因。
Vert.x的事件总线工作模式,对熟悉了传统应用开发的程序员来讲确实需要一个适应的过程,对于广大的分析和设计人员也是巨大的挑战。因为使用传统的面向对象的分析和设计理念与方法,尤其是UML成果的表达都是对象间的依赖和关联,而Vert.x中所有的Verticle都是无关联的,非耦合的,这也是未来异步应用开发者需要解决的问题之1。
Verticle的运行在Vert.x实例单线程内,通过 Event Loop进行运行调度。 Verticle之间的相互调用和数据传递,都通过在事件总线( Event bus)对象上发送事件和接收事件来完成。
vert.x的事件总线对象通过事件的传输实现 Verticle之间的调用和数据传递,每种事件在事件总线上都有一个地址( address), Verticle通过在事件总线上对指定地址发送事件,并在事件中附带动作参数和数据参数,实现对其他 Verticle的调用。
Verticle同时在事件总线上对指定地址注册事件监听处理器,完成事件的接收和处理,
事件总线的工作原理如图2-7所示。
事件总线不但在一个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所示。
Vert.x事件总线上支持3种模式的事件发布机制。
(1)发布/订阅模式( Publish/ Subscribe)
此模式支持同时向多个 Verticle接收者发送事件。此模式的工作原理如图2-9所示。
**发布/订阅模式一般用于信息的发布,**如股票行情的显示、期货交易的数据显示、通知通
实时发布,实现向多个连接客户实时同步发送信息。
(2)点对点模式(per-to-peer)
此模式下,事件只能有一个接收 Verticle,此模式的工作原理如图2-10所示。
此模式用于日常的业务管理,如登录处理,增加、修改、删除业务数据处理等,实际项目
中业务层 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);
再一个解决方案就是每个 Verticle定义自己的局部变量,保存需要共享的数据,当一个Verticle更新的一个共享数据后,其要向其他 Verticle发布更新消息事件,其他 Verticle接收到更新事件后,更新自己的局部变量值。如果访问共享数据的 Verticle过多,其事件的发送和处理需要较大的处理量,也会导致系统性能的下降。
为解决共享问题,vert.x提供两种类型的共享数据对象,一个是类似 Java map类型的容器结构,另一个是类似Java语言的Set容器结构的共享对象。具体创建这两种容器对象的个数没有限制。在一个Vert.x的实例内,所有的 Verticle都可以对这两种类型的共享容器对象进行读写,现数据的共享,并且数据保存在Vert.x实例的缓存中,系统的性能会有极大的改善。通常在开发企业级应用时,可以将登录用户的信息保存这些共享容器对象内,实现多个Verticle高效的数据共享方式。在以后的 Verticle编程时会详细介绍共享数据的读写操作。
Vert.x应用开发中根本没有必要使用这些动态页面技术,通过延伸到客户端的事件总线,在客户端内使用 JavaScript可以实现与服务器端 Verticle的实时双向数据通信,结合客户端的各种 JavaScript框架,如 jQuery、 jQueryUI、 jQuery EasyU、Dojo等,可以实现丰富多彩的数据显示、表单提交等功能,并且Vert.x在性能上要全面超越以上各种动态页面技术,且能适应移动互联网众多客户的高并发连接请求。这也开启了未来淘汰JSP、ASP
JSF、ASP.NET动态页面技术的序幕,让我们开发者拭目以待
如何在现有的旧浏览器中支持 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应用开发实例教程》吕海东、张坤 编著