1. PaiFlow 的微服务是怎么划分的?每个服务的职责是什么?
考察点:服务拆分
参考答案:
按照业务能力和技术特点,PaiFlow 拆成了这几个服务:
| 服务 | 端口 | 职责 |
|---|---|---|
| Console Hub | 8080 | 用户管理、权限、工作流 CRUD、对外 API 网关 |
| Workflow Engine | 7880 | 工作流执行引擎,核心调度逻辑 |
| AI Tools | 18668 | AI 能力封装,如语音合成 |
| Link | 动态 | 外部工具连接器,对接第三方 API |
| Frontend | 80 | React 前端,可视化编排界面 |
拆分原则:
-
单一职责:每个服务只做一件事
-
独立部署:可单独扩容
-
技术异构:不同服务可以用不同语言(Java/Python)
-
数据隔离:每个服务有自己的数据库
参考答案版本 2
我们的服务划分遵循一个原则:按业务领域拆分,让每个服务有清晰的边界和单一的职责。
Console Hub 是业务中台,Java 写的,跑在 8080 端口。它负责所有"管理"相关的事情:用户登录认证、工作流的增删改查、工具市场管理、权限控制、租户管理。用户在前端的大部分操作,比如创建一个工作流、配置节点参数、保存发布,都是 Hub 在处理。
Console Frontend 是前端界面,React 写的,开发时跑在 1881 端口。核心是一个可视化的流程编辑器,用户在这里拖拽节点、连线、配置参数。它只做展示和交互,所有数据都通过 API 从后端获取。
Core Workflow 是工作流执行引擎,分为 Python 和 Java 两个版本,跑在 7880 端口。Hub 管的是"定义",它管的是"执行"。用户点击运行,Hub 把流程定义和输入参数丢给 workflow,它按照 DAG 的顺序一个节点一个节点地执行,调大模型、调插件,最后把结果返回。
// 工作流执行器
com.iflytek.astron.workflow.engine.WorkflowEngine
- execute(WorkflowDSL) // 执行工作流
- verifyWorkflow() // 校验(环检测、节点合法性)
- hasCycle() // Kahn 算法检测环
// 并行执行器
com.iflytek.astron.workflow.engine.ParallelWorkflowEngine
- 支持多节点并行执行
- 拓扑排序 + 线程池调度
Link 是工具调度服务,有 Java 和 Python 两个版本。它是工作流引擎和外部工具之间的桥梁。引擎执行到插件节点时,不是自己去调外部 API,而是把请求转给 Link,Link 根据工具的 OpenAPI Schema 解析出该怎么调用,然后转发请求、处理响应。这样新增工具只需要注册 Schema,不用改引擎代码。
AI Tools 是 AI 能力的封装服务,也是有 Python 和 Java 两个版本。语音合成、语音识别这些能力的 SDK 调用都在这里。比如讯飞的 TTS 用的是 WebSocket 协议,调用逻辑比较复杂,我们把它封装成一个简单的 HTTP 接口,其他服务调用就方便多了。
Nginx 是统一入口,所有请求先到 Nginx,由它根据路径转发到不同的后端服务。前端静态资源也是 Nginx 托管的。加上 gzip 压缩、缓存控制、HTTPS 这些,都在 Nginx 这一层处理。
数据服务包括 MySQL、Redis、MinIO。MySQL 存工具元数据、工作流和业务配置,Redis 做缓存和分布式锁,MinIO 存文件。
2. 服务之间是怎么通信的?用的 HTTP 还是 RPC?
考察点:服务间调用
参考答案:
我们用的是 HTTP REST,没有用 gRPC 或 Dubbo。
原因:
-
简单:HTTP 调试方便,curl 就能测
-
技术栈混合:Java 和 Python 服务都有,HTTP 兼容性好
-
流量不大:我们的场景不需要 RPC 那么高的性能
调用方式:
// Console Hub 调用 Workflow Engine
RestTemplate restTemplate = new RestTemplate();
String url = "http://core-workflow:7880/api/workflow/execute";
ResponseEntity response = restTemplate.postForEntity(url, request, String.class);
流式场景用 SSE:
// Workflow Engine 返回 SSE 流
SseEmitter emitter = new SseEmitter();
// 前端直连 Workflow Engine 的 SSE 端点
服务发现用 Docker 内网 DNS:
# docker-compose.yml
services:
core-workflow:
hostname: core-workflow # 其他服务用这个名字访问
参考答案版本 2
我们用的是 HTTP,没有用 RPC 框架。
选择 HTTP 主要有几个考虑。第一是多语言兼容。我们的服务有 Java 写的、Python 写的,以后可能还有 Go 的。如果用 gRPC,每个语言都要维护 proto 文件,多一套工具链要管理。HTTP 就简单多了,JSON 是通用格式,什么语言都能解析,不用额外的代码生成步骤。
第二是调试方便。HTTP 请求可以直接用 curl、Postman 测试,出了问题抓个包就能看...
真诚点赞 诚不我欺
回复