【源码分析】:从零拆解bs_worker的3层核心架构

第五篇:bs_worker 主流程

第一篇:Catalog 表管理

第二篇:cluster 集群管理

第三篇:bs_admin - 主流程

第四篇:bs_admin构建任务流程

前面介绍了bs-admin的主流程以及一个构建任务下发的流程,下一步会重点介绍bs_worker,bs-worker通过心跳下发的不同配置,实现不同的角色,主要包括:processor、builder、merger。

上图是build service的架构,主要包括几个角色:bs admin,processor,builder和merger。今天先重点介绍bs_worker的主流程。

服务工作节点:ServiceWorker

整个bs_worker的入口是ServiceWorker,他负责启动、管理和协调各种具体的"工人角色"(如构建器、处理器等),在启动的时候,完成3件事:

  1. 自身身份识别(分区ID (PartitionId))的识别。PartitionId 包含了工作节点的详细身份信息,例如它属于哪个应用、哪个版本、扮演什么角色等
  2. 根据角色创建对应的工作状态处理器(WorkerStateHandler),包括:
  • BuilderServiceImpl负责构建索引。
  • ProcessorServiceImpl负责数据预处理。
  • MergerServiceImpl负责合并索引分片。
  • TaskStateHandler 负责执行通用任务。
  • AgentServiceImpl 负责管理子进程。
  • BuildJobImpl 负责整个 Job 的构建流程。
  1. 创建心跳执行器,负责驱动整个工作流程
    根据3件事,我们分别介绍这3个重要概念。

分区ID

why need

在bs-worker中,每个 ServiceWorker 进程(在成为领导者后)都负责执行一个具体的、与数据分区相关的任务,我们需要有一个统一的方式来标识一个具体的实例。

what 核心职责

proto::PartitionId 是一个 Protobuf 消息结构,定义在 build_service/proto/BasicDefs.proto 文件中。它包含了构成一个唯一工作单元的关键信息。

ini 复制代码
enum RoleType {  
    ROLE_UNKNOWN = -1;  
    ROLE_PROCESSOR = 0;  
    ROLE_BUILDER = 1;  
    ROLE_MERGER = 2;  
    ROLE_JOB = 3;  
    ROLE_ALTER_FIELD = 4;  
    ROLE_TASK = 5;  
    ROLE_AGENT = 6;  
}  

enum BuildStep {  
    BUILD_STEP_FULL = 0;  
    BUILD_STEP_INC = 1;  
    NO_BUILD_STEP = 2;  
    BUILD_STEP_IDLE = 3; // inc processor not exist  
}  

// [from, to]  
message Range {  
    optional uint32 from = 1 [default = 0];  
    optional uint32 to = 2 [default = 65535];  
}  

// builder not require dataTable  
message BuildId {  
    optional string dataTable = 1;  
    optional uint32 generationId = 2;  
    optional string appName = 3;  
}  

message PartitionId {  
    optional RoleType role = 1 [default = ROLE_UNKNOWN];  
    optional BuildStep step = 2 [default = BUILD_STEP_FULL];  
    required Range range = 3;  
    required BuildId buildId = 4;  

一些示例:

how

解析的方法:

markdown 复制代码
1. 去掉第一个 .
2. 根据 . 切分,会有7个部分[0,1,2,3,4,5,6]
 - in1.1750125387.processor.full.0.65535.1-clustername-in1-a-5eb9
 - in1.1750125387.task.taskid-7516731375828913056-name-fullmerge-taskname-general-task.0.65535.in1-a-5a5a
3. role是第2,上面分别是 processor、task
4. task的话,第3是taskid
5. processor的话,第3个是 full or inc 的步骤表示
6. 4、5分别是 range 的 from、to
7. 如果是processor,6是taskid
8. 如果是其他,则是 cluster 

工作状态处理器 (WorkerStateHandler)

why need

worker 项目设计的目标是能够运行不同类型的构建相关任务:比如构建索引(Builder)、处理数据(Processor)、合并分片(Merger)、执行任意任务(Task)、甚至管理子进程(Agent)。

每种类型的任务,其具体执行流程、需要维护的状态信息、如何响应"启动"、"停止"、""等指令的方式都完全不同。Builder 需要处理数据源、调用索引库接口;Processor 需要读写消息队列、执行处理插件;Merger 需要协调不同版本的索引进行合并。

如果 心跳执行器 需要了解并直接调用每种任务类型特有的方法,那么它的代码会变得异常复杂且难以维护,因为它需要包含所有任务类型的逻辑分支。

WorkerStateHandler 的存在正是为了解决这个问题。它是一个基类,定义了一组通用接口(虚函数),所有不同类型的具体工作逻辑(Builder、Processor 等)都必须实现这些接口。这样一来,心跳执行器 只需要持有一个 WorkerStateHandler 类型的指针,并通过这些通用接口与底层的具体实现进行交互,而无需知道这个指针实际指向的是 BuilderServiceImpl、ProcessorServiceImpl 还是其他什么。

what 核心职责

WorkerStateHandler 基类为不同类型的工作进程提供了通用的状态管理框架,其核心职责包括:

  1. 接收并解析目标状态: 接收 心跳执行器 传递来的 目标状态 字符串,并将其解析成具体的、该角色能理解的指令和参数。
  2. 执行业务逻辑: 根据解析后的目标状态,执行相应的业务操作,如启动、停止、、更新配置、执行构建/处理/合并流程等。这通常是耗时且复杂的实际工作。
  3. 维护当前状态: 实时收集并维护自身的工作进度、运行状态、资源使用情况等信息,以便随时能够向 心跳执行器 报告。

心跳执行器(WorkerHeartbeatExecutor)

why need

ServiceWorker 启动后,它代表着一个具体的工作节点。这个工作节点需要不断地与远端的bs-admin进行通信,以确保它:

  • 定期"报到":告诉管理员"我还活着,我在这里!"。这就是所谓的"心跳"。
  • 接收"任务指令":管理员会根据集群的整体情况,给工作节点下达新的任务或调整现有任务的指令。
  • "汇报工作进展":工作节点需要告诉管理员自己当前正在做什么,任务进行到哪一步了,有没有遇到问题。
    工作节点心跳执行器 (WorkerHeartbeatExecutor),就像是工作节点内部的"通信和任务分配中心"。它专门负责处理所有与管理员之间的心跳通信、任务接收和状态汇报。它确保了工作节点能与管理员保持实时同步,是分布式系统中节点健康和任务调度顺利进行的关键。

what 核心职责

工作节点心跳执行器主要职责包括:

  • 感知目标状态变化: 从 WorkerHeartbeat 更新的 Worker 节点基类 (WorkerNodeBase) 对象中获取最新的"目标状态"。
  • 驱动工作执行: 根据获取到的"目标状态",调用具体的业务逻辑处理者(工作状态处理器 WorkerStateHandler)来执行相应的操作。
  • 隔离耗时操作: 将处理"目标状态"这样的耗时任务放到单独的 线程池 中执行,避免阻塞心跳和主循环。
  • 汇报当前状态: 定期从 工作状态处理器 获取"当前状态",更新到 Worker 节点基类 对象中,供心跳汇报使用。

how 内部工作原理

工作节点心跳执行器周期性地运行,从 Worker 节点基类 获取由 工作心跳 同步的"目标状态",并利用一个单线程的 线程池 将"目标状态"的处理任务 (工作状态处理器 的 handleTargetState 方法) 异步地派发出去,避免阻塞主循环。同时,它也负责获取 工作状态处理器 的"当前状态"并更新到 Worker 节点基类 中供心跳汇报使用,并监控 worker 的健康状况。它确保了 worker 进程既能高效通信,又能可靠地执行任务。

总结

以上就是bs-worker的主要流程,他接受bs-admin的心跳,根据心跳中解析出来的target执行不同的操作,同时在心跳中会将当前的状态返回。

具体不同的任务类型是如何执行的,我们在后面陆续介绍。

相关推荐
2025学习3 小时前
Spring循环依赖导致Bean无法正确初始化
后端
l0sgAi3 小时前
最新SpringAI 1.0.0正式版-实现流式对话应用
后端
parade岁月3 小时前
从浏览器存储到web项目中鉴权的简单分析
前端·后端
用户91453633083914 小时前
ThreadLocal详解:线程私有变量的正确使用姿势
后端
IT_10244 小时前
SpringBoot扩展——发送邮件!
java·spring boot·后端
用户4099322502124 小时前
如何在FastAPI中实现权限隔离并让用户乖乖听话?
后端·ai编程·trae
阿星AI工作室4 小时前
n8n教程:5分钟部署+自动生AI日报并写入飞书多维表格
前端·人工智能·后端
郝同学的测开笔记4 小时前
深入理解 kubectl port-forward:快速调试 Kubernetes 服务的利器
后端·kubernetes
Ray664 小时前
store vs docValues vs index
后端
像污秽一样5 小时前
软件开发新技术复习
java·spring boot·后端·rabbitmq·cloud