1.13.始源之地:Vert.x集成

考槃在涧,硕人之宽。独寐寤言,永矢弗谖。——佚名《国风·卫风》

「壹」Vert.x子项目

    Vert.x从3.x开始,就将曾经的工具箱重新进行了模块化设计,您可以在官方文档中看到很多相关子项目(2.x中的模块化完全是灾难级的):

    可能您会困惑,如果使用Zero,是不是就用不了这些相关的子项目了呢?答案是否定的,在Zero中您可以开发连接点 程序,有了它您可以直接和Vert.x提供的官方子项目集成(类似MySQL Client ),也可以和Zero中设计的标准插件集成。Zero中的标准插件主要源起于实战,有些插件是Vert.x的子项目未提供的,而两种插件的引入使用统一的模式,Zero的玩法不一定最炫,但铁定会让您眼前一亮!

ifx全称为infix,翻译为“中缀、插入”。

    Zero的子项目vertx-ifx中包含了目前支持的所有插件,这些插件的开发流程都遵循了本章节的思路,其中还包含类似Neo4jElasticSearch、** Excel**等官方不支持的集成,一旦您学会了本章完整的开发思路,那么您的项目自然如虎添翼。目前的插件如下表:

项目名
类型
含义

zero-ifx-es

Zero

ElasticSearch功能模块。

zero-ifx-excel

Zero

Excel导入导出功能模块(可直连Jooq功能模块)。

zero-ifx-feign

Zero

Feign功能模块。

zero-ifx-history

Zero

系统读写日志历史数据库(第二库)。

zero-ifx-iqiy

Zero

Qiy爱奇艺视频客户端。

zero-ifx-neo4j

Zero

Neo4j的非SQL数据库图库集成模块。

zero-ifx-shell

Zero

命令行工具抽象框架。

zero-ifx-sms

Zero

阿里云手机短信服务。

zero-ifx-native

Vertx

MySQL和PgSQL客户端专用集成(标准)。

zero-ifx-mongo

Vertx

Mongo数据库客户端。

zero-ifx-redis

Vertx

Redis功能模块。

    表格中的类型标识了该插件是Vert.x集成插件还是Zero的集成插件,本章不去剖析部分复杂的插件用法,后续会有单独的章节讲解,主要告诉读者:

  1. 如何在Zero中开发这种插件项目以及连接点程序(如何扩展)。

  2. 如何在您的Agent/Worker组件中使用这些扩展。

    这些插件的设计以单一职责为原则,项目本身比较小,代码不多,目的也是让您在选择时可直接根据所需按需引入

1.1. MySQL孤岛

1.1.1. 插件分析

    Zero中使用了MySQL,但由于动态建模的影响,并没有使用Vert.x中的MySQL Client,而是将Jooq标准化了。有关MySQL Client 的引入目前存在于zero-ifx-native项目中,它只包含了一个代码文件(读者无需自己开发):

    把它称为孤岛,就是因为整个zero-ifx-native项目中只有这个文件,而这个文件却包含了很多巧思,也包含了Zero插件结构的骨架代码。     接口io.vertx.up.plugin.Infix是Zero中为第三方功能模块设计的插件接口,实现该接口的类必须包含两个基本规范:

  1. 这是一个插件,必须被@Plugin(io.vertx.up.annotations.Plugin)注解。

  2. 这个插件必须包含初始化静态方法(根据Vertx实例初始化插件):

    Zero中的插件连接点实现了池化客户端,如MySqlInfix构造完成后的完整结构如下:

    默认情况下,您获取的客户端引用直接和ZERO_MYSQL_POOL绑定,Zero中和Vert.x集成的所有Infix目前的版本都没扩展第二客户端 ,是否扩展最终取决于您的实际项目需求,上边代码中的插件您可以直接使用。

1.1.2. 插件使用

    本章讲解如何在Zero中使用Infix插件。

    第一步:先在您的项目pom.xml文件中引入该插件的依赖,由于Zero中所有vertx-ifx子项目都已经定义过版本,所以可省略<version>标签:

    第二步:在项目中书写以下配置文件(以MySQL为例):

    上述三个文件内容如下:

vertx.yml片段

vertx-mysql.yml内容如:

vertx-inject.yml内容如:

    第三步:完成了上述配置后,您就可以直接在您的Agent或Worker组件中使用SQLClient了,参考下边代码:

Agent代码

    发送请求到地址/hi/mysql/client,您可以得到如下响应:

    从响应结果可以知道,实际clientAclientB引用了同一个对象,在整个环境中,都指向了ZERO_MYSQL_POOL绑定的SQLClient 。上边注解部分的代码使用了依赖注入(Worker和Agent组件中代码相同),如果不使用依赖注入,则您可以使用下边代码获取:

    值的注意的是在Vert.x的3.9.8中(不知哪个版本开始),原来的vertx-mysql-postgresql-client项目已经被废弃 了,那是不是本章内容无用了呢?其实不然,虽然废弃了原来的SQLClient,但还引入了MySQLClient以及PgSQLClient,只是分得更细了,后续版本中我会更新Zero的Vert.x集成部分的代码,将native 拆成不同的子项目来对待,但整体思路以及玩法和本章节的内容保持高度一致,读者就不用去困惑了。

javax.inject.infix包中的注解为保留注解,后续版本扩展时会根据不同功能执行拓展,如果是您自己定义的插件,直接使用标准的io.vertx.up.annotations.Plugin即可。

1.2. Mongo

    前一个章节讲解了zero-ifx-native项目的内容、用法、以及Zero中插件的开发和使用思路,本章节使用同样的思路来分析zero-ifx-mongo ,这个项目是从最早的手机实战中延生出来的子项目,当初使用了MongoDB作为数据库。回到前文思路中,先看看MongoInfix的写法:

    熟悉的味道、熟悉的配方,有了前一个章节的基础,理解这部分代码轻车熟路。它的基本配置如下:

Maven中引入

vertx-mongo.yml

具体配置项可参考官方的MongoOptions。

vertx-inject.yml

    这部分的代码就不详细叙述了,参考下边代码段:

    如此,您就可以直接在Zero的Agent和Worker组件中直接使用Mongo客户端了,若想要直接在工具类中使用,则可参考:

1.3. Redis

    Zero目前版本只支持三个和Vert.x集成项目的子项目:

  • zero-ifx-native:MySQL/PgSQL

  • zero-ifx-mongo:MongoDB

  • zero-ifx-redis:Redis

    本章我们分析一下Redis的基础用法,Redis的插件在Zero中是最复杂的,它支持的功能如下:

  1. 提供了和Mongo类似的RedisInfix实现Redis的异步访问。

  2. 引入Jedis客户端新增同步访问(适用于旧场景)。

  3. 可替换Vert.x Web中的Session存储介质,将web-session存储在Redis中替换原生存储。

    还是回到本章重点Infix的代码:

    在Redis部分,除了Vert.x在集成中引入了新版的Redis异步访问部分,还包含了Jedis的同步访问部分(同步不支持JSR330),二者结合使得功能更加完善,基本代码如下:

Maven引入

vertx-redis.yml

vertx-inject.yml

    使用部分参考下边代码段:

    那么到这里,整个Zero中目前牵涉的三个和Vert.x的集成就告一段落,根据本章节的内容,读者可以很快和MySQL、Mongo、Redis集成,并去详细体会Zero中Infix 插件的详细内容,后续版本中,我会根据实际项目需求将部分客户端内容标准化,当前版本则提供给读者自己发挥。最后强调一点,本章节所有的Infix实现代码都是Zero已经提供的代码,使用时不需额外开发。

挑战:最后留一个挑战,您可以尝试自己去开发一个Infix彻底理解Zero中的插件结构。

「贰」内置插件

    除了第一章节表格中枚举的Zero子项目以外,Zero中还有部分内置的Infix插件,本章主要讲解一个特殊的内置插件MapInfix ;和Redis项目插件一样,Zero为了兼容部分遗留系统或老系统,通常都会开同步异步双通道来做新旧的桥接,如果只支持异步不支持同步,虽然看起来更加Vert.x,但对很多项目的迁移将是灾难。

2.1. MapInfix

    Vert.x中的SharedData数据结构是类似Hash表的一种结构,它不仅仅可以在本地环境使用,也可以在集群环境使用,Zero Extension中用来存储临时授权码 就使用了该结构,为了同时支持同步异步,Zero提供了一个特殊的SharedClient,该客户端架构和MySQLClient以及MongoClient类似(Vert.x没有),而本章的MapInfix 就是用来访问该Client的插件

    MapInfix的完整代码如下:

    由于该插件是内置,所以基本使用代码中不需Maven的额外引入,直接可用。

vertx-shared.yml

vertx-inject.yml

    使用代码段如:

2.2. SharedClient

2.2.1. 结构综述

    由于当前插件的特殊性,SharedClient是Zero提供的接口,本小节简单讲解该接口中常用的API函数,该客户端的完整图示如下:

    每个SharedClient内部都包含了一个对应的同步引用(LocalMap)和异步引用 (AsyncMap)。由于Vert.x中的LocalMap不能在集群环境中跨环境使用,vertx-shared.yml 中的配置会让SharedClient选择内部实现模式,如果是异步则使用AsyncMap,如果是同步则使用LocalMap,且只能二选一。

    如果您要使用多个Map如何操作,您可以使用下边的API函数(图中的切换)。

    上述API可以让您直接切换客户端引用,一旦切换后您就可以操作第二个SharedClient,Zero中保证每个名字下只有一个SharedClient实例,实现池化单件结构。

2.2.2. 最小单元

    SharedClient最小操作单元为io.vertx.up.atom.Kv——该数据结构存储了一个key = value的完整信息,包括键名、键值等,该类的完整实现代码如下:

    该结构和Map.Entry类似,但比Map.Entry更简化,Zero内部很多地方都使用了该数据结构。

2.2.3. 操作类API

    同步所有API定义如下:

    异步所有API定义如下:

    简单汇总:

  1. 异步类型的API全部参考Vert.x子项目中的Client架构量身打造,且每个API都是@Fluent的,由于参考了Vert.x子项目,所以并不包含Future模式。

  2. 这些API比Map常规API唯一多出来的两个功能是:

    1. 存储到Map中的**项(key = value)**可按秒计时,如果超时则Zero会自动移除该项。

    2. 可使用一次读取的函数,该项被消费后就直接从数据结构中移除。

2.3. Ux.Pool

    Ux.Pool是Zero提供的另外一个工具函数,它近似于Ux.JwtUx.Jooq ,提供了Zero中常用的函数(可以理解成SharedClient的Future模式的封装)。使用它的初始化代码如:

    实际上边代码片段最终返回了UxPool类型,看看它开放的所有API定义:

    该工具和SharedClient中的API维持了高度统一,所以只是转换了异步函数,转换成了Future 的返回结果以方便使用Zero的开发人员,最后提供一份内部使用临时授权码部分的调用代码给您参考:

「叁」小结

    本文主要给您讲解了Zero如何和Vert.x中的子项目做集成,并且通过集成部分给您讲解了Zero中的插件Infix架构,可能有部分读者会困惑,为什么不直接在SharedClient 中提供Future模式?这和Vert.x中的子项目有关,为了和Vert.x中的大部分子项目高度统一,所以才提供了原生风格类似的异步API(全@Fluent模式结构),而扩展部分的API才会提供Future模式,简单说SharedClient几乎是参考Vert.x中子项目的各种Client仿造的。

    目前Zero提供的工具类中,主要包含如下:

工具类
类型
含义

Ux.Jooq.on(daoClass)

UxJooq

和Jooq生成的VertxDAO绑定简化数据库访问。

Ux.Join.on()

UxJoin

实现跨表访问,JOIN类型的读取、搜索、统一。

Ux.Pool.on()

UxPool

和SharedData绑定可调Future模式的异步API。

Ux.Jwt

UxJwt

和安全中Jwt相关的核心工具类。

Ux.Job.on()

UxJob

获取任务管理器,启动、停止、恢复后台任务专用。

Last updated