news 2026/10/21 23:56:40

Apache Pinot Controller UI 前端开发环境搭建指南:从源码启动与调试 Web 控制台

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache Pinot Controller UI 前端开发环境搭建指南:从源码启动与调试 Web 控制台
  • OLAP
  • 数据库
  • 大数据
  • 流处理

【免费下载链接】pinot

Apache Pinot - A realtime distributed OLAP datastore

项目地址:https://gitcode.com/gh_mirrors/pinot/pinot
点击查看免费下载

Apache Pinot Controller 自带一套基于 React + TypeScript 的 Web 控制台(Pinot Controller UI),用于集群管理、表与 Schema 运维、SQL 查询、任务调度和 ZooKeeper 浏览。本文围绕 pinot-controller/src/main/resources/Readme.md 中给出的开发环境搭建步骤,结合仓库内的前端源码、构建配置与 Controller 后端静态资源挂载逻辑,系统讲解如何从源码启动 UI 开发服务器、如何与后端 Controller 联调,以及生产构建产物如何被打包进 Controller 进程对外提供服务。读完本文,你将能够独立完成 Pinot Controller UI 的开发、调试与构建流程。

一、Pinot Controller UI 是什么

Pinot Controller UI 是 Apache Pinot 的官方 Web 管理界面,源码位于仓库的pinot-controller/src/main/resources目录下,是一个典型的现代前端工程:

  • 技术栈:React 16 + TypeScript + Material-UI,路由使用react-router-dom(HashRouter),请求库使用axios,代码编辑器使用 CodeMirror(用于 SQL 查询编辑);
  • 入口文件:app/index.tsx 负责将App组件挂载到#app节点,外层依次包裹HashRouter、MuiThemeProvider、NotificationContextProvider和AuthProvider;
  • 页面结构:页面组件集中在 app/pages 目录,包括查询控制台Query.tsx、租户管理Tenants*.tsx、实例管理Instance*、表/段管理TablesListingPage.tsx、Minion 任务管理MinionTaskManager.tsx、任务队列TaskQueue*.tsx、ZooKeeper 浏览器ZookeeperPage.tsx以及登录页LoginPage.tsx;
  • 后端 API 封装:所有对 Controller REST API 的调用统一收敛在 app/requests/index.ts,如/tenants、/tables、/schemas、/segments、/instances、/tasks、/zk/*、/sql等接口都有对应的封装函数。

因此,开发 UI 的前提是理解它的目录组织:app/存放全部业务代码,webpack.config.js与tsconfig.json定义构建与开发服务器行为,package.json声明脚本与依赖,swagger/存放与后端接口定义相关的资源。

二、开发前置条件:让 Pinot 后端跑起来

UI 本身只是一个前端壳,所有数据都来自 Controller 暴露的 REST API。开发时通过 webpack-dev-server 的代理把请求转发到本机 Controller,因此在启动 UI 之前,必须保证 Pinot 后端(Controller)已经在9000 端口正常运行。

启动后端的最简方式是直接编译并运行仓库根目录下的模块(Pinot 的构建方式可参考仓库根目录 README.md 中关于构建的说明),典型流程为:

  1. 克隆仓库后,在根目录执行 Maven 编译相关模块(pinot-controller及其依赖),确保mvn与 JDK 环境就绪;
  2. 按 Pinot 的启动方式拉起 ZooKeeper 与 Controller,默认 Controller 监听9000端口;
  3. 确认http://localhost:9000可以正常访问(返回 UI 首页或 API 响应)。

提示:Readme 中特别强调后端必须运行在 9000 端口,这是 webpack-dev-server 代理配置(见下文)的硬性前提;若你修改了 Controller 端口,需同步调整代理目标。

三、进入 UI 源码目录

Readme 给出的第一步是切换到 UI 源码目录。由于 UI 源码位于 Controller 模块的资源目录下,因此进入方式为:

cd pinot-controller/src/main/resources

后续所有npm命令都在该目录下执行。该目录下的关键文件包括:

  • package.json:npm 脚本与依赖清单;
  • webpack.config.js:webpack 构建配置与开发服务器代理;
  • tsconfig.json:TypeScript 编译配置;
  • app/:前端业务源码根目录。

四、安装依赖:Node 版本要求与 npm install

Readme 明确要求使用Node v16 或更精确的 v16.15.0,这与本仓库 package.json 锁定的前端依赖版本直接相关——工程内使用了 webpack 4.29.6、webpack-dev-server 3.2.1、TypeScript 3.8.3、React 16.13.1 等较早期版本的工具链,Node 版本过新可能导致兼容性问题。建议使用 nvm 之类的版本管理工具切换到 Node 16.15.0 后再执行:

npm install

npm install会依据package.json与仓库中已提交的 package-lock.json 安装全部依赖。该工程的依赖主要分为两类:

  • 运行时依赖(dependencies):react、react-dom、react-router-dom、@material-ui/core(含 icons/lab)、axios、codemirror、react-codemirror2、json-bigint、jwt-decode、@fortawesome/*、@sqltools/formatter等;
  • 开发依赖(devDependencies):typescript、webpack、webpack-cli、webpack-dev-server、ts-loader、css-loader、style-loader、html-webpack-plugin、copy-webpack-plugin、clean-webpack-plugin、eslint与prettier系列等。

其中json-bigint用于处理查询结果中的大整数(如超精度时间戳),jwt-decode用于解析 OIDC 登录后的 JWT access token,这两点在后续认证与查询功能中都会用到。

五、启动开发服务器:npm run dev

依赖安装完成后,执行:

npm run dev

该命令实际执行的是webpack-dev-server --config ./webpack.config.js --mode development(见 package.json 的scripts段)。webpack 会从入口./app/index.tsx开始打包,然后启动开发服务器。

5.1 开发服务器端口与代理

webpack.config.js 中配置了devServer:

  • 默认开发服务器监听8080端口,因此 Readme 指出应用运行在http://localhost:8080;
  • hot: true开启热模块替换(HMR),改代码后页面自动刷新;
  • compress: true开启 gzip 压缩;
  • 关键的是proxy配置:将/下所有请求代理到http://localhost:9000并设置changeOrigin: true。这正是前面要求后端跑在 9000 端口的原因——前端请求/tables、/sql等 API 时,webpack-dev-server 会将其转发给本机 Controller,实现前后端分离开发。

5.2 开发模式下的功能验证

启动后访问http://localhost:8080,可以看到登录页或主界面。开发模式与生产模式的主要差异包括:

  • 使用--mode development,并开启source-map(devtool: 'source-map'),方便在浏览器中直接调试 TypeScript/React 源码;
  • 走webpack-dev-server的内存打包与热更新,无需手工构建产物。

六、UI 与后端是如何对接的:从请求封装到静态资源挂载

理解"UI 如何工作"对开发调试至关重要,这里从源码层面梳理两条链路。

6.1 前端请求链路

前端所有 API 请求都通过 app/utils/axios-config.ts 创建的 axios 实例发出:

  • baseApi:baseURL: '/',用于绝大多数 REST 调用;
  • transformApi:配置了transformResponse: [data => data],不自动解析 JSON,用于/sql查询等需要保留原始字符串的场景;
  • baseApiWithErrors:在 API 失败时会抛出错误,供需要显式处理错误的新增接口使用(文件中注释明确说明新增 API 建议使用它)。

所有 axios 实例都注册了请求/响应拦截器:当启用 Basic Auth 时自动附加Authorization头;当启用 OIDC 时附加 access token;当收到 401/403 时触发"未认证访问"回调(跳转登录或自动登出)。拦截器的具体逻辑见 axios-config.ts 与 app/components/auth/AuthProvider.tsx。

业务侧的接口封装集中在 app/requests/index.ts,例如getQueryResult通过transformApi.post('/sql', params)提交查询,getTableSchema拉取表 Schema,scheduleTask调度 Minion 任务等。开发新页面时,通常只需要在requests/index.ts增加封装函数,再在页面组件中调用即可。

6.2 后端如何托管 UI 产物

生产环境下,Controller 进程直接托管 UI 的静态文件。相关实现分散在 Controller 模块中:

  • ControllerAdminApiApplication.java 通过CLStaticHttpHandler将 classpath 下的/webapp/、/webapp/images/、/webapp/js/分别挂载到/index.html、/images/、/js/路径;
  • LandingPageHandler.java 在/路径直接返回webapp/index.html作为首页;
  • ControllerConf.java 中可配置 UI 资源路径。

也就是说,npm run build产出的dist/webapp目录(见webpack.config.js的output.path)在打包进 jar 后会被 Controller 读取并对外服务。开发模式下你访问 8080 端口看到的页面,与生产环境访问 9000 端口 Controller 根路径看到的页面,是同一套代码的两种形态。

6.3 认证方式

Controller 支持三种认证工作流(见 AuthProvider.tsx 的AuthWorkflow):

  • NONE:无需认证,直接进入应用;
  • BASIC:由 LoginPage.tsx 提供用户名/密码表单,前端用btoa生成Basic base64(username:password)凭据,调用/auth/verify校验后写入app_state.authToken;
  • OIDC:前端根据/auth/info返回的issuer、clientId、redirectUri构造隐藏表单跳转授权端点,通过 token 方式(token id_token)获取 access token,并持久化到 localStorage 中。

开发时若后端未开启认证(默认 NONE),UI 会直接进入主界面,无需登录。

七、生产构建与常用 npm 脚本

package.json 提供的常用脚本如下:

脚本命令作用
devwebpack-dev-server --config ./webpack.config.js --mode development启动开发服务器(默认 8080 端口,代理 9000)
startnpm-run-all --parallel lint dev并行执行代码检查与开发服务器
buildwebpack --mode production生产构建,产物输出到dist/webapp
build-devwebpack --mode development开发模式构建
build-ci按CI环境变量选择build或build-devCI 环境专用构建
build-analyzewebpack --mode production --analyze带包体积分析的构建
linteslint 'app/**/*.{js,ts,tsx,jsx}' --quiet --fixESLint 自动修复

生产构建(npm run build)会执行 webpack.config.js 中的插件链:CleanWebpackPlugin清理旧产物、CopyWebpackPlugin将favicon.ico复制到images/、HtmlWebPackPlugin以app/index.html为模板生成带 viewport 元信息的index.html。构建完成后,dist/webapp即为可被 Controller 托管的完整静态站点。

八、常见开发问题排查

  1. 8080 端口无法访问:确认npm run dev未报错、Node 版本为 v16.15.0 附近;若端口被占用,可调整 webpack-dev-server 配置或释放端口。
  2. 页面能打开但数据加载失败:优先检查http://localhost:9000的 Controller 是否存活、代理是否生效。可在浏览器 Network 面板确认请求是否被转发到 9000 端口;若后端未开启认证而 UI 误以为需要登录,检查/auth/info返回的workflow是否为NONE。
  3. 改代码后页面未热更新:确认dev模式(非build),并检查 webpack 是否报编译错误;HMR 需要hot: true(默认已开启)。
  4. 构建产物未出现在预期位置:生产构建输出目录是dist/webapp(由output.path决定),不要与dist/下的 TypeScript 编译输出(见 tsconfig.json 的outDir)混淆。
  5. 查询结果数字精度丢失:查询接口走transformApi(保留原始 JSON 字符串),配合json-bigint处理大整数;不要自行改用默认 JSON 解析的baseApi。

九、小结

Pinot Controller UI 的开发链路可概括为:进入pinot-controller/src/main/resources→ 使用 Node v16.15.0 执行npm install→ 确保 Controller 运行在 9000 端口 → 执行npm run dev访问http://localhost:8080。开发模式下 webpack-dev-server 负责热更新与 API 代理,生产模式下npm run build产出dist/webapp由 Controller 静态托管。理解 webpack.config.js 的代理机制、app/requests/index.ts 的接口封装以及 ControllerAdminApiApplication.java 的资源挂载逻辑,即可在这套前后端分离架构下高效开发、调试与扩展 Pinot 的 Web 控制台。

  • OLAP
  • 数据库
  • 大数据
  • 流处理

【免费下载链接】pinot

Apache Pinot - A realtime distributed OLAP datastore

项目地址:https://gitcode.com/gh_mirrors/pinot/pinot
点击查看免费下载

相关推荐

上一篇:3个颠覆性功能:Scarab模组管理器如何重新定义空洞骑士游戏体验
下一篇:EntityComponentSystemSamples 之 Tornado 示例深度解析:用 ECS、Burst 与数组实现 50Hz 的杆件撕裂模拟

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/18 16:19:56

拉瓦尔喷管准一维数值模拟:从欧拉方程到MacCormack格式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/18 20:01:23

深度学习入门:从核心概念到PyTorch实战训练全流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/18 11:59:15

[对比学习LangChain和MAF-14]使用消息注入改变对话历史

对话历史作为核心的上下文信息,为LLM建立起对话的语境,是决定LLM响应内容的关键输入之一。对话历史中的每一条消息都绑定这一个固定的角色,典型的角色包括System、User、Assistant和Tool。但是这并不意味着每条消息一定要求都要由对应的角色生…

作者头像 李华