尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

SpringBoot微服务搭建冥想助眠平台:音频资源、用户日志、付费套餐模块拆分与 TaoToken 统一 Key 配置

SpringBoot微服务搭建冥想助眠平台:音频资源、用户日志、付费套餐模块拆分与 TaoToken 统一 Key 配置 1. 从单体到微服务冥想助眠平台为什么要拆冥想助眠平台在早期用单体 SpringBoot 项目跑起来很舒服一个 jar 包音频上传、播放记录、会员套餐全塞在一起本地mvn spring-boot:run就能演示。但用户量一上来问题就集中爆发了。音频流接口被日志写入拖慢、套餐规则改一行要重新部署整个应用、日志表数据量暴涨把核心库的查询性能拉垮——这些都是单体架构的典型症状。我试过在一个单体项目里同时维护这三条业务线最直观的感受是改付费逻辑时不敢动日志代码怕牵连播放接口。所以这次我们把平台拆成三个核心微服务音频资源服务负责音频的上传、分类、上下架和流媒体播放用户日志服务承接登录、播放、打卡等行为日志的异步落库与统计付费套餐服务独立管理会员套餐、订单、权限校验和有效期。三者各自持有独立数据库通过一个轻量网关统一对外暴露接口。这套方案适合谁适合正在做课程设计、毕业设计或者想把单体项目重构为微服务的中级开发者。技术栈只用到 SpringBoot、Spring MVC、MyBatis-Plus 和 Maven不引入 Nacos、Sentinel 这类重型中间件落地成本低。同时我们会在每个服务里通过 TaoToken 统一配置 AI 能力的 Key 和 API 通道让音频摘要生成、日志异常分析、套餐推荐这些智能化功能有一个统一的接入点而不是每个服务各写一套密钥管理。下面按模块拆分、配置骨架、统一 Key 接入、启动验证、排障的顺序展开每一步都给可复制的代码和命令。2. TaoToken 前置统一 Key 与 API 通道准备在拆微服务之前先把 AI 能力的接入方式定下来。三个服务如果各自去申请 Key、各自维护请求地址后期换通道或轮换密钥会非常痛苦。TaoToken 的作用就是提供一个统一的 API 入口你只需要在平台侧生成一个 Key然后在各服务的配置里引用同一个环境变量即可。你需要先拿到两样东西一个是 API Key一个是统一的请求地址。Key 在控制台的 API Keys 页面创建地址固定为https://taotoken.net/api。创建 Key 的入口在这里控制台 API Keyshttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite拿到 Key 之后不要硬编码进application.yml而是通过环境变量注入。这样三个微服务可以共用同一个 Key本地开发和容器部署都不需要改代码。如果你还想先验证模型是否可用可以直接在模型对话页面测试一次请求模型对话https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite对于长期做编码和 Agent 场景的读者Coding Plan 提供了更稳定的调用额度适合把 AI 能力嵌进日常开发流程Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite接入文档里有完整的请求格式和参数说明配置前建议先扫一遍接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite准备好 Key 之后我们进入项目结构搭建。3. 可复制配置三服务骨架与统一 Key 注入3.1 父工程与模块划分父pom.xml用dependencyManagement统一版本子模块只声明依赖不写版本号。目录结构如下meditation-platform ├── pom.xml ├── common-core # 公共返回、异常、常量 ├── gateway-service # 网关 ├── audio-service # 音频资源 ├── log-service # 用户日志 └── package-service # 付费套餐父工程关键片段modules modulecommon-core/module modulegateway-service/module moduleaudio-service/module modulelog-service/module modulepackage-service/module /modules properties spring-boot.version2.7.18/spring-boot.version mybatis-plus.version3.5.5/mybatis-plus.version /properties3.2 音频资源服务 application.yml音频服务端口设为 8081独立数据库meditation_audio同时预留 AI 摘要生成的配置项server: port: 8081 spring: application: name: audio-service datasource: url: jdbc:mysql://127.0.0.1:3306/meditation_audio?useUnicodetruecharacterEncodingutf8 username: root password: ${DB_PASSWORD:root} driver-class-name: com.mysql.cj.jdbc.Driver mybatis-plus: mapper-locations: classpath*:/mapper/**/*.xml configuration: map-underscore-to-camel-case: true ai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} model: gpt-4o-mini timeout: 150003.3 用户日志服务 application.yml日志服务端口 8082数据库meditation_log重点是异步线程池配置避免日志写入阻塞播放请求server: port: 8082 spring: application: name: log-service datasource: url: jdbc:mysql://127.0.0.1:3306/meditation_log?useUnicodetruecharacterEncodingutf8 username: root password: ${DB_PASSWORD:root} task: execution: pool: core-size: 4 max-size: 16 queue-capacity: 200 ai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} model: gpt-4o-mini3.4 付费套餐服务 application.yml套餐服务端口 8083数据库meditation_package权限校验逻辑独立server: port: 8083 spring: application: name: package-service datasource: url: jdbc:mysql://127.0.0.1:3306/meditation_package?useUnicodetruecharacterEncodingutf8 username: root password: ${DB_PASSWORD:root} ai: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} model: gpt-4o-mini3.5 config.toml 骨架如果你用外部配置中心或本地 TOML 管理环境变量可以这样写。注意 Key 从环境变量读取不落盘明文[app] name meditation-platform env dev [ai] base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} model gpt-4o-mini timeout_ms 15000 [services] audio_port 8081 log_port 8082 package_port 80833.6 统一 AI 客户端封装在common-core里写一个AiClient三个服务共用避免重复代码Component public class AiClient { Value(${ai.base-url}) private String baseUrl; Value(${ai.api-key}) private String apiKey; Value(${ai.model}) private String model; private final RestTemplate restTemplate new RestTemplate(); public String chat(String prompt) { HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); headers.setBearerAuth(apiKey); MapString, Object body new HashMap(); body.put(model, model); body.put(messages, List.of(Map.of(role, user, content, prompt))); HttpEntityMapString, Object entity new HttpEntity(body, headers); ResponseEntityString resp restTemplate.postForEntity( baseUrl /v1/chat/completions, entity, String.class); return resp.getBody(); } }这样音频服务可以用它生成音频简介日志服务可以用它分析异常模式套餐服务可以用它做推荐文案而 Key 只有一个来源。4. 启动验证与接口连通性检查4.1 设置环境变量并启动先导出 Key再依次启动三个服务。Linux/macOSexport TAOTOKEN_API_KEY你的Key export DB_PASSWORD你的数据库密码 mvn -pl audio-service spring-boot:runWindows PowerShell$env:TAOTOKEN_API_KEY你的Key $env:DB_PASSWORD你的数据库密码 mvn -pl audio-service spring-boot:run三个服务分别启动后控制台应看到Started AudioServiceApplication、Started LogServiceApplication、Started PackageServiceApplication。4.2 接口连通性检查用 curl 逐个验证。音频服务查询接口curl -s http://127.0.0.1:8081/audio/list?page1size5预期返回统一格式{code:200,msg:请求成功,data:{total:0,records:[]}}日志服务写入接口curl -s -X POST http://127.0.0.1:8082/log/play \ -H Content-Type: application/json \ -d {userId:1001,audioId:2001,playDuration:180}套餐权限校验接口curl -s http://127.0.0.1:8083/package/auth?userId1001audioLevel2返回{code:200,data:false}表示该用户无会员权限逻辑正确。4.3 验证 AI 通道是否打通在任意服务里加一个测试端点调用AiClient.chatGetMapping(/ai/ping) public ResultUtil aiPing() { String reply aiClient.chat(用一句话介绍冥想助眠); return ResultUtil.success(reply); }请求http://127.0.0.1:8081/ai/ping如果返回包含模型回复内容说明 TaoToken 的 Key 和 API 通道配置成功。若返回 401检查环境变量是否生效若超时检查timeout配置和网络出口。5. 本篇常见错排查启动报Table meditation_audio.xxx doesnt exist三个服务连的是不同数据库确认每个库都执行了对应的建表 SQL不要三个服务共用一个库。日志服务写入阻塞播放接口检查Async是否生效。需要在启动类加EnableAsync并且recordPlayLog方法必须是public同类内部调用不会走代理。AI 请求返回 401 Unauthorized最常见的原因是环境变量没导出就启动了服务或者application.yml里写的是${TAOTOKEN_API_KEY}但变量名拼错。用echo $TAOTOKEN_API_KEY确认。端口冲突导致服务起不来8081/8082/8083 被占用时改server.port即可但记得同步改网关路由配置。MyBatis-Plus 查询返回字段为 null检查实体类字段和数据库列的下划线映射map-underscore-to-camel-case: true要开启或者用TableField显式指定。网关转发 404确认网关路由的uri指向http://127.0.0.1:8081这类具体地址而不是服务名没有注册中心时服务名无法解析。套餐权限校验始终返回 false检查selectValidPackage的 SQL 条件通常要过滤status1且expire_time now()否则过期套餐也会被查出来。排障时如果怀疑是 Key 或通道问题可以直接去 API Keys 页面重新生成一个 Key 对比测试API Keyshttps://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入细节和请求参数以官方文档为准接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite6. 按场景选择接入方式三个微服务跑起来之后AI 能力的接入点其实分几种场景。如果你只是想在音频服务里做简介生成、在日志服务里做异常摘要直接用统一的 API Key 加AiClient就够了这是最轻量的方式。如果你要验证某个模型对中文冥想文案的效果先去模型对话页面手动测几轮确认输出风格再写进代码模型对话https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite如果你打算把 AI 能力长期嵌进编码流程比如让 Agent 自动生成 Mapper、自动补全套餐校验逻辑那 Coding Plan 的额度模型更适合不用每次调用都担心临时额度Coding Planhttps://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite统一 Key 的好处在这里体现得很明显三个服务、多个场景只需要维护一个环境变量。后续要换模型或调整超时改一处配置三个服务同时生效。这套骨架跑通之后你可以继续往上加打卡服务、睡眠评分服务每个新服务复用common-core里的AiClient和统一返回封装扩展成本很低。
返回列表