Vert.x学习笔记-什么是Verticle

什么是Verticle

Verticle是Vert.x应用中的基本编程单元,类似于Java中的Servlet、Pojo Bean或Akka中的Actor。它可以使用不同的编程语言实现,并且这些由不同编程语言实现的Verticle可以封装到一个模块中,进而部署到一个Vert.x应用中。Verticle可分为两种类型:标准VerticleWorker Verticle

  • 标准Verticle运行在Vert.x实例的事件循环线程中,当有事件发生时,在事件循环线程中回调Verticle实例中的event handler。
  • Worker Verticle在background workers线程池中执行,该线程池的大小缺省为40。

在事件循环线程上运行代码的基本原则是不能阻塞,并且代码的执行要足够快,但是在很多场合中确实难以避免会有阻塞的代码出现,vert.x提供了两种处理此类情况的方法: Worker VerticleexecuteBlocking方法

在这里插入图片描述

Worker Verticle

Worker Verticle是一种特殊的Verticle,它不是在事件循环线程上执行的,而是在专门的工作线程上执行的。工作线程来自一个特殊的工作线程池,开发人员也可以自定义工作线程池,将Worker Verticle部署给工作线程池。

Worker Verticle处理事件的方式与事件循环一致,只不过它可用人异常的时间来处理事件,Worker Verticle有以下两个特点:

  • Worker Verticle不会与某一个工作线程绑定,每一次运行可能是在不同的工作线程上的
  • 在任意的时刻,Worker Verticle只能被单个工作线程访问

Working Verticle和事件循环一样,都是单线程的,不同的地方是事件循环线程固定,Worker Verticle依附的线程不固定,每次可能会从线程池中找新的线程处理

Workder Verticle示例

public class WorkerVerticle extends AbstractVerticle{

  private final Logger logger = LoggerFactory.getLogger(WorkerVerticle.class);

  @Override
  public void start() {
    vertx.setPeriodic(10_000, id -> {
      try {
        logger.info("Zzz...");
        Thread.sleep(8000);
        logger.info("Up!");
      } catch (InterruptedException e) {
        logger.error("Woops", e);
      }
    });
  }

  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    DeploymentOptions opts = new DeploymentOptions()
      .setInstances(2) //创建两个实例
      .setWorker(true); //通过该标志来确定实例化的是否为Worker Verticle
    vertx.deployVerticle("xxx.WorkerVerticle", opts); //由于单次要创建两个实例,所以需要用全路径,如果只是创建单个Verticle就可以用new或者全路径
  }
}

在这里插入图片描述

从代码的执行结果也可以明显的看出来,每一次执行Worker Verticle的并不是固定的线程

在这里插入图片描述

executeBlocking方法

虽说Worker Verticle处理阻塞任务是一个非常优秀的方案,但是将阻塞代码全部抽取到Worker Verticle也不一定是完全合理的,这样可能会造成有非常多的执行很小功能的Worker Verticle,并且造成各个类无法形成一个独立的功能单元
运行阻塞式代码的另一种方式是通过Vertx类中的executeBlocking方法。该方法将一些阻塞的代码的执行转移到工作线程上,然后会以新事件的形式将结果发送回事件循环,执行流程如下图所示:

在这里插入图片描述

代码示例

public class Offload extends AbstractVerticle {

  private final Logger logger = LoggerFactory.getLogger(Offload.class);

  @Override
  public void start() {
    vertx.setPeriodic(5000, id -> {
      logger.info("Tick");
      vertx.executeBlocking(this::blockingCode, this::resultHandler);
    });
  }

  private void blockingCode(Promise<String> promise) { // promise对象用于返回结果的传递
    logger.info("Blocking code running");
    try {
      Thread.sleep(4000);
      logger.info("Done!");
      promise.complete("Ok!"); //promise完成并返回OK
    } catch (InterruptedException e) {
      promise.fail(e); //promise失败并返回异常
    }
  }

  private void resultHandler(AsyncResult<String> ar) { //在事件循环线程上处理阻塞代码的结果
    if (ar.succeeded()) {
      logger.info("Blocking code result: {}", ar.result());
    } else {
      logger.error("Woops", ar.cause());
    }
  }

  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle(new Offload());
  }
}
执行结果:

在这里插入图片描述

从上图的执行 结果就可以看出来,事件循环线程是固定不变的,但是执行executeBlocking方法的线程每次执行都可能是会变化的,并且是worker线程来进行执行的

默认情况下,当Vert.x有连续的多个executeBlocking方法时,会按照其调用顺序获得执行结果,executeBlocking方法还有一个带布尔参数类型的重载( Future<@Nullable T> executeBlocking(Handler<Promise> blockingCodeHandler, boolean ordered);),当该参数被设置为false时,任务执行完成后立即会将结果返回给事件循环,而不再遵循executeBlocking的调用顺序

在这里插入图片描述

Verticle 运行环境有Context

在这里插入图片描述
根据上图,我们来详细阐述一下Verticle相关的一些内容
Verticle对象本质是两个对象的组合,分别是:Vert.x和Context

  • Vertx对象: 该Verticle对象所属的Vert.x实例
  • Context对象: 记录Verticle上下文信息的实例,Verticle借助Context对象将事件分派到各个处理程序中

Vert.x实例提供了许多核心API来声明事件处理程序

Vert.x实例由多个Verticle共享,通常每个JVM程序只需要一个Vert.x实例

Verticle Context 可访问此Verticle的事件处理程序的执行线程,事件的来源有很多,比如数据库驱动程序、定时器程序、Http服务器程序,实际环境中,事件更多的是由其它线程触发的,例如Netty接收连接的线程
用户自定义的事件处理程序借助Verticle Context运行,Verticle Context使得我们可以在Verticle分配到的事件循环上执行事件处理程序,从而遵循Vert.x的线程模型。

Worker Verticle 与 Context

在这里插入图片描述

Worker Verticle事件处理程序由工作线程池中的某个工作线程执行,初次之外,Worker Verticle与事件循环的情况基本一致

Context

Verticle Context是Vert.x框架中的一种机制,用于管理和执行Verticle。当Vert.x提供一个事件的处理程序或调用Verticle的开始或停止的方法时,执行与Context相关联。在Verticle中,Context通常是事件循环 context绑定特定的事件循环线程。因此,对于这方面的执行总是发生在该完全相同的事件循环线程。在worker verticles和运行内嵌阻塞代码worker context的情况下将使用一个线程从worker线程池的执行关联。

Verticle的Context对象可以通过Vert.x的getOrCreateContext()方法获取,虽然Context对象几乎都是与Verticle相关联的,单实际上也可以在Verticle之外创建Context对象

  • 从Vert.x上下文环境中调用 getOrCreateContext()方法时,会返回当前的Context对象,如Verticle Context
  • 从非Vert.x上下文环境中调用getOrCreateContext()方法时,会创建一个新的Context对象
    下面的代码就是在非Vert.x上下文环境(JVM进程的主线程)中创建了Context
public class ThreadsAndContexts {

  private static final Logger logger = LoggerFactory.getLogger(ThreadsAndContexts.class);

  public static void main(String[] args) {
    createAndRun();
    dataAndExceptions();
  }

  private static void createAndRun() {
    Vertx vertx = Vertx.vertx();

    vertx.getOrCreateContext()
      .runOnContext(v -> logger.info("ABC")); //Lambda表达式在Vert.x上下文线程上执行

    vertx.getOrCreateContext()
      .runOnContext(v -> logger.info("123"));
  }

  private static void dataAndExceptions() {
    Vertx vertx = Vertx.vertx();
    Context ctx = vertx.getOrCreateContext();
    ctx.put("foo", "bar"); //上下文中可以保存任意的键值对

    ctx.exceptionHandler(t -> { //还可以声明一个异常处理程序
      if ("Tada".equals(t.getMessage())) {
        logger.info("Got a _Tada_ exception");
      } else {
        logger.error("Woops", t);
      }
    });

    ctx.runOnContext(v -> {
      throw new RuntimeException("Tada"); 
    });

    ctx.runOnContext(v -> {
      logger.info("foo = {}", (String) ctx.get("foo"));
    });
  }
}

当事件处理程序的实现跨越了多个类时,不妨用Context来携带数据,这样可能比较有用,否则,不如直接使用某个类的变量

如果某个事件处理程序可能抛出异常,则异常处理程序会变得非常重要。

在这里插入图片描述

桥接Vert.x线程和非Vert.x线程

在编写Vert.x代码的时候,通常不需要同Vert.x的Context打交道,但有一种情况例外:我们不得不使用某些第三方代码,这些代码内置了自己的线程模型,而我们又想让他们与Vert.x协同工作,下面是一个非常常用的解决方法:

public class MixedThreading extends AbstractVerticle {

  private final Logger logger = LoggerFactory.getLogger(MixedThreading.class);

  @Override
  public void start() {
    Context context = vertx.getOrCreateContext(); //提前获取Verticle的Context
    new Thread(() -> {
      try {
        run(context);
      } catch (InterruptedException e) {
        logger.error("Woops", e);
      }
    }).start();
  }

  private void run(Context context) throws InterruptedException {
    CountDownLatch latch = new CountDownLatch(1);
    logger.info("I am in a non-Vert.x thread");
    context.runOnContext(v -> { //runOnContext方法确保这些代码在事件循环线程上执行的
      logger.info("I am on the event-loop");
      vertx.setTimer(1000, id -> {
        logger.info("This is the final countdown");
        latch.countDown();
      });
    });
    logger.info("Waiting on the countdown latch...");
    latch.await();
    logger.info("Bye!");
  }

  public static void main(String[] args) {
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle(new MixedThreading());
  }
}

上面的代码创建了一个非Vert.x线程,先从Verticle上获取Context对象,再将它传递给非Vert.x线程,以便在非Vert.x线程环境中调用时间循环线程来执行一些代码

总结

  • Verticle是Vert.x应用程序中处理异步事件的核心组件
  • 事件循环负责处理异步的IO事件,它不应该被阻塞,也不应该用来处理耗时很长的任务
  • Worker Verticle可用于处理阻塞的IO事件,或者耗时的任务
  • 借助事件循环上下文,开发人员可以在代码中混合使用Vert.x线程和非Vert.x线程

在这里插入图片描述

拓展

下面是与Vert.x相关的一些其它博文链接,希望可以帮助大家进一步的了解Vert.x的相关知识

Vert.x学习笔记-异步编程和响应式系统

Vert.x学习笔记-什么是Vert.x

Vert.x学习笔记-Vert.x的基本处理单元Verticle

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/134660.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关系型数据库Redis安装与写入数据

文章目录 安装和初步选择数据库创建键值对数据类型 安装和初步 安装 Redis是开源的跨平台非关系型数据库&#xff0c;特点是占用资源低、查询速度快。 首先&#xff0c;在Github上下载最新发布的Redis-xxxx.zip压缩文件&#xff0c;下载之后解压&#xff0c;并将解压后的路径…

要找事做,我真怕被闲死

要找事做&#xff0c;我真怕被闲死 | 昨晚睡足了5个多小时&#xff0c;元气开始恢复&#xff0c;今晨6点钟醒来&#xff0c;如厕后无睡意&#xff0c;便窝在被子里闭目养神&#xff0c;同时想心事。 7点钟翻身起床穿衣洗刷后&#xff0c;烧瓶开水泡杯浓茶&#xff0c;打开电脑…

如何关闭Windows Defender(亲测可行!!非常简单)

一、背景 Windows Defender&#xff08;简称WD&#xff09;真的太讨厌了&#xff0c;经常给你报你下载的文件是病毒&#xff0c;且不说真的是不是病毒&#xff0c;它都不询问直接删。 另外聚资料显示WD还会不合时宜地执行扫描导致系统变慢&#xff08;不会在合适的、空闲的时…

Linux shell编程学习笔记24:函数定义和使用

为了实现模块化设计和代码重用&#xff0c;很多编程语言支持函数或过程&#xff0c;Linux shell也支持函数定义和调用。 Linux shell中的函数与其它编程语言很多有相似之处&#xff0c;也有自己独特之处。 1 函数的定义 1.1 标准格式 function 函数名(){语句或命令1……语句…

一步一步详细介绍如何使用 OpenCV 制作低成本立体相机

在这篇文章中,我们将学习如何创建定制的低成本立体相机(使用一对网络摄像头)并使用 OpenCV 捕获 3D 视频。我们提供 Python 和 C++ 代码。文末并附完整的免费代码下载链接 我们都喜欢观看上面所示的 3D 电影和视频。您需要如图 1 所示的红青色 3D 眼镜才能体验 3D 效果。它是…

操作系统 | proc文件系统

&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《操作系统实验室》&#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 目录结构 1. 操作系统实验之proc文件系统 1.1 实验目的 1.2 实验内容 1.3 实验步骤 1.4 实验…

Azure 机器学习 - 机器学习中的企业安全和治理

目录 限制对资源和操作的访问网络安全性和隔离数据加密数据渗透防护漏洞扫描审核和管理合规性 在本文中&#xff0c;你将了解可用于 Azure 机器学习的安全和治理功能。 如果管理员、DevOps 和 MLOps 想要创建符合公司策略的安全配置&#xff0c;那么这些功能对其十分有用。 通过…

HTML使用lable将文字与控件进行关联以获取焦点

先养养眼再往下看 注释很详细&#xff0c;直接上代码 <form action""><!-- 第一种方法:用id的方式绑定账户(文字)和输入框 --><label for"zhanghu">账户</label><input "text" id"zhanghu" name"ac…

Milvus Cloud ——Agent 的展望

Agent 的展望 目前,LLM Agent 大多是处于实验和概念验证的阶段,持续提升 Agent 的能力才能让它真正从科幻走向现实。当然,我们也可以看到,围绕 LLM Agent 的生态也已经开始逐渐丰富,大部分工作都可以归类到以下三个方面进行探索: Agent模型 AgentBench[4] 指出了不同的 L…

Azure 机器学习 - 使用受保护工作区时的网络流量流

目录 环境准备入站和出站要求方案&#xff1a;从工作室访问工作区方案&#xff1a;从工作室使用 AutoML、设计器、数据集和数据存储方案&#xff1a;使用计算实例和计算群集方案&#xff1a;使用联机终结点入站通信出站通信 方案&#xff1a;使用 Azure Kubernetes 服务方案&am…

ROS 学习应用篇(三)服务Server学习之Server

话题Topic是订阅器与发布器节点之间的&#xff0c;而服务则是客户端&#xff08;Client&#xff09;和服务器&#xff08;Server&#xff09;间的&#xff0c;前者是异步的&#xff0c;后者是同步的。而且话题是单项的不需要服务器上线&#xff0c;而服务是双向的。在开启服务之…

使用米联客FPGA开发板进行光口开发时遇到的问题总结

使用的开发板型号&#xff1a;米联客MA703FA&#xff0c; 实物图如下 FPGA型号为a35t 米联客提供的开发板资料中的FPGA型号为a100&#xff0c;所以要想使用开发板例程必须进行FPGA的重新选择。如下图 通过对开发板原理图的分析&#xff0c;例程代码不用做任何修改就可使用&am…

Linux常用命令——bzless命令

在线Linux命令查询工具 bzless 增强.bz2压缩包查看器 补充说明 bzless命令是增强“.bz2”压缩包查看器&#xff0c;bzless比bzmore命令功能更加强大。 语法 bzless(参数)参数 文件&#xff1a;指定要分屏显示的.bz2压缩包。 在线Linux命令查询工具

Pathways

信号通路signaling pathway-武汉华美生物 (cusabio.cn) 神经信号通路(Neuronal Signaling)--selleck.cn PI3K/Akt/mTOR信号通路 表观遗传 甲基化 免疫&炎症 酪氨酸蛋白激酶 血管生成 凋亡 自噬 内质网应激&UPR响应 JAK/STAT信号通路 MAPK信号通路 细胞骨架…

网络运维Day11

文章目录 if语句if单分支应用案例 if双分支应用案例 if多分支应用案例 for循环while循环案例 正则表达式基本正则Perl兼容的正则 综合练习总结 if语句 if单分支 if单分支的语法组成&#xff1a; if 条件测试;then 命令序列 fiif 条件测试then 命令序列 fi应用案例 判断用…

Linux学习教程(第二章 Linux系统安装)2

第二章 Linux系统安装 四、使用U盘安装Linux系统 前面章节介绍了如何通过虚拟机 VMware 安装 Linux 系统&#xff0c;而实际开发中&#xff0c;我们更多的是要将 Linux 系统直接安装到电脑上。 直接在电脑上安装 Linux 系统的常用方法有 2 种&#xff0c;分别是用光盘安装和用…

软件自动化测试平台

软件测试分类黑盒、白盒、功能、API、接口、压力测试和性能测试&#xff0c; 自动化测试平台是一种用于自动化执行软件测试过程的工具。 一、自动化测试平台-功能性 1. 接口自动化&#xff1a;对接软件的接口进行测试&#xff0c;验证接口的功能和性能。 2. Web 自动化&…

了解项目管理软件的功能和用途

数字化办公、无纸化办公的概念越来越火&#xff0c;项目管理软件也一跃成为了热门话题。项目管理软件到底什么&#xff1f;项目管理软件是不是项目团队才用得到&#xff1f;项目管理软件都能干什么&#xff1f;今天一篇文章让你对项目管理软件不再迷茫。 什么是项目管理软件&a…

优化编辑距离以测量文本相似度

一、说明 编辑距离是一种文本相似度度量&#xff0c;用于测量 2 个单词之间的距离。它有许多方面应用&#xff0c;如文本自动完成和自动更正。 对于这两种用例中的任何一种&#xff0c;系统都会将用户输入的单词与字典中的单词进行比较&#xff0c;以找到最接近的匹配项&#x…

Seata之TCC模式解读

目录 基本介绍 起源 概述 案例流程分析 TCC注意事项 空回滚 幂等 悬挂 具体使用 LocalTCC TwoPhaseBusinessAction 小结 基本介绍 起源 关于TCC的概念&#xff0c;最早是由Pat Helland于2007年发表的一篇名为《Life beyond Distributed Transactions:an Apost…