# R 统计引擎架构与部署指南 > **版本:** v1.0 > **创建日期:** 2026-02-19 > **维护者:** SSA-Pro 开发团队 > **状态:** ✅ 生产就绪 --- ## 📋 目录 1. [概述](#1-概述) 2. [架构设计](#2-架构设计) 3. [Docker 镜像构建](#3-docker-镜像构建) 4. [部署指南](#4-部署指南) 5. [API 参考](#5-api-参考) 6. [开发指南](#6-开发指南) 7. [运维指南](#7-运维指南) 8. [常见问题](#8-常见问题) --- ## 1. 概述 ### 1.1 什么是 R 统计引擎 R 统计引擎是平台的**专用统计计算服务**,基于 Docker 容器化部署,提供: - 🧮 **严谨的统计分析能力**(T 检验、方差分析、回归等) - 🛡️ **统计护栏**(正态性检验、方差齐性检验等) - 📊 **可视化输出**(Base64 编码的图表) - 📝 **可复现代码生成**(APA 格式的 R 脚本) ### 1.2 定位 ``` ┌─────────────────────────────────────────────────────────────┐ │ 业务模块层 │ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │ │ SSA-Pro │ │ 其他 │ │ 其他 │ │ │ │ 智能统计 │ │ 模块 │ │ 模块 │ │ │ └────┬────┘ └─────────┘ └─────────┘ │ ├───────┼─────────────────────────────────────────────────────┤ │ ▼ 通用能力层 │ │ ┌─────────────────────────────────────────────────────┐ │ │ │ R 统计引擎 (Docker) │ │ │ │ • /health 健康检查 │ │ │ │ • /api/v1/tools 工具列表 │ │ │ │ • /api/v1/skills 技能执行 │ │ │ └─────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ### 1.3 技术栈 | 组件 | 版本 | 说明 | |------|------|------| | R | 4.3.3 | 统计计算核心 | | plumber | 1.2.1 | REST API 框架 | | ggplot2 | 最新 | 数据可视化 | | car | 3.1-2 | 高级统计检验 | | dplyr/tidyr | 最新 | 数据处理 | | Docker | 24+ | 容器化部署 | --- ## 2. 架构设计 ### 2.1 Brain-Hand 模型 R 统计引擎采用 **Brain-Hand 分离架构**: ``` ┌──────────────────┐ ┌──────────────────┐ │ Node.js │ │ R Docker │ │ (Brain) │ │ (Hand) │ ├──────────────────┤ ├──────────────────┤ │ • 业务逻辑 │ HTTP │ • 统计计算 │ │ • 认证鉴权 │ ───────> │ • 数据处理 │ │ • OSS 签名 │ │ • 图表生成 │ │ • 结果解释 │ <─────── │ • 代码生成 │ └──────────────────┘ JSON └──────────────────┘ ``` ### 2.2 数据传输协议 支持两种数据传输方式: | 方式 | 条件 | 字段 | |------|------|------| | **inline** | 数据 < 2MB | `data_source.data` (JSON) | | **oss** | 数据 >= 2MB | `data_source.oss_url` (预签名 URL) | ```json // 方式 1: inline { "data_source": { "type": "inline", "data": [{"group": "A", "value": 10}, ...] } } // 方式 2: oss (预签名 URL) { "data_source": { "type": "oss", "oss_url": "https://bucket.oss.com/data.csv?signature=xxx" } } ``` ### 2.3 安全设计 | 安全措施 | 实现方式 | |----------|----------| | 非特权用户 | `USER appuser` | | 路径遍历防护 | `tool_code` 正则白名单 `^[A-Z][A-Z0-9_]*$` | | OSS 密钥隔离 | Node.js 生成预签名 URL,R 无需持有密钥 | | 健康检查 | Docker HEALTHCHECK | --- ## 3. Docker 镜像构建 ### 3.1 完整 Dockerfile ```dockerfile FROM rocker/r-ver:4.3 LABEL maintainer="dev-team@aiclinicalresearch.com" LABEL version="1.0.1" LABEL description="SSA-Pro R Statistics Service" # 安装系统依赖(包括 R 包编译所需的库) RUN apt-get update && apt-get install -y \ libcurl4-openssl-dev \ libssl-dev \ libxml2-dev \ libsodium-dev \ zlib1g-dev \ libnlopt-dev \ liblapack-dev \ libblas-dev \ gfortran \ pkg-config \ cmake \ curl \ && rm -rf /var/lib/apt/lists/* # 直接安装 R 包 RUN R -e "install.packages(c( \ 'plumber', \ 'jsonlite', \ 'ggplot2', \ 'glue', \ 'dplyr', \ 'tidyr', \ 'base64enc', \ 'yaml', \ 'car', \ 'httr' \ ), repos='https://cloud.r-project.org/', Ncpus=2)" # 安全加固:创建非特权用户 RUN useradd -m -s /bin/bash appuser WORKDIR /app # 复制应用代码 COPY plumber.R plumber.R COPY utils/ utils/ COPY tools/ tools/ COPY tests/ tests/ # 设置目录权限 RUN chown -R appuser:appuser /app # 切换到非特权用户 USER appuser EXPOSE 8080 # 环境变量 ENV DEV_MODE="false" # 健康检查 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD curl -f http://localhost:8080/health || exit 1 # 启动服务 CMD ["R", "-e", "plumber::plumb('plumber.R')$run(host='0.0.0.0', port=8080)"] ``` ### 3.2 系统依赖说明 | 依赖包 | 用途 | |--------|------| | `libcurl4-openssl-dev` | httr 包(HTTP 请求) | | `libssl-dev` | openssl 包(加密) | | `libxml2-dev` | xml2 包(XML 解析) | | `libsodium-dev` | sodium 包(加密) | | `zlib1g-dev` | httpuv 包(Web 服务器) | | `libnlopt-dev` | nloptr 包(优化算法) | | `liblapack-dev` | 线性代数计算 | | `libblas-dev` | 基础线性代数 | | `gfortran` | Fortran 编译器(部分 R 包需要) | | `cmake` | nloptr 包构建 | | `curl` | 健康检查 | ### 3.3 构建命令 ```bash # 本地构建 cd r-statistics-service docker build -t ssa-r-statistics:1.0.1 . # 查看镜像 docker images ssa-r-statistics # 预期输出 REPOSITORY TAG IMAGE ID CREATED SIZE ssa-r-statistics 1.0.1 xxxxxxxxxxxx x minutes ago 1.81GB ``` ### 3.4 构建时间参考 | 阶段 | 耗时 | |------|------| | 基础镜像下载 | ~2 分钟(首次) | | 系统依赖安装 | ~1 分钟 | | R 包安装 | ~6 分钟 | | **总计** | **~9 分钟** | --- ## 4. 部署指南 ### 4.1 开发环境 使用 docker-compose: ```yaml # r-statistics-service/docker-compose.yml version: '3.8' services: ssa-r-service: build: . container_name: ssa-r-statistics ports: - "8082:8080" # 主机8082 → 容器8080(REDCap占用8080/8081) environment: - DEV_MODE=true volumes: # 开发环境挂载:支持热重载 - ./tools:/app/tools - ./utils:/app/utils - ./tests:/app/tests restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"] # 容器内部仍是8080 interval: 30s timeout: 10s retries: 3 start_period: 10s ``` 启动命令: ```bash cd r-statistics-service docker-compose up -d ``` ### 4.2 生产环境 (SAE) ```yaml # SAE 配置 容器镜像: registry.cn-beijing.aliyuncs.com/aiclinical/ssa-r-statistics:1.0.1 实例规格: 2 vCPU, 4 GB 最小实例: 1 最大实例: 5 端口: 8080 环境变量: DEV_MODE: "false" ``` ### 4.3 环境变量 | 变量 | 默认值 | 说明 | |------|--------|------| | `DEV_MODE` | `false` | 开发模式(启用热重载,每次请求重新加载工具脚本) | > **说明**:开发环境和生产环境都使用真实 OSS,无需 Mock 数据。 > - 开发环境:`ai-clinical-data-dev` bucket > - 生产环境:`ai-clinical-data` bucket ### 4.4 端口配置 | 环境 | 主机端口 | 容器端口 | 说明 | |------|----------|----------|------| | **开发环境** | 8082 | 8080 | 避免与 REDCap 8080/8081 冲突 | | **生产环境 (SAE)** | 8080 | 8080 | 云端无端口冲突 | > **注意**:Node.js 后端通过 `R_SERVICE_URL` 环境变量配置 R 服务地址,默认值为 `http://localhost:8082`。 --- ## 5. API 参考 ### 5.1 健康检查 ```http GET /health ``` **响应:** ```json { "status": "ok", "timestamp": "2026-02-19 08:00:00", "version": "1.0.1", "dev_mode": true, "tools_loaded": 1 } ``` ### 5.2 工具列表 ```http GET /api/v1/tools ``` **响应:** ```json { "status": "ok", "tools": ["t_test_ind", "anova_oneway"], "count": 2 } ``` ### 5.3 执行技能 ```http POST /api/v1/skills/{tool_code} Content-Type: application/json ``` **请求体:** ```json { "data_source": { "type": "inline", "data": [...] }, "params": { "group_var": "group", "value_var": "value" }, "guardrails": { "check_normality": true } } ``` **成功响应:** ```json { "status": "success", "message": "分析完成", "warnings": null, "results": { "method": "Welch Two Sample t-test", "statistic": -5.196, "df": 5.98, "p_value": 0.002, "p_value_fmt": "p = .002" }, "plots": ["data:image/png;base64,..."], "trace_log": [...], "reproducible_code": "..." } ``` **错误响应:** ```json { "status": "error", "error_code": "E001", "error_type": "business", "message": "列名 'xxx' 在数据中不存在", "user_hint": "请检查变量名是否拼写正确" } ``` --- ## 6. 开发指南 ### 6.1 添加新工具 1. 在 `tools/` 目录创建 R 脚本: ```r # tools/my_analysis.R #' @tool_code ST_MY_ANALYSIS #' @name 我的分析工具 #' @version 1.0.0 # 统一入口函数 run_analysis <- function(input) { # 加载数据 df <- load_input_data(input) # 参数 p <- input$params # 护栏检查 # ... # 核心计算 # ... # 返回结果 return(list( status = "success", message = "分析完成", results = list(...) )) } ``` 2. 重启服务(开发模式无需重启) 3. 测试: ```bash curl -X POST http://localhost:8082/api/v1/skills/ST_MY_ANALYSIS \ -H "Content-Type: application/json" \ -d '{"data_source": {...}, "params": {...}}' ``` ### 6.2 工具命名规范 | 项目 | 规范 | |------|------| | 文件名 | 小写下划线:`t_test_ind.R` | | tool_code | 大写下划线:`ST_T_TEST_IND` | | 入口函数 | 固定名称:`run_analysis` | ### 6.3 结果格式规范 ```r return(list( status = "success" | "error" | "blocked", message = "...", warnings = c("...") | NULL, results = list( # 统计结果 ), plots = list( "data:image/png;base64,..." ), trace_log = c("..."), reproducible_code = "..." )) ``` --- ## 7. 运维指南 ### 7.1 日志查看 ```bash # 实时日志 docker logs -f ssa-r-statistics # 最近 100 行 docker logs --tail 100 ssa-r-statistics ``` ### 7.2 性能监控 ```bash # 容器资源使用 docker stats ssa-r-statistics ``` ### 7.3 重启服务 ```bash # 开发环境 docker-compose restart # 生产环境 (SAE) 通过 SAE 控制台重启实例 ``` ### 7.4 镜像更新 ```bash # 1. 构建新镜像 docker build -t ssa-r-statistics:1.0.2 . # 2. 推送到镜像仓库 docker tag ssa-r-statistics:1.0.2 registry.cn-beijing.aliyuncs.com/aiclinical/ssa-r-statistics:1.0.2 docker push registry.cn-beijing.aliyuncs.com/aiclinical/ssa-r-statistics:1.0.2 # 3. 更新 SAE 部署 ``` --- ## 8. 常见问题 ### Q1: 构建时 httpuv 安装失败 **错误:** `fatal error: zlib.h: No such file or directory` **解决:** 添加 `zlib1g-dev` 到系统依赖 ### Q2: 构建时 nloptr 安装失败 **错误:** `CMAKE NOT FOUND` **解决:** 添加 `cmake` 到系统依赖 ### Q3: /tmp 权限问题 **错误:** `cannot open file '/tmp/Rtmpxxx': No such file or directory` **解决:** 不要在启动命令中清理 /tmp ### Q4: DEV_MODE 热重载不生效 **原因:** 没有挂载 volumes **解决:** ```yaml volumes: - ./tools:/app/tools ``` ### Q5: 容器启动后无法访问 **检查:** 1. 端口映射是否正确 2. 健康检查是否通过 3. 查看容器日志 --- ## 附录:文件结构 ``` r-statistics-service/ ├── Dockerfile # 生产镜像定义 ├── docker-compose.yml # 开发环境编排 ├── renv.lock # R 包版本锁定(备用) ├── .Rprofile # R 启动配置(备用) ├── plumber.R # API 入口 ├── utils/ │ ├── data_loader.R # 数据加载(预签名 URL) │ ├── guardrails.R # 统计护栏 │ ├── error_codes.R # 错误映射 │ └── result_formatter.R # 结果格式化 ├── tools/ │ └── t_test_ind.R # 独立样本 T 检验 ├── tests/ │ └── fixtures/ │ └── normal_data.csv # 测试数据 ├── metadata/ # 工具元数据(预留) └── templates/ # 解释模板(预留) ``` --- **文档结束**