# vita **Repository Path**: edwarddamon/vita ## Basic Information - **Project Name**: vita - **Description**: 私人领域中枢后端 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-05 - **Last Updated**: 2026-08-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: vita ## README # Vita · 此生 > **vita** — 拉丁语「生命」 · 中文品牌 **此生** **Slogan:此生所历,皆在于此** 基于 Spring Cloud 的**个人私域综合平台**后端(v2.0.0),为个人项目提供统一认证、文件、消息与业务能力;当前生活场景由微信小程序 **此生录** 承载。覆盖认证授权、文件、消息、即时通讯与生活记录等能力,配套 [vita-web](https://gitee.com/edwarddamon/vita-web) 管理端。 ## 产品命名 | 层级 | 名称 | 用途 | |------|------|------| | 英文 / 代码 | **Vita** | 仓库、服务(`vita-*`)、API、技术文档 | | 中文整体品牌 | **此生** | 短信签名 `【此生】`、邮件发件人与主题 `[此生]`、产品体系对外称呼 | | 生活小程序 | **此生录** | 微信小程序名称; Slogan:**此生之事,记于此录** | | Web 管理端 | **此生 · 管理台** | [vita-web](https://gitee.com/edwarddamon/vita-web) 运维与 RBAC | **通知示例** ```text 【此生】您有 2 笔人情待还。 详情请在「此生录」小程序查看。 ``` ```text 发件人:此生 主题:[此生] 重要日子提醒 ``` ## 功能概览 | 领域 | 能力 | |------|------| | 统一入口 | 网关路由、TraceId、Token 鉴权、接口级权限拦截、白名单 IP 限流、已登录用户限流 | | 认证授权 | 邮箱登录、微信小程序登录/绑定、RBAC、菜单树、API 资源注册、字典、权限客户端范围 | | 文件 | 分步上传、临时访问 URL、业务绑定、OSS 存储、孤儿文件自动清理 | | 消息 | 阿里云邮件推送、Velocity 模板渲染、发送记录、多维度限流 | | 即时通讯 | WebSocket 连接、广播消息、ACK 回执 | | 生活记录 | 礼金收支 CRUD(婚礼/丧礼、还礼跟踪) | ## 模块一览 ``` vita/ ├── vita-common # 公共包 — 自动配置、异常处理、Feign 拦截器、通用 DTO/枚举、Feign Client ├── vita-gateway :8888 # 网关 — 路由、鉴权、TraceId、白名单 IP 限流、用户限流 ├── vita-auth-center :8033 # 认证中心 — 用户/角色/权限/菜单/API 资源/字典/微信登录 ├── vita-file :8023 # 文件服务 — 上传/访问/业务绑定/孤儿清理 ├── vita-message :8043 # 消息服务 — 邮件模板与发送/多维度限流 ├── vita-im :8053 # IM 服务 — WebSocket ├── vita-life :8063 # 生活服务 — 礼金记录 ├── vita_server_deploy_basic # 本地/演示用基础设施 compose(MySQL / Redis / Nacos) ├── vita_server_devops # CI 镜像构建脚本;旧版单机 CD(compose)保留作参考 └── vita_server_swarm_deploy # ★ 生产部署:Docker Swarm Stack 编排 ``` ## 架构 ``` 客户端 → vita-gateway (:8888) ├── TraceFilter → 生成 traceId(order +0) ├── UrlTokenToHeaderFilter → WebSocket 等场景:URL token → Authorization Header(order +10) ├── RateLimitFilter → 白名单接口 IP 级令牌桶限流(order +20) ├── CryptoFilter → 解密加密请求体、加密响应体(order +30) ├── AuthFilter → 匹配 API 规则 / Token 校验 / 权限码校验(order +40) ├── UserRateLimitFilter → 已登录接口 userId 级令牌桶限流(order +50) ↓ StripPrefix 路由 ├── /auth/**, /system/** → vita-auth-center ├── /file/** → vita-file ├── /message/** → vita-message ├── /im/** → vita-im(WebSocket) └── /life/** → vita-life ``` ### 网关过滤器链 | 顺序 | order | 过滤器 | 职责 | |------|-------|--------|------| | 1 | +0 | **TraceFilter** | 生成 `traceId`,写入 MDC 并向下游透传 | | 2 | +10 | **UrlTokenToHeaderFilter** | 对配置的路径(如 `/im/ws/**`)提取 URL 末段 token 置入 `Authorization` Header | | 3 | +20 | **RateLimitFilter** | 仅对白名单接口(无需登录)按 IP + 路径维度做令牌桶限流,触发返回 429;Redis 故障时降级放行 | | 4 | +30 | **CryptoFilter** | 解密加密请求体、加密响应体(RSA + AES-GCM,可配置关闭) | | 5 | +40 | **AuthFilter** | 匹配 API 鉴权规则——未注册接口拒绝、白名单放行、需登录接口校验 Token 与权限码,通过后向下游注入 `UserInfo` | | 6 | +50 | **UserRateLimitFilter** | 对已登录接口按 userId 做令牌桶限流(默认全局兜底 + 高风险路径收紧),触发返回 429;Redis 故障时降级放行 | ## 模块功能 ### vita-common - **自动配置**(SPI):全局异常处理、健康检查、TraceId 拦截器、Feign 拦截器(传播 traceId 与用户信息)、数据权限拦截器(自动注入各模块 MybatisPlusInterceptor) - **Feign Client**:`AuthCenterClient`(用户信息)、`FileClient`(文件业务绑定) - **通用模型**:统一 `Result` / `PageResult`、各模块 DTO/VO/BO/枚举 - **API 鉴权工具**:`ApiAuthRuleMatcher` 供网关匹配路径与权限码;`ApiResourceAuthProfile` 根据权限码推导鉴权策略 ### vita-gateway **路由与鉴权** - 基于 `sys_api_resource` 快照(Redis)做**接口级鉴权**:未注册接口直接拒绝 - Token 校验(Redis),校验通过后向下游注入 `UserInfo`;每次请求自动刷新 Token TTL - 支持 CORS;WebSocket 路径 `/im/ws/**` 通过 URL token 转 Header **白名单接口限流(IP 维度)** - 使用 Redisson `RRateLimiter` 令牌桶算法,仅对无需登录的接口生效 - 按 **IP + 请求路径** 维度独立限流,支持 Ant 风格路径匹配 - 配置前缀 `gateway.rate-limit`,通过 Nacos 动态刷新(`@RefreshScope`) - 本地版本缓存检测配置变更,仅变化时才更新 Redis,避免无效写操作 - Key 自动过期:活跃用户持续续期,不活跃用户窗口结束后自动清理,防止 Redis 内存膨胀 - Redis 故障时降级放行,保证可用性 **已登录接口限流(userId 维度)** - 新增 `UserRateLimitFilter`,在 `AuthFilter` 之后执行,从 `UserInfo` 请求头解析 userId - 默认单用户全局兜底(如 600 次/分钟),不按路径分桶,每请求仅一回合 Redis - 支持 `path-rules` 对高风险接口组(如 `/message/email/**`、`/file/upload/**`)单独收紧 - 配置前缀 `gateway.user-rate-limit`,通过 Nacos 动态刷新 - 白名单接口由 IP 限流覆盖,本过滤器不重复处理 - Redis 故障时降级放行 ### vita-auth-center **用户** - 邮箱登录 / 登出 / 当前用户信息 - 微信小程序登录:`code2Session` 换取 openId/sessionKey,新用户引导绑定邮箱 - 微信绑定流程:发送绑定验证码 → 验证码校验 → 绑定邮箱(自动创建用户或关联已有用户,分配小程序默认角色) - 运维:分页、创建、编辑、删除、详情、按 ID 批量查用户名 **角色** - 分页、CRUD - 用户-角色关联(`/role/associate`) - 数据权限标识 `dataAuth`:`OWNER`(仅本人)/ `ALL`(全部) **权限** - 权限树、分页、CRUD、详情(含关联菜单与 API 资源) - 权限 ↔ 菜单 / API 资源 绑定与解绑;变更后自动同步 API 鉴权规则至 Redis - 权限客户端范围(`clientScope`):控制权限在哪些客户端类型(运营 PC / 小程序)下可见 - 系统预置权限保护:`common:white`(白名单,无需登录)与 `common`(通用权限,登录即可)禁止修改删除 **API 资源** - 分页、详情、CRUD;维护接口路径、方法、所需权限码 **菜单** - 按用户与客户端类型(运营 PC / 小程序)返回动态菜单树 **字典** - 按 key 查列表、按 key+value 查 label(供前端下拉/展示) ### vita-file **上传流程**:申请令牌 → 上传数据 → 完成确认(含扩展名/大小校验与频率限制) **访问**:单个/批量获取临时访问 URL **业务绑定**(Feign / 内部调用):绑定、解绑、列表查询、批量按 bizId 查询、原子替换绑定、按业务维度删除 **存储**:工厂模式,当前实现阿里云 OSS(v2 SDK + 预签名 URL);可通过新增 `StorageService` 实现扩展 **孤儿文件自动清理**:定时任务(默认凌晨 2:30)扫描并清理三类孤儿文件——上传中废弃、上传中断、已完成但无业务关联,使用 Redisson 分布式锁保证多实例安全 **运维**:文件分页查询 ### vita-message **邮件发送** - 阿里云邮件推送(DirectMail),支持 Velocity 模板渲染或直接发送 - 模板 CRUD、发送记录分页与删除 **发送限流** - 全局维度:每分钟总发送量限制 - 用户维度:每人每分钟 + 每日发送量限制(区分用户端与运维端) - 收件人维度:同一邮箱每小时接收量限制 - 权重计数:可按收件人数或调用次数计权 ### vita-im - WebSocket 端点 `/ws/{token}`,握手时校验 token - 文本消息:广播(排除发送者)+ ACK 回执 - 二进制消息处理器已预留(分片传输待完善) ### vita-life 礼金记录管理: - 类型:婚礼 / 丧礼 - 收支方向、金额、送/收礼人、时间 - 还礼标记与还礼金额 - 分页查询与 CRUD ## 认证与权限 ``` User → Role → Permission ├── Menu(前端路由) └── ApiResource(网关接口鉴权) ``` 1. **网关层**:`AuthFilter` 加载 Redis 中的 API 规则快照,匹配 method + path;校验 Token 与 permissionCodes 2. **规则同步**:认证中心 `ApiAuthRuleSyncService` 在启动及权限变更时,将 `sys_api_resource` 全量写入 Redis;网关 `ApiAuthRuleCache` 缓存快照 3. **服务间调用**:Feign 自动传播 traceId 与当前用户信息 4. **数据权限**:基于 `@DataPermission` 注解 + MyBatis Plus 拦截器自动追加 SQL 过滤条件,详见下方调用链路 ### 鉴权策略推导 API 资源关联的权限码决定了网关鉴权策略(由 `ApiResourceAuthProfile.resolve()` 推导): | 权限码组合 | 网关行为 | |-----------|---------| | 含 `common:white` | 无需登录,无需权限校验 | | 全部为 `common` | 需登录,不校验具体权限码 | | 其他 | 需登录,且需持有对应权限码 | ### 数据权限调用链路 ``` HTTP Request (Header 含 UserInfoBO) │ ├─[路径A] Service/Facade 方法标注 @DataPermission │ │ │ ├── DataPermissionAspect.around() │ │ ├── 解析注解 → DataPermissionRule │ │ └── DataPermissionContext.push(rule) │ │ │ ├── Service 方法执行 │ │ └── 调用 Mapper │ │ │ │ │ ▼ │ │ DataPermissionInterceptor (MyBatis Plus) │ │ └── VitaDataPermissionHandler.getSqlSegment() │ │ ├── resolveRule() → 从 ThreadLocal 取 rule │ │ ├── matchTable() → 表名/别名匹配 │ │ ├── isAllScope() → 检查用户角色权限 │ │ └── 追加 WHERE create_by = {userId} │ │ │ └── finally: DataPermissionContext.poll() │ └─[路径B] Mapper 方法标注 @DataPermission(无 AOP) │ └── 调用 Mapper │ ▼ DataPermissionInterceptor (MyBatis Plus) └── VitaDataPermissionHandler.getSqlSegment() ├── resolveRule() │ ├── ThreadLocal 为空 → null │ └── AnnotationCache.resolve(msId) → 反射+缓存 ├── matchTable() → 别名匹配 ├── isAllScope() → 检查用户角色权限 └── 追加 WHERE {alias}.create_by = {userId} ``` **双路径说明**: - **路径 A**:注解标在 Service/Facade 方法上,由 AOP 切面将规则压入 ThreadLocal,Mapper 执行时从上下文取规则 - **路径 B**:注解直接标在 Mapper 方法上,无 AOP 介入,由 `DataPermissionAnnotationCache` 通过反射解析注解并缓存(静态元数据,所有用户共享) **用户隔离**:缓存仅存储注解元数据(column / tableAlias / tableName),用户身份每次从请求 Header 实时解析,在 `getSqlSegment()` 中合并为最终 SQL 条件 ## 技术栈 | 分类 | 技术 | |------|------| | 语言 / 构建 | Java 17 · Maven | | 框架 | Spring Boot 3.5.9 · Spring Cloud 2025.0.0 · Spring Cloud Alibaba 2025.0.0.0 | | 网关 | Spring Cloud Gateway (WebFlux) | | 注册 / 配置 | Nacos 3.x | | 持久化 | MySQL 8.0+ · MyBatis Plus 3.5.15 · MapStruct 1.5.5 | | 缓存 / 分布式锁 / 限流 | Redis 7.4+ · Redisson 3.52.0 | | 服务调用 | OpenFeign | | 文件存储 | 阿里云 OSS(alibabacloud-oss-v2) | | 邮件 | 阿里云邮件推送 | | 即时通讯 | Spring WebSocket | | 生产日志 | 阿里云 SLS + Logtail(见 [生产日志收集方案](#生产日志收集方案logtail--sls)) | | 工具 | Hutool · Gson · Jakarta Validation · Apache Commons Lang3 | ## 配置策略 Profile + 环境变量 + Nacos 三层分环境,仓库无根级 `application.yml`。 | Profile | 用途 | 配置来源 | |---------|------|---------| | `dev` | 本地联调 | Nacos `vita-dev` namespace | | `demo` | 单机演示 | 各模块内置 `application-demo.yml`,无需 Nacos | | `test` | 测试 | `${NACOS_*}` → Nacos `vita-test` | | `prod` | 生产 | 同 test,不同 namespace | 同一镜像适用所有环境,切换只需改 `ACTIVE_PROFILE` 与 `NACOS_*` 环境变量。 ## 本地开发 **环境要求**:JDK 17+ · Maven 3.6+ · MySQL 8.0+ · Redis 7.4+ ### 快速启动(demo,无需 Nacos) ```bash # 1. 拉起依赖(可选) docker compose -f vita_server_deploy_basic/docker-compose-basic.yml up -d # 2. 打包 mvn clean package -DskipTests # 3. 按依赖顺序启动:auth-center → file → message → im → life → gateway cd vita-auth-center && mvn spring-boot:run -Dspring-boot.run.profiles=demo ``` ### dev Profile + Nacos ```bash docker compose -f vita_server_deploy_basic/docker-compose-basic.yml up -d # 在 Nacos vita-dev namespace 配置各服务 yml 后: mvn spring-boot:run -Dspring-boot.run.profiles=dev ``` **健康检查**:各服务 `GET /health/check`(网关 `:8888/health/check`) ## CI / 镜像构建 生产镜像仍由本地 CI 脚本构建并推送到腾讯云 CCR,无需第三方 CI 平台: ``` 拉代码 → Maven 打包 → Docker 构建 → 推送 ccr.ccs.tencentyun.com/vita/* (vita-ci.sh) ``` 详见 [CI README](vita_server_devops/ci/README.md)。构建完成后,用 Swarm 做生产发布(见下节);旧版单机 `vita-cd.sh`(compose)仅作参考,见 [CD README](vita_server_devops/cd/README.md)。 ## 生产部署(Docker Swarm) > 详细步骤、排障与运维命令见 [vita_server_swarm_deploy/README.md](vita_server_swarm_deploy/README.md)。 ### 方式概览 | 项 | 说明 | |----|------| | 编排 | **Docker Swarm** + `docker stack deploy`(声明式,多 Stack) | | 入口 | 自托管 **Traefik v3**(80/443,Let's Encrypt 自动 TLS) | | 中间件 | Redis 7 + Nacos 3.x(固定 infra 节点) | | 数据库 | **阿里云 RDS MySQL**(不部署本地 MySQL) | | 业务 | 5 个微服务 spread 到 worker 池(gateway / auth-center / file / message / life) | | 前端 | nginx 静态资源 Stack(独立域名) | | 监控 | Prometheus + Grafana + Alertmanager + Blackbox + Node Exporter | | 日志 | 容器 stdout → Logtail → **阿里云 SLS**(见下方日志方案) | | 镜像 | 腾讯云 CCR `ccr.ccs.tencentyun.com/vita/*` | ``` 客户端 ├─ https://www. → Traefik → vita-web(前端) └─ https://api. → Traefik → vita-gateway → 各微服务 监控:https://grafana. 或 Manager:3000 外部:阿里云 RDS · OSS · SLS · 邮件推送 ``` ### 集群角色 | 角色 | 标签 / Swarm | 部署内容 | |------|--------------|----------| | Manager(1 台) | `manager` | Traefik、监控全栈 | | 中间件(1 台) | `role=infra` | Redis、Nacos、Redis Exporter | | 业务池(≥1 台,可扩) | `role=worker` | 5 个微服务 + 前端(自动 spread / 故障漂移) | 共用 overlay 网络:`vita-net`(`--attachable`)。 ### Stack 与文件 | Stack 名 | Compose 文件 | 内容 | |----------|--------------|------| | `vita-edge` | `docker-compose.traefik.yml` | Traefik 入口 | | `vita-infra` | `docker-compose.infra.yml` | Redis + Nacos | | `vita-business` | `docker-compose.business.yml` | 5 个微服务 | | `vita-frontend` | `docker-compose.frontend.yml` | 前端 nginx | | `vita-monitoring` | `docker-compose.monitoring.yml` | 监控全栈 | 配置模板在 `vita_server_swarm_deploy/config/`,运行时同步到 Manager 宿主机 `/opt/deploy/monitor/`。 ### 首次上线(Manager 上执行) ```bash # 1) 初始化集群(仅首次) docker swarm init --advertise-addr docker network create --driver overlay --attachable vita-net # 各节点 join 后打标签:role=infra / role=worker # 2) 改 compose 占位符(密码、域名、RDS、镜像 tag、ACME 邮箱等) # 3) 同步监控配置到 /opt/deploy/monitor/ # 4) 按顺序 deploy cd vita_server_swarm_deploy docker stack deploy -c docker-compose.traefik.yml vita-edge docker stack deploy -c docker-compose.infra.yml vita-infra --with-registry-auth docker stack deploy -c docker-compose.business.yml vita-business --with-registry-auth docker stack deploy -c docker-compose.frontend.yml vita-frontend --with-registry-auth docker stack deploy -c docker-compose.monitoring.yml vita-monitoring --with-registry-auth ``` ### 日常发布与运维 | 场景 | 做法 | |------|------| | **改配置后对齐整栈** | 改对应 compose → `docker stack deploy -c --with-registry-auth`(声明式,有差异才滚动更新) | | **只升级某个服务镜像** | `docker service update --image ccr.../vita-gateway:NEW_TAG vita-business.vita-gateway`(滚动 + 失败可自动回滚) | | **扩缩容副本** | `docker service scale vita-business.vita-gateway=3`;扩容后请同步改 compose 里 `replicas`,避免下次 deploy 被打回 | | **加业务机器** | 新机 `swarm join` → 打 `role=worker` → `scale` 提高副本;Traefik / Prometheus 自动发现,无需改路由与抓取配置 | | **回滚** | `docker service rollback vita-business.` | | **看状态 / 日志** | `docker service ls` · `docker service ps ` · `docker service logs -f` | > **`stack deploy` vs `service update`**:前者以 compose 为真相源,适合正式发版与多服务同步;后者改单个服务运行态,适合应急换镜像/调参,事后应回写 compose,避免漂移。 ### 访问与健康 | 入口 | 地址 | |------|------| | 前端 | `https://www.` | | API | `https://api.`(经 gateway) | | Grafana | `https://grafana.` 或 `http://:3000` | | Nacos | `http://:8848/nacos` | | Prometheus / Alertmanager | Manager `:9090` / `:9093` | 各服务健康检查:`GET /health/check`。Prometheus 用 Swarm DNS(`tasks.`)自动发现副本,扩缩容与漂移后无需改抓取配置。 ## 生产日志收集方案(Logtail → SLS) 生产环境推荐 **阿里云 Logtail 采集 Docker 容器日志 → 日志服务 SLS** 集中存储与检索。业务代码**无需接入 SLS SDK**,沿用 SLF4J + Logback 输出到 stdout 即可。 ### 方案选型 | 方案 | 说明 | Vita 生产 | |------|------|-----------| | **Logtail → SLS** | 阿里云官方 Agent,内网上传,按写入量计费 | ✅ 推荐 | ### 采集架构 ``` Spring Boot (SLF4J/Logback) │ stdout/stderr ▼ Docker json-file 驱动 → /var/lib/docker/containers//-json.log │ ▼ Logtail (ilogtaild,每台 ECS 安装) │ 增量读取、压缩、断点续传 ▼ 内网 HTTPS(同地域免外网流量费) 阿里云 SLS Logstore (vita-app) │ ├── 控制台 / SQL 检索 └── 智能告警 → 钉钉 Webhook ``` **采集范围**(生产部署 IM 可不启动时): | 容器名 | 服务 | 端口 | |--------|------|------| | `vita-gateway` | 网关 | 8888 | | `vita-auth-center` | 认证中心 | 8033 | | `vita-file` | 文件 | 8023 | | `vita-message` | 消息 | 8043 | | `vita-life` | 生活 | 8063 | 日志中已透传 `traceId`(`TraceFilter` / MDC),可在 SLS 按 traceId 串联网关与下游服务。 ### 计费说明(按写入数据量,Logstore 默认模式) | 计费项 | 单价 | Vita 说明 | |--------|------|-----------| | **原始写入数据量** | 0.4 元/GB | **主要费用** | | 30 天内存储 | 免费 | 保留 7~15 天即可 | | ECS 内网上传 | 免费 | Logtail 与 SLS 同地域 | | 查询 / 智能告警 | 通常不另收费 | 该计费模式下 | 粗估月费:**优化后 ¥1~2 / 默认 ¥3~5**(视日志量与探活频率)。 ### 接入步骤 #### 1. 创建 SLS 资源 ``` 阿里云控制台 → 日志服务 SLS → 创建 Project:vita-prod(地域与 ECS 相同,如 cn-hangzhou) → 创建 Logstore:vita-app → 计费模式:按写入数据量 → 数据保留:7~15 天(排障够用,控制成本) ``` #### 2. 创建机器组 ``` 日志服务 → 机器组 → 创建 名称:vita-ecs-group 机器标识:IP 地址 添加所有 ECS 内网 IP(如 10.0.0.1 ~ 10.0.0.4) ``` #### 3. 安装 Logtail(每台 ECS 执行一次) 在 SLS 控制台「机器组 → 安装 Logtail」复制脚本,或: ```bash # 将 cn-hangzhou 替换为 Project 所在地域 wget http://logtail-release-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/linux64/logtail.sh -O logtail.sh chmod +x logtail.sh sudo ./logtail.sh install cn-hangzhou ``` 验证: ```bash sudo /etc/init.d/ilogtaild status # 期望:ilogtaild is running ``` 在 SLS 控制台确认机器组内各节点 **心跳正常**。 #### 4. 配置日志采集(Docker 标准输出) ``` 日志服务 → Project vita-prod → Logstore vita-app → 数据接入 → Docker 标准输出 机器组:vita-ecs-group 容器名正则:vita-.* 解析模式:单行文本(默认) ``` 保存后等待 1~2 分钟,在 Logstore「查询分析」中应能看到容器日志。 #### 5. Docker 日志轮转(Swarm Stack) 各 Vita 服务建议统一 logging 配置,防止占满 ECS 磁盘(与 SLS 采集并行): ```yaml logging: driver: json-file options: max-size: "50m" max-file: "5" compress: "true" ``` 参考:`vita_server_swarm_deploy/docker-compose.business.yml`(及 frontend / infra 等同目录文件)。 #### 6. 生产日志级别建议(Nacos `prod` 各服务 yml) ```yaml logging: level: root: INFO com.vita: INFO ``` **健康检查** `GET /health/check` 建议使用 `DEBUG` 级别输出,避免 Prometheus / 负载均衡高频探活产生大量无效 INFO 日志(显著增加 SLS 写入量)。 #### 7. SLS 查询示例 ```sql -- gateway 错误日志 container_name: vita-gateway and ERROR -- 异常堆栈 * and Exception -- 按 traceId 查全链路(将 xxx 换为实际 traceId) * and xxx -- 各服务 5 分钟内错误数 * | SELECT container_name, count(*) AS cnt WHERE content LIKE '%ERROR%' OR content LIKE '%Exception%' GROUP BY container_name ``` #### 8. 告警(SLS 智能告警) ``` SLS → 告警 → 新建 名称:vita-error-spike 查询: * | WHERE content LIKE '%ERROR%' OR content LIKE '%Exception%' OR content LIKE '%OutOfMemoryError%' 条件:5 分钟内超过 20 条 通知对象:钉钉机器人 Webhook(推荐,免短信费) ``` ### 验证清单 - [ ] 每台 ECS `ilogtaild` 运行中,机器组心跳正常 - [ ] 访问一次 API 后,SLS 能搜到 `vita-gateway` 日志 - [ ] 各服务容器名均匹配 `vita-.*` 规则 - [ ] 测试告警能送达钉钉 - [ ] 账单中计费项以「原始写入数据量」为主(确认未误用「按使用功能」模式) ### 注意事项 1. **无需改 Java 代码**:不引入 SLS SDK;后续可选 JSON 日志布局便于字段检索。 2. **地域一致**:Project 与 ECS 同地域,走内网,上传不计外网流量费。 3. **一个 Logstore 即可**:不要重复采集同一容器到多个 Logstore。 4. **与指标监控分工**:日志走 SLS;CPU/内存/JVM 走 Prometheus + Grafana 或 ECS 云监控(见运维文档)。 ## 开发状态 | 模块 | 状态 | |------|------| | common / gateway / auth-center / file / message / life | ✅ 可用 | | vita-im | ⚠️ 基础 WebSocket(广播/ACK),私聊与持久化待完善 | **待完善**:IM 点对点消息与文件传输、菜单运维 CRUD 接口。 ## 接口加解密(RSA + AES-GCM) 客户端与网关之间对敏感接口启用**应用层加密**,算法为 **RSA-2048(密钥交换)+ AES-256-GCM(数据体)**。单次 HTTP 请求生成一个临时 AES 会话密钥,**上行与下行复用同一密钥**。 ### 架构 ``` 客户端 │ ① GET /auth/crypto/publicKey(明文,auth-center 签发 RSA 密钥对,私钥存 Redis) │ ② 生成 AES 会话密钥 K │ ③ Header: X-Encrypt-Key = RSA(服务端公钥, Base64(K)&Base64(IV)) │ ④ Body: { "data": AES(K, 请求 JSON) } ▼ vita-gateway │ CryptoFilter(order=+30):RSA 解 K → AES 解 body → 下游明文 │ 业务微服务处理 │ CryptoFilter 响应包装:AES(K, 响应 JSON) ▼ 客户端用同一 K 解密响应 ``` ### 网关过滤器顺序 | 顺序 | order | 过滤器 | 职责 | |------|-------|--------|------| | 1 | +0 | TraceFilter | traceId | | 2 | +10 | UrlTokenToHeaderFilter | WebSocket token 转 Header | | 3 | +20 | RateLimitFilter | 白名单 IP 限流 | | 4 | +30 | **CryptoFilter** | 请求解密 + 响应加密 | | 5 | +40 | AuthFilter | Token + 权限(公钥接口在 sys_api_resource 注册为 common:white) | | 6 | +50 | UserRateLimitFilter | 已登录 userId 限流 | ### 请求头协议 | Header | 说明 | |--------|------| | `X-Encrypt-Enabled` | 响应头:`true` 表示响应体已加密 | | `X-Encrypt-Key` | Base64(RSA-OAEP-SHA256( Base64(aesKey)&Base64(iv) )) | | `X-Encrypt-Key-Id` | 服务端 RSA 密钥版本 | | `X-Encrypt-Timestamp` | 毫秒时间戳(防重放) | | `X-Encrypt-Nonce` | UUID(Redis 一次性校验) | ### 业务错误码 | code | 含义 | 客户端处理 | |------|------|------------| | 407 | 请求解密失败 | 提示错误 | | 408 | 请求过期或重复提交 | 提示重试 | | **409** | **RSA 密钥不存在或已过期** | **清除公钥缓存 → 重新 GET /auth/crypto/publicKey → 重试 1 次** | RSA 私钥按 `keyId` 写入 Redis(`crypto:rsa:{keyId}`),过期后解密返回 409。 ### 涉及模块 | 模块 | 类 | 职责 | |------|-----|------| | vita-common | `CryptoUtil` / `CryptoService` / `RsaKeySupport` / `RsaKeyIssuer` / `RsaKeyDecryptor` | 加解密核心 | | vita-auth-center | `RedisRsaKeyIssuer` / `AuthCenterCryptoAutoConfiguration` | RSA 公钥签发 | | vita-auth-center | `CryptoController` | `GET /auth/crypto/publicKey` | | vita-gateway | `RedisRsaKeyDecryptor` / `GatewayCryptoAutoConfiguration` | 请求解密 + 防重放 | | vita-gateway | `CryptoFilter` | 请求解密、响应加密 | | vita-gateway | `GatewayExceptionHandler` | 统一返回 407/408/409 | ### 登录接口示例 ``` POST /auth/user/login X-Encrypt-Enabled: true X-Encrypt-Key-Id: vita-demo Body: { "data": "" } 解密后明文: { "email": "user@qq.com", "password": "" } ``` 下游 `AuthController` / `UserFacadeImpl` **无需改动**,网关解密后仍为标准 `LoginDTO`。 ## 客户端 | 端 | 名称 | 说明 | |----|------|------| | Web 管理端 | [此生 · 管理台](https://gitee.com/edwarddamon/vita-web)(vita-web) | RBAC、礼金运维、邮件与文件管理 | | 微信小程序 | **此生录** | 个人生活记录与提醒(C 端) |