《深度拆解JVS-智能BI技术栈:为什么选择 Spring Cloud + Doris + DataX?(附3000字实战笔记)》

0 阅读7分钟

本文首发于掘金,从架构、数据集成、存储、调度、前后端选型,再到真实部署中的踩坑与调优,全面拆解一款开源 BI 的技术细节。如果你正在自研数据平台或选型 BI,欢迎收藏交流。

一、这是一篇什么文章?

先交代背景:JVS-BI 是一款 私有化部署、全源码开放 的自助式数据分析平台。我因为项目需要,深度研究了它的技术栈,并在测试环境完整部署过一遍。

这篇文章不是官方文档的复读机,而是我从选型对比、实际配置到生产化改造中积累的 技术笔记 + 踩坑实录。全文 3500 字左右,建议先赞后看。

你会看到

  • 一套完整的 BI 系统分层架构(附官方架构图)
  • 为什么选 Spring Cloud Alibaba + DataX + Doris + XXL-JOB?
  • DataX 从 MySQL 同步到 Doris 的完整配置(含 JSON 示例)
  • Doris 建表与查询的实战 SQL
  • 前端大屏设计器:Vue3 + 拖拽组件 + 图层管理
  • 独家踩坑:DataX OOM、Doris 分区设计失误、XXL-JOB 重复执行

二、整体架构概览(先看图)

JVS-BI 采用经典的四层架构:

  1. 基础框架层:JVS 统一底座(用户、认证、消息、微服务治理)
  2. 数据接入层:JDBC / API / 文件 多源连接,屏蔽差异
  3. 数据加工层:可视化 ELT + DataX 抽取 + Doris 数仓存储
  4. 数据应用层:图表、报表、大屏、API 服务

image.png

三、后端核心组件选型与详解(含代码)

3.1 微服务底座:Spring Cloud Alibaba

组件具体技术作用
服务注册/配置Nacos动态配置、服务发现
服务调用OpenFeign声明式 HTTP
网关Spring Cloud Gateway路由 + 鉴权

为什么不是 Dubbo 或纯 Spring Boot?

  • Nacos 同时搞定配置和服务发现,比 Eureka 香。
  • BI 系统主要是 IO 密集型(查数据),RPC 调用不频繁,OpenFeign 足够轻量。
  • 对中小团队来说,Spring Cloud 生态学习成本更低。

3.2 数据抽取:DataX(附 JSON 配置)

DataX 是阿里开源的异构数据同步神器,JVS-BI 将其封装成了界面化任务。

一个真实的 MySQL → Doris 同步配置(从页面导出的 JSON): json

{
  "job": {
    "content": [
      {
        "reader": {
          "name": "mysqlreader",
          "parameter": {
            "username": "root",
            "password": "123456",
            "connection": [{
              "jdbcUrl": ["jdbc:mysql://localhost:3306/sales"],
              "table": ["orders"]
            }]
          }
        },
        "writer": {
          "name": "doriswriter",
          "parameter": {
            "feLoadUrl": ["fe_host:8030"],
            "beLoadUrl": ["be_host:8040"],
            "database": "jvs_bi_ods",
            "table": "orders",
            "maxBatchRows": 500000,
            "maxBatchByteSize": 104857600
          }
        }
      }
    ],
    "setting": {
      "speed": {
        "channel": 3,
        "byte": 1048576
      }
    }
  }
}

image.png

3.3 数据存储:Apache Doris(含建表 SQL)

Doris 是 MPP 列存数据库,支持 MySQL 协议,学习成本极低。

选型对比(个人实践后的结论):

特性DorisClickHouseStarRocks
SQL 兼容性✅ 高⚠️ 有差异✅ 高
实时写入✅ 高吞吐✅ 高吞吐✅ 高吞吐
主键更新✅ Unique Key❌ 需重建✅ 支持
运维复杂度低(FE/BE)
社区活跃度Apache 顶级

建表示例(聚合模型,按天分区):

sql

CREATE TABLE sales_daily (
    sale_date DATE,
    product_id INT,
    region VARCHAR(20),
    amount DECIMAL(18,2)
) AGGREGATE KEY(sale_date, product_id, region)
PARTITION BY RANGE(sale_date) (
    PARTITION p20260101 VALUES [('2026-01-01'), ('2026-01-02')),
    PARTITION p20260102 VALUES [('2026-01-02'), ('2026-01-03'))
)
DISTRIBUTED BY HASH(product_id) BUCKETS 10
PROPERTIES (
    "replication_num" = "1",
    "storage_format" = "V2"
);

为什么不用 MySQL 直接分析?

  • 业务库行存,复杂聚合直接打挂 OLTP。
  • Doris 列存 + 向量化,亿级数据秒级响应。

3.4 调度引擎:XXL-JOB

  • 每个数据集对应一个 XXL-JOB 任务,通过 @XxlJob 注解触发 DataX 或 Doris SQL。
  • 支持前置/后置任务依赖(比如先同步 ODS,再加工 DWD)。
  • 提供 Web 界面,可以手动触发、查看日志。

2196e8099897020d785e31a96f39e317.png

3.5 消息队列:RabbitMQ

  • 用途:异步处理任务状态更新、发送通知(邮件/钉钉)、记录执行日志。
  • 为什么不选 Kafka?BI 系统的任务量级远小于日志系统,RabbitMQ 更轻,且支持复杂的路由。

四、前端大屏设计器技术实现(掘金前端读者必看)

image.png JVS-BI 的大屏设计器是基于 Vue3 + Element Plus + 自研拖拽组件 实现的。我重点拆解三个核心能力:

4.1 拖拽布局

  • 使用 vue3-draggable-resizable 库实现组件的自由拖拽和缩放。
  • 每个组件对应一个 JSON 配置(x, y, w, h, type, props)。
  • 画布是一个绝对定位容器,组件通过 transform 或 top/left 定位。

简化代码示意

vue

<template>
  <div class="canvas" :style="{ width: canvasWidth, height: canvasHeight }">
    <draggable-resizable
      v-for="item in widgets"
      :key="item.id"
      :x="item.x"
      :y="item.y"
      :w="item.w"
      :h="item.h"
      @resize="onResize"
      @drag="onDrag"
    >
      <component :is="item.type" v-bind="item.props" />
    </draggable-resizable>
  </div>
</template>

4.2 图层管理(z-index 堆叠)

  • 每个组件有一个 zIndex 属性。
  • 左侧图层树展示所有组件,支持拖拽排序、显示/隐藏、锁定。
  • 通过 EventBus 实现画布组件和图层树的双向同步。

4.3 母版(Master)功能

  • 类似 PPT 的母版:在母版页添加的组件,会在所有普通页面自动出现。
  • 技术实现:两个独立的画布数据源(masterSlides 和 slides),渲染时先渲染母版组件,再渲染普通组件。
  • 母版组件被锁定,普通页面不可编辑。

这一套前端方案,基本可以满足企业级大屏 90% 的需求,而且代码完全开放,值得借鉴。


五、独家踩坑与调优(真实生产环境)

坑1:DataX 同步大表 OOM

现象:同步 2000 万行数据时,DataX 进程直接 OOM。
原因:默认 channel 数为 5,每个 channel 会缓存全部数据。
解决:限制 channel 数量和单 channel 内存:

json

"setting": {
    "speed": {
        "channel": 1,
        "byte": 1048576
    },
    "errorLimit": {
        "record": 0
    }
}

同时增加 JVM 堆内存:-Xms2g -Xmx4g

坑2:Doris 分区键设计不合理导致查询慢

现象:按 sale_date 分区,但查询常用 region 过滤,分区裁剪失效。
原因:Doris 的分区裁剪只针对分区键。
解决:将常用过滤字段作为 DISTRIBUTED BY HASH 的键,并创建 Bloom Filter 索引。

sql

ALTER TABLE sales_daily SET ("bloom_filter_columns" = "region");

坑3:XXL-JOB 分片任务重复执行

现象:配置了分片(shardIndex=0,1),但两个节点都处理全量数据。
原因:代码中没有根据 shardIndex 和 shardTotal 拆分数据范围。
解决:在任务方法中获取分片参数,用取模拆分数据:

java

int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
// where mod(id, shardTotal) = shardIndex

坑4:前端大屏拖拽时卡顿

现象:画布上超过 30 个组件后,拖拽缩放非常卡。
原因vue3-draggable-resizable 在每次拖拽时触发大量重绘。
解决:使用 requestAnimationFrame 节流 + 开启硬件加速(transform: translateZ(0))。另外对非可视区域组件做虚拟滚动(未完全实现,但官方正在优化)。


六、部署与运维(Docker Compose 一键启动)

JVS-BI 提供完整的 docker-compose 脚本,以下为核心步骤:

bash

# 1. 克隆部署项目(示例地址,实际以官方为准)
git clone https://gitee.com/software-minister/jvs-docker-compose.git
cd jvs-docker-compose

# 2. 修改本地 IP(替换 ${IP} 为你的服务器内网IP)
sed -i 's/server-ip/192.168.1.100/g' ./mysql/nacos.sql

# 3. 启动基础中间件(MySQL, Nacos, RabbitMQ, XXL-JOB)
docker-compose -f docker-compose-db.yml up -d
docker-compose -f docker-compose-base.yml up -d

# 4. 启动 Doris(需先调优系统参数,见官方文档)
docker-compose -f docker-compose-doris.yml up -d

# 5. 启动 BI 服务
docker-compose -f docker-compose-data-platform.yml up -d

254f770e6a571f49eedf15468afd9b05.png

七、总结与互动

JVS-BI 的技术栈没有盲目追新,而是选择了 成熟、可维护、开源 的组件:

  • 微服务:Spring Cloud Alibaba(Nacos + Gateway)
  • 数据集成:DataX(稳定,支持限速、断点续传)
  • 数仓:Doris(MPP,兼容 MySQL,易运维)
  • 调度:XXL-JOB(轻量,支持分片)
  • 前端:Vue3 + 自研拖拽设计器

如果你也在做类似的数据平台,欢迎参考这套架构。同时,我也很想知道:

  1. 你会选择 Doris 还是 ClickHouse?为什么?
  2. 在数据抽取中,你遇到过哪些坑?如何解决的?
  3. 你还想了解 JVS-BI 哪个模块的源码实现?

如果这篇文章对你有帮助,请点赞、收藏、评论三连支持!

📌 相关资源