Vert.x学习笔记-Verticle原理解析
- 一、设计理念:事件驱动的组件化模型
- 二、生命周期管理
- 三、部署方式与策略
- 四、通信机制:事件总线(Event Bus)
- 五、底层实现原理
- 六、典型应用场景
- 七、Verticle与EventLoop的关系
- 1、核心关系:一对一绑定与线程亲和性
- 2、EventLoop的核心机制
- 3、Verticle与EventLoop的交互流程
- 4、性能优化与最佳实践
- 5、典型场景与架构设计
- 总结
Verticle 是 Vert.x 框架的核心抽象,它通过事件驱动和非阻塞 I/O 模型,将业务逻辑封装为独立的执行单元。以下从设计理念、生命周期、部署方式、通信机制和底层实现五个维度深入解析其原理。
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。
点击跳转到网站
一、设计理念:事件驱动的组件化模型
-
核心定位
Verticle 类似于 Actor 模型中的“参与者”,但更轻量。每个 Verticle 代表一个独立的业务逻辑单元(如 HTTP 服务、数据库操作),通过事件总线(Event Bus)与其他组件解耦。 -
非阻塞与异步
Vert.x 基于事件循环(Event Loop)驱动,所有 Verticle 的 I/O 操作均通过回调或 Promise 异步完成,避免线程阻塞。例如,HTTP 请求处理通过requestHandler
注册回调函数实现。 -
多语言支持
Verticle 可由 Java、JavaScript、Ruby 等语言编写,Vert.x 通过类加载器动态实例化不同语言的 Verticle。
二、生命周期管理
Verticle 的生命周期分为五个阶段,通过 AbstractVerticle
的钩子方法实现:
-
实例化(Instantiation)
Vert.x 通过VerticleFactory
创建 Verticle 实例,支持从类名、文件路径或已有实例部署。 -
部署(Deployment)
调用deployVerticle()
触发部署,返回Future<String>
用于跟踪部署状态。部署时指定配置参数(如 Worker 模式、实例数)。 -
启动(Start)
覆盖start(Promise<Void>)
方法执行初始化逻辑(如启动 HTTP 服务)。异步启动需调用startFuture.complete()
标记完成。 -
运行(Execution)
Verticle 在分配的线程(Event Loop 或 Worker 线程)中持续处理事件,如定时任务、消息消费。 -
停止(Stop)
覆盖stop(Promise<Void>)
释放资源(如关闭数据库连接)。Vert.x 自动撤销子 Verticle,无需手动清理。
三、部署方式与策略
-
编程式部署
// 部署 Java Verticle vertx.deployVerticle(new MyVerticle(), ar -> {if (ar.succeeded()) {String deploymentId = ar.result();} });// 部署多实例(负载均衡) DeploymentOptions options = new DeploymentOptions().setInstances(4); vertx.deployVerticle("com.example.MyVerticle", options);
-
声明式部署
通过 JSON 配置文件定义 Verticle 参数,结合命令行工具运行:vertx run my-verticle.js -conf config.json
-
Worker 模式
通过DeploymentOptions.setWorker(true)
将 Verticle 部署到 Worker 线程池,适用于阻塞操作(如文件 I/O):DeploymentOptions options = new DeploymentOptions().setWorker(true); vertx.deployVerticle("com.example.BlockingVerticle", options);
四、通信机制:事件总线(Event Bus)
-
核心概念
- 地址(Address):字符串标识的通信通道(如
news.feed
)。 - 消息(Message):包含
body
(数据)和headers
(元数据)。
- 地址(Address):字符串标识的通信通道(如
-
通信模式
- 发布/订阅(Publish/Subscribe)
// 发布消息到地址 vertx.eventBus().publish("news.feed", "Breaking News!");// 订阅地址 vertx.eventBus().consumer("news.feed", message -> {System.out.println("Received: " + message.body()); });
- 点对点(Point-to-Point)
使用send()
替代publish()
,确保消息仅被单个消费者处理。
- 发布/订阅(Publish/Subscribe)
-
跨实例通信
事件总线支持集群模式,通过-cluster
参数启动 Vert.x 实例,实现跨节点的消息路由。
五、底层实现原理
-
线程模型
- Event Loop 线程池
默认大小为2 * CPU 核心数
,每个 Verticle 实例绑定一个线程,通过vertx.getOrCreateContext()
获取上下文,确保事件在正确线程处理。 - Worker 线程池
独立线程池处理阻塞任务,避免 Event Loop 阻塞。
- Event Loop 线程池
-
并发控制
- 单线程执行:Standard Verticle 的代码在同一线程串行执行,天然线程安全。
- 多线程 Worker:通过
DeploymentOptions.setMultiThreaded(true)
允许单个 Verticle 实例并发处理事件(需自行处理线程安全)。
-
性能优化
- 零拷贝:Netty 底层实现减少数据复制。
- 背压(Backpressure):通过
Pause/Resume
机制控制数据流速,防止资源耗尽。
六、典型应用场景
- 微服务架构
每个服务封装为 Verticle,通过事件总线通信,实现服务解耦。 - 高并发处理
利用 Event Loop 线程池处理海量连接(如 40 万并发连接)。 - 阻塞任务隔离
将数据库查询、文件 I/O 等操作交给 Worker Verticle,避免主线程阻塞。
七、Verticle与EventLoop的关系
1、核心关系:一对一绑定与线程亲和性
-
Standard Verticle的EventLoop绑定
- 单线程执行模型:每个Standard Verticle实例部署时,Vert.x会为其分配一个固定的EventLoop线程。所有事件处理(如HTTP请求、定时任务)均由该线程串行执行,天然避免线程安全问题。
- 示例:
部署后,vertx.deployVerticle(new MyStandardVerticle()); // 默认绑定EventLoop
MyStandardVerticle
的所有代码(包括start()
和事件处理器)均在同一个EventLoop线程中运行。
-
Worker Verticle的隔离机制
- 阻塞任务处理:Worker Verticle运行在独立的Worker线程池中,与EventLoop线程严格隔离。需通过
DeploymentOptions.setWorker(true)
显式配置:DeploymentOptions options = new DeploymentOptions().setWorker(true); vertx.deployVerticle("com.example.BlockingVerticle", options);
- 线程安全约束:单个Worker Verticle实例同一时间仅由一个线程执行,但不同时间可能切换线程,需开发者自行处理线程安全。
- 阻塞任务处理:Worker Verticle运行在独立的Worker线程池中,与EventLoop线程严格隔离。需通过
2、EventLoop的核心机制
-
非阻塞事件循环
- 事件驱动模型:EventLoop通过轮询事件队列(如网络I/O、定时器)触发事件处理,采用回调或Promise模式避免阻塞。
- 高性能保障:默认线程数为CPU核心数×2(如8核CPU创建16个EventLoop线程),单节点可支撑数十万并发连接。
-
上下文绑定与任务调度
- Context封装:每个Verticle绑定一个
Context
对象,封装其执行上下文(如线程、资源)。通过vertx.getOrCreateContext()
可获取当前Context。 - 任务提交:
- 非阻塞任务:直接通过
context.runOnContext()
提交到EventLoop线程。 - 阻塞任务:通过
context.executeBlocking()
委托给Worker线程池:context.executeBlocking(future -> {// 阻塞操作(如数据库查询)future.complete(result); }, res -> {// 处理结果 });
- 非阻塞任务:直接通过
- Context封装:每个Verticle绑定一个
3、Verticle与EventLoop的交互流程
-
事件分发
- 监听与触发:EventLoop持续监听Verticle关联的事件(如HTTP请求)。事件到达时,通过Context将任务调度到绑定的EventLoop线程。
- 示例:HTTP请求到达后,EventLoop调用注册的请求处理器:
vertx.createHttpServer().requestHandler(req -> {req.response().end("Hello from EventLoop!"); }).listen(8080);
-
生命周期管理
- 启动阶段:Verticle的
start()
方法在绑定的EventLoop线程中执行,完成资源初始化(如启动HTTP服务)。 - 停止阶段:
stop()
方法在同一线程执行,释放资源(如关闭数据库连接)。
- 启动阶段:Verticle的
4、性能优化与最佳实践
-
避免阻塞EventLoop
- 禁止操作:同步I/O、长时间计算、
Thread.sleep()
等。 - 后果:阻塞EventLoop会导致事件积压,系统吞吐量骤降。
- 禁止操作:同步I/O、长时间计算、
-
合理配置线程池
- EventLoop线程数:通过
-Dvertx.eventLoopPoolSize
调整(默认CPU核心数×2)。 - Worker线程池:通过
-Dvertx.workerPoolSize
配置,建议根据阻塞任务负载调整。
- EventLoop线程数:通过
-
异步API优先
- 使用场景:数据库查询、HTTP客户端调用等I/O操作。
- 示例:异步Redis客户端:
RedisClient client = RedisClient.create(vertx, config); client.get("key", res -> {if (res.succeeded()) {System.out.println(res.result());} });
-
多语言支持与线程安全
- 跨语言调用:Verticle可由Java、JavaScript等语言编写,但需确保事件处理符合线程模型(如JavaScript Verticle默认运行在EventLoop线程)。
- 数据传递:Verticle间通过EventBus通信时,建议传递不可变对象(如JSON),避免线程安全问题。
5、典型场景与架构设计
-
高并发Web服务
- 方案:Standard Verticle处理HTTP请求,结合异步API(如WebClient)实现非阻塞I/O。
- 优势:单线程EventLoop处理数千并发连接,资源占用极低。
-
实时数据处理
- 方案:通过EventBus订阅消息,Standard Verticle处理实时数据流,Worker Verticle执行复杂计算。
- 示例:物联网设备数据采集与聚合:
// Standard Verticle订阅数据 eventBus.consumer("sensor.data", message -> {processData(message.body()); });// Worker Verticle执行聚合 context.executeBlocking(future -> {aggregateData(rawData);future.complete(); }, res -> {eventBus.publish("aggregated.data", result); });
-
微服务架构
- 方案:每个服务封装为Verticle,通过EventBus实现跨节点通信,结合Cluster Manager实现集群扩展。
- 优势:服务解耦、动态伸缩,支持分布式事务与服务发现。
Vert.x通过Verticle与EventLoop的协同设计,实现了高性能、可扩展的异步编程模型。Standard Verticle与EventLoop的一对一绑定确保了非阻塞任务的线程安全,而Worker Verticle和Worker线程池则提供了阻塞任务的隔离处理能力。开发者需严格遵循线程模型规范,避免阻塞EventLoop,并合理配置线程池以优化系统性能。通过结合事件总线、异步API和分布式集群,Vert.x能够轻松应对高并发、实时性和微服务场景的挑战。
总结
Verticle 通过事件驱动、非阻塞 I/O 和松耦合通信,构建了高性能、可扩展的应用架构。其生命周期管理、灵活部署和线程模型设计,使得开发者能够专注于业务逻辑,而无需处理底层并发复杂性。
Vert.x学习笔记-什么是Handler
spring中的@EnableAutoConfiguration注解详解
Vert.x学习笔记-什么是EventLoop
Vert.x学习笔记-EventLoop与Context的关系
相关文章:

Vert.x学习笔记-Verticle原理解析
Vert.x学习笔记 一、设计理念:事件驱动的组件化模型二、生命周期管理三、部署方式与策略四、通信机制:事件总线(Event Bus)五、底层实现原理六、典型应用场景七、Verticle与EventLoop的关系1、核心关系:一对一绑定与线…...
Cobra CLI 工具使用指南:构建 Go 语言命令行应用的完整教程
Cobra CLI 工具使用指南:构建 Go 语言命令行应用的完整教程 在 Go 语言开发中,构建功能强大的命令行界面(CLI)应用是常见需求。Cobra 作为 Go 生态中最受欢迎的 CLI 库,凭借其灵活的设计和丰富的功能,成为…...

jQuery和CSS3卡片列表布局特效
这是一款jQuery和CSS3卡片列表布局特效。该卡片布局使用owl.carousel.js来制作轮播效果,使用简单的css代码来制作卡片布局,整体效果时尚大方。 预览 下载 使用方法 在页面最后引入jquery和owl.carousel.js相关文件。 <link rel"stylesheet&qu…...

不连网也能跑大模型?
一、这是个什么 App? 你有没有想过,不用连网,你的手机也能像 ChatGPT 那样生成文字、识别图片、甚至回答复杂问题?Google 最近悄悄发布了一个实验性 Android 应用——AI Edge Gallery,就是为此而生的。 这个应用不在…...

强化学习鱼书(10)——更多深度强化学习的算法
:是否使用环境模型(状态迁移函数P(s’|s,a)和奖 励函数r(s,a,V))。不使用环境模型的方法叫作无模型(model-free)的方法,使用环境模型的方法叫作有模型(model-based&#…...

K8S上使用helm部署 Prometheus + Grafana
一、使用 Helm 安装 Prometheus 1. 配置源 地址:prometheus 27.19.0 prometheus/prometheus-community # 添加repo $ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts "prometheus-community" has been added…...
十四、【测试执行篇】让测试跑起来:API 接口测试执行器设计与实现 (后端执行逻辑)
@[TOC](【测试执行篇】让测试跑起来:API 接口测试执行器设计与实现 (后端执行逻辑)) 前言 测试执行是测试平台的核心价值所在。一个好的测试执行器需要能够: 准确解析测试用例: 正确理解用例中定义的请求参数和断言条件。可靠地发送请求: 模拟真实的客户端行为与被测 API…...

Java面试八股--07-项目篇
致谢:2025年 Java 面试八股文(20w字)_java面试八股文-CSDN博客 目录 1、介绍一下最近做的项目 1.1 项目背景: 1.2 项目功能 1.3 技术栈 1.4自己负责的功能模块 1.5项目介绍参考: 1.6整体业务介绍: 1.8后台管理系统功能: 1.8.1后台主页: 1.8.2 商品模块: 1.8…...

MCP架构全解析:从核心原理到企业级实践
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「storms…...

从0到1认识EFK
一、ES集群部署 操作系统Ubuntu22.04LTS/主机名IP地址主机配置elk9110.0.0.91/244Core8GB100GB磁盘elk9210.0.0.92/244Core8GB100GB磁盘elk9310.0.0.93/244Core8GB100GB磁盘 1. 什么是ElasticStack? # 官网 https://www.elastic.co/ ElasticStack早期名称为elk。 elk分别…...
快速了解GO+ElasticSearch
更多个人笔记见: (注意点击“继续”,而不是“发现新项目”) github个人笔记仓库 https://github.com/ZHLOVEYY/IT_note gitee 个人笔记仓库 https://gitee.com/harryhack/it_note 个人学习,学习过程中还会不断补充&…...

定制开发开源AI智能名片驱动下的海报工厂S2B2C商城小程序运营策略——基于社群口碑传播与子市场细分的实证研究
摘要 本文聚焦“定制开发开源AI智能名片S2B2C商城小程序”技术与海报工厂业务的融合实践,探讨其如何通过风格化海报矩阵的精细化开发、AI技术驱动的用户体验升级,以及S2B2C模式下的社群裂变机制,实现“工具功能-社交传播-商业变现”的生态…...

【Unity开发】控制手机移动端的震动
🐾 个人主页 🐾 阿松爱睡觉,横竖醒不来 🏅你可以不屠龙,但不能不磨剑🗡 目录 一、前言二、Unity的Handheld.Vibrate()三、调用Android原生代码四、NiceVibrations插件五、DeviceVibration插件六、控制游戏手…...
JAVA中的注解和泛型
目录 JAVA注解介绍 概念 注解的本质 4种标准元注解 自定义注解 泛型介绍 泛型的定义 JAVA泛型 泛型方法( ) 泛型类( ) 类型通配符 类型擦除 JAVA注解介绍 概念 注解是 JDK 5.0 引入的一种元数据机制,用来对代码进行标注。它不会影…...

Cesium快速入门到精通系列教程二:添加地形与添加自定义地形、相机控制
一、添加地形与添加自定义地形 在 Cesium 1.93 中添加地形可以通过配置terrainProvider实现。Cesium 支持多种地形数据源,包括 Cesium Ion 提供的全球地形、自定义地形服务以及开源地形数据。下面介绍几种常见的添加地形的方法: 使用 Cesium Ion 全球地…...
汽车零配件---ecu开发工厂学习
ecu成品制作工艺流程 一、PCB 设计与制作(打板) 工艺流程步骤 需求分析与电路设计 根据 ECU 功能(如发动机控制、变速箱控制)确定所需芯片(如 MCU、传感器接口芯片)、外围电路(如电源、通信接…...

python学习打卡day43
DAY 43 复习日 作业: kaggle找到一个图像数据集,用cnn网络进行训练并且用grad-cam做可视化 浙大疏锦行 数据集使用猫狗数据集,训练集中包含猫图像4000张、狗图像4005张。测试集包含猫图像1012张,狗图像1013张。以下是数据集的下…...

Microsoft Word使用技巧分享(本科毕业论文版)
小铃铛最近终于完成了毕业答辩后空闲下来了,但是由于学校没有给出准确地参考模板,相信诸位朋友们也在调整排版时感到头疼,接下来小铃铛就自己使用到的一些排版技巧分享给大家。 注:以下某些设置是根据哈尔滨工业大学(威…...

windows安装多个版本composer
一、需求场景 公司存在多个项目,有的项目比较老,需要composer 1.X版本才能使用 新的项目又需要composer 2.X版本才能使用 所以需要同时安装多个版本的composer二、下载多个版本composer #composer官网 https://getcomposer.org/download/三、放到指定目…...

【办公类-22-05】20250601Python模拟点击鼠标上传CSDN12篇
、 背景需求: 每周为了获取流量券,每天上传2篇,获得1500流量券,每周共上传12篇,才能获得3000和500的券。之前我用UIBOT模拟上传12篇。 【办公类-22-04】20240418 UIBOT模拟上传每天两篇,获取流量券,并删除内容_csdn 每日任务流量券-CSDN博客文章浏览阅读863次,点赞18…...

贪心算法应用:边着色问题详解
贪心算法应用:边着色问题详解 贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致结果是全局最优的算法策略。边着色问题是图论中的一个经典问题,贪心算法可以有效地解决它。下面我将从基础概念到具体实现,全…...
【蓝桥杯】包子凑数
包子凑数 题目描述 小明几乎每天早晨都会在一家包子铺吃早餐。他发现这家包子铺有 NN 种蒸笼,其中第 ii 种蒸笼恰好能放 AiAi 个包子。每种蒸笼都有非常多笼,可以认为是无限笼。 每当有顾客想买 XX 个包子,卖包子的大叔就会迅速选出若干…...

ck-editor5的研究 (2):对 CKEditor5 进行设计,并封装成一个可用的 vue 组件
前言 在上一篇文章中—— ck-editor5的研究(1):快速把 CKEditor5 集成到 nuxt 中 ,我仅仅是把 ckeditor5 引入到了 nuxt 中,功能还不算通用。 这一篇内容将会对其进行设计,并封装成可复用的 vue 组件&…...

Java-redis实现限时在线秒杀功能
1.使用redisson pom文件添加redisson <!--redisson--><dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.23.4</version></dependency> 2.mysql数据库表设…...

simulink mask、sfunction和tlc的联动、接口
这里全部是讲的level2 sfunction(用m语言编写),基于matlab 2020a。 1.mask的参数操作 1)mask通过set_param和get_param这2个函数接口对mask里面定义的Parameters&Dialog的参数的大部分属性进行读写,一般是Value值…...

VMWare安装常见问题
如果之前安装过VMWare软件,只要是 15/16 版本的,可以正常使用的,不用卸载!!! 如果之前安装过,卸载了,一定要保证通过正常的渠道去卸载(通过控制面板卸载软件)…...
set_property LOC约束
##下列指令是用于清除自带GT CELL相关的LOC约束,或者覆盖 ##你需要把IP中自带的GT cell相关的LOC约束清除掉,或者覆盖掉 ##以下命令可以用来覆盖GT_CHANNEL的LOC约束, 在这条命令之后执行你自己的physical constraint: ##GT的channel的相关管脚有两种设计…...

【北邮 操作系统】第十二章 文件系统实现
一、文件的物理结构 1.1 文件块、磁盘块 类似于内存分页,磁盘中的存储单元也会被分为一个个“块/磁盘块/物理块”。很多操作系统中,磁盘块的大小与内存块、页面的大小相同 内存与磁盘之间的数据交换(即读/写操作、磁盘I/0)都是以“块”为单位进行的。即…...

Docker 插件生态:从网络插件到存储插件的扩展能力解析
Docker 容器技术以其轻量、快速、可移植的特性,迅速成为构建和部署现代应用的核心工具。然而,尽管 Docker Engine 自身功能强大,但在面对多样化的生产环境和复杂业务需求时,仅靠核心功能往往无法满足所有场景。 例如,跨主机的容器网络通信、异构存储系统的持久化数据管理…...

WordPress搜索引擎优化的最佳重定向插件:进阶指南
在管理网站时,我们经常需要调整网页地址或修复错误链接。这时,通过重定向不仅能有效解决这些问题,还能显著提升网站在搜索引擎中的排名。对于熟悉基础重定向插件的用户来说,一些功能更强大的工具可以帮助你更全面地管理网站&#…...