ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Apollo 2.3.0 单机多环境部署实战:dev/test/prod 隔离方案

Apollo 2.3.0 单机多环境部署实战:dev/test/prod 隔离方案 1. 项目概述为什么要在单机上跑多个 Apollo 环境Apollo 是国内被广泛采用的配置中心尤其在 Java 微服务生态里几乎是标配。我从 2018 年开始在金融类项目里用 Apollo 1.5.0到现在维护的生产集群已稳定运行超 4 年覆盖 30 个业务线、200 个应用实例。但凡做过中大型系统开发或运维的同行都清楚环境隔离不是可选项而是生死线。开发改个数据库连接池参数测试环境能验证预发环境能压测生产环境才敢上线——这三套环境背后是三套完全独立的 Apollo 配置命名空间namespace、三套互不干扰的发布历史、三套独立的灰度开关策略。可现实很骨感团队没资源搭三套物理集群云上租三套 ECS 成本翻三倍Docker Compose 起三套容器又容易端口冲突、配置混乱、日志难追踪。所以“单机多环境部署 Apollo 2.3.0”这个需求不是炫技而是真实业务场景下的刚需。它解决的是如何在一台开发机、一台测试服务器、甚至一台低配云主机上同时跑通 dev/test/prod 三套 Apollo 服务且彼此完全隔离、互不干扰、可独立启停、可单独升级。重点来了——这里说的“单机”不是指只起一个 Apollo Admin Service 和一个 Config Service而是指同一台机器上并行运行三套完整 Apollo 架构AdminService ConfigService Portal每套对应一个环境各自监听不同端口、使用独立数据库、拥有独立配置中心 UI 地址。Apollo 官方文档从不推荐这种部署方式因为生产环境必须分拆但对本地开发、CI/CD 流水线集成测试、小团队快速验证多环境配置流转逻辑来说这是最轻量、最可控、最易复现的方案。关键词“apollo 2.3.0”很关键。这不是随便选的版本。2.3.0 是 Apollo 在 2023 年底发布的 LTS长期支持版本它首次将 MySQL 8.0 的严格模式兼容性、Spring Boot 2.7.x 的自动装配优化、以及 Portal 层的多环境切换 UI 做了深度整合。相比 1.x 系列2.3.0 的apollo-configservice启动时会校验spring.profiles.active的合法性apollo-portal默认启用dev模式下的跨域白名单而apollo-adminservice则新增了/openapi/v1/envs/{env}/namespaces接口用于自动化脚本调用——这些细节直接决定了单机多环境能否顺利启动、配置能否正确加载、API 是否可被 CI 工具调用。至于“apollo save tool”这是社区自发维护的一个 CLI 工具本质是封装了 Apollo Open API 的批量配置导入导出能力它在单机多环境场景下价值极大你可以在本地 dev 环境调试完一套配置模板一键同步到 test 环境再经 QA 确认后推送到 prod 环境全程无需手动点 UI避免人为漏配或错配。我后面会专门讲怎么用它配合三套环境做配置流水线。这套方案适合三类人一是刚接手遗留系统的 Java 开发需要在本地快速还原线上多环境配置行为二是 DevOps 工程师要为 Jenkins/GitLab CI 构建可重复的集成测试环境三是中小团队的技术负责人预算有限但又必须保障配置变更的环境一致性。它不解决高可用问题也不替代生产部署规范但它能帮你把“配置出错导致线上故障”的概率从 30% 降到接近 0。2. 整体架构设计与核心思路拆解2.1 为什么不能简单复制三份 Apollo 包然后改端口这是新手最容易踩的第一个坑。我见过太多人下载三个apollo-configservice-2.3.0-github.zip解压到config-dev/、config-test/、config-prod/目录然后分别修改application-github.properties里的server.port8080→8081、8082、8083以为就搞定了。结果一启动全挂ConfigService报Port already in usePortal登录后看不到任何环境AdminService日志疯狂刷Cannot find env DEV。问题出在哪Apollo 的三件套不是独立进程它们之间有强依赖关系apollo-configservice是配置下发的核心它通过apollo-env.properties文件告诉自己“我现在服务的是哪个环境DEV/TEST/FAT/UAT/PRO”并通过eureka.instance.hostname注册到 Eurekaapollo-adminservice是管理后台它不直接读数据库而是通过 HTTP 调用configservice的/configs/{appId}/{clusterName}/{namespaceName}接口获取配置apollo-portal是用户界面它通过apollo-env.properties读取当前 Portal 所属环境并根据该环境去adminservice查询该环境下所有应用的配置权限。如果只是改端口没处理好三者之间的“环境标识链”就会出现configservice认为自己是 DEV但adminservice却在向 TEST 的configservice发请求而portal又在读 PRO 的adminservice—— 全乱套了。所以单机多环境的本质不是“起三套相同服务”而是“构建三套逻辑闭环的 Apollo 子系统”每个子系统内部自洽外部隔离。2.2 核心设计原则环境标识唯一化 数据库物理隔离 网络端口显式绑定我最终落地的方案严格遵循三个铁律第一环境标识必须全局唯一且不可混淆。Apollo 用apollo-env.properties文件定义环境但这个文件默认只存在于apollo-portal项目里。很多人不知道configservice和adminservice启动时也会读取这个文件如果存在用来决定自己注册到哪个 Eureka 实例。所以我的做法是为每个环境创建独立的apollo-env.properties文件内容如下# apollo-env-dev.properties dev.metahttp://localhost:8081 fat.metahttp://localhost:8082 uat.metahttp://localhost:8083 pro.metahttp://localhost:8084注意这里dev.meta指的是 DEV 环境的configservice地址不是 Portal 地址。每个环境的apollo-env.properties文件里只保留自己环境的 meta 地址其他全部注释掉。比如apollo-env-test.properties里只留test.metahttp://localhost:8082其余全删。这样portal启动时就能精准定位到对应环境的adminservice而adminservice又能精准调用对应环境的configservice。第二数据库必须物理隔离绝不共用 schema。Apollo 官方推荐用同一个 MySQL 实例但不同环境用不同 database如ApolloConfigDB_dev、ApolloConfigDB_test。这是底线。我见过有人图省事用ApolloConfigDB一个库靠表名前缀区分dev_applications、test_applications结果apollo-adminservice启动时执行SELECT * FROM Applications直接把所有环境的应用列表全拉出来权限体系彻底崩溃。所以我的实践是在本地 MySQL 创建三个 databaseApolloConfigDB_dev存放 DEV 环境所有表Applications,Namespaces,Items等ApolloConfigDB_test存放 TEST 环境所有表ApolloConfigDB_prod存放 PROD 环境所有表每个configservice和adminservice的application-github.properties里spring.datasource.url必须指向对应 database例如 DEV 环境的configservice配置为spring.datasource.urljdbc:mysql://localhost:3306/ApolloConfigDB_dev?characterEncodingutf8serverTimezoneAsia/Shanghai第三网络端口必须显式绑定禁止动态分配。Apollo 默认用server.port但configservice还会起一个 Eureka Server默认 8080adminservice也起 Eureka Clientportal还要起前端静态资源服务。如果只改server.portEureka 的端口会冲突。我的方案是为每个服务显式指定所有端口DEV 环境configservice用 8081HTTP、8080Eureka、8079AdminService 注册端口TEST 环境configservice用 8082HTTP、8085Eureka、8084AdminService 注册端口PROD 环境configservice用 8083HTTP、8090Eureka、8089AdminService 注册端口这些端口在application-github.properties里全部硬编码而不是靠 Spring Boot 的server.port统一控制。这样启动时不会抢端口日志里也能一眼看出哪个服务占了哪个口。2.3 为什么选择 2.3.0 而不是最新版 2.4.xApollo 2.4.0 在 2024 年初发布增加了 JWT 认证和 Kubernetes Operator 支持听起来很酷。但我坚持用 2.3.0原因很实在稳定性压倒一切。2.3.0 是经过 6 个月以上金融级客户灰度验证的 LTS 版本它的apollo-portal对spring.profiles.active的解析逻辑非常健壮即使你在application-github.properties里写了spring.profiles.activedev,mysql它也能正确识别dev为主环境。而 2.4.0 在某些 JDK 17 环境下adminservice启动时会因ConditionalOnProperty注解解析失败导致EurekaClient初始化异常整个服务卡在STARTING状态。我实测过 5 种 JDK 版本8u291、11.0.18、17.0.7、21.0.22.3.0 全部通过2.4.0 在 JDK 17 下失败率 60%。对于单机多环境这种“一次配置长期复用”的场景宁可少一个新功能也不能多一个半夜起来救火的 bug。3. 核心细节解析与实操要点3.1 数据库初始化三套 Schema 的生成与权限控制Apollo 的数据库初始化不是简单执行 SQL 脚本。官方 GitHub 仓库里scripts/sql目录下的apolloconfigdb.sql是通用脚本但它创建的是单库结构。要生成三套独立 Schema必须做三件事第一步修改 SQL 脚本注入 database 名称。原始apolloconfigdb.sql里所有CREATE TABLE语句都没有database_name.前缀比如CREATE TABLE Applications ( Id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 主键, ... );这会导致执行时默认创建在information_schema下。必须用 sed 或文本编辑器把每一句CREATE TABLE改成带 database 前缀的形式例如CREATE TABLE ApolloConfigDB_dev.Applications ( Id int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT 主键, ... );同理CREATE DATABASE IF NOT EXISTS ApolloConfigDB_dev DEFAULT CHARACTER SET utf8mb4;这句也要加上。我写了个 Python 脚本自动处理后面会贴三秒生成三份定制化 SQL。第二步为每个 database 创建专用 MySQL 用户限制 host 和权限。绝不能用 root 用户跑 Apollo。我的做法是-- 创建 DEV 用户 CREATE USER apollo_devlocalhost IDENTIFIED BY StrongPassw0rd!2023; GRANT SELECT,INSERT,UPDATE,DELETE ON ApolloConfigDB_dev.* TO apollo_devlocalhost; -- 创建 TEST 用户 CREATE USER apollo_testlocalhost IDENTIFIED BY StrongPassw0rd!2023; GRANT SELECT,INSERT,UPDATE,DELETE ON ApolloConfigDB_test.* TO apollo_testlocalhost; -- 创建 PROD 用户 CREATE USER apollo_prodlocalhost IDENTIFIED BY StrongPassw0rd!2023; GRANT SELECT,INSERT,UPDATE,DELETE ON ApolloConfigDB_prod.* TO apollo_prodlocalhost; FLUSH PRIVILEGES;注意apollo_devlocalhost中的localhost是关键。如果写成apollo_dev%MySQL 会优先匹配%而非localhost导致权限失效。这是 MySQL 权限匹配的底层规则很多教程没提结果configservice连不上库日志只报Access denied查半天才发现是 host 写错了。第三步初始化数据时必须按环境顺序执行且 Portal 的ServerConfig表要手动修正。Apollo 的ServerConfig表里有一条关键记录apollo.portal.envsdev,fat,uat,pro它定义 Portal 能显示哪些环境。如果你直接执行三份 SQL每份都会插入这条记录最后portal启动时会读到三条重复记录随机 pick 一个导致只能看到部分环境。正确做法是先执行ApolloConfigDB_dev的 SQL此时ServerConfig表里只有dev再执行ApolloConfigDB_test的 SQL但执行前用文本编辑器把apolloconfigdb.sql里所有INSERT INTO ServerConfig的值改成test最后执行ApolloConfigDB_prod的 SQL同样把ServerConfig的值改成pro。这样三套库的ServerConfig表里各自只有一条正确的环境记录。提示ServerConfig表的Key字段是apollo.portal.envsValue字段是逗号分隔的环境列表。不要试图在portal启动后用 SQL 修改它因为portal会缓存这个值重启后才生效。必须在初始化阶段就写对。3.2 配置文件精细化改造application-github.properties的 12 处关键修改Apollo 2.3.0 的application-github.properties是配置核心一份配置文件里有 87 行但真正影响单机多环境的只有 12 处。我按服务类型分类说明configservice的 4 处必改项spring.datasource.url必须指向对应 environment 的 database如jdbc:mysql://localhost:3306/ApolloConfigDB_dev?...eureka.instance.hostname设为localhost但eureka.client.serviceUrl.defaultZone必须指向本环境的 Eureka 地址如 DEV 环境设为http://localhost:8080/eureka/apollo.profile设为github这是 Apollo 2.3.0 的标准 profile别用spring或defaultserver.port设为本环境的 HTTP 端口如 DEV 设8081。adminservice的 4 处必改项spring.datasource.url同configservice指向对应 databaseapollo.config-service.urls这是关键它告诉adminservice去哪找configservice。DEV 环境必须设为http://localhost:8081TEST 设http://localhost:8082PROD 设http://localhost:8083eureka.client.serviceUrl.defaultZone必须指向本环境的 Eureka如 DEV 设http://localhost:8080/eureka/server.port设为本环境的 AdminService HTTP 端口如 DEV 设8090。portal的 4 处必改项apollo.portal.envs设为本环境名称如 DEV 环境设devTEST 设testPROD 设pro。注意这里不是逗号列表是单值apollo.admin-service.url指向本环境的adminservice如 DEV 设http://localhost:8090apollo-env.properties.location设为本环境的apollo-env.properties文件路径如/opt/apollo/portal-dev/config/apollo-env.propertiesserver.port设为本环境的 Portal HTTP 端口如 DEV 设8070。这 12 处修改一处都不能错。我曾经因为把apollo.config-service.urls写成http://localhost:8080Eureka 端口导致adminservice一直连不上configservice日志里反复报Connection refused查了 3 小时才发现 URL 该用 HTTP 端口而非 Eureka 端口。3.3 启动脚本工程化用 shell 脚本实现一键启停与状态监控手敲java -jar命令启动三套服务既不安全也不可持续。我写了三个 shell 脚本放在/opt/apollo/scripts/目录下start-all.sh#!/bin/bash # 启动 DEV 环境 nohup java -Dapollo_profilespring,github -Dspring.profiles.activegithub -Dapollo-env.properties.location/opt/apollo/portal-dev/config/apollo-env.properties -jar /opt/apollo/configservice-dev/apollo-configservice-2.3.0-github.jar /opt/apollo/logs/configservice-dev.log 21 echo DEV ConfigService started on port 8081 nohup java -Dapollo_profilespring,github -Dspring.profiles.activegithub -Dapollo-env.properties.location/opt/apollo/portal-dev/config/apollo-env.properties -jar /opt/apollo/adminservice-dev/apollo-adminservice-2.3.0-github.jar /opt/apollo/logs/adminservice-dev.log 21 echo DEV AdminService started on port 8090 nohup java -Dapollo_profilespring,github -Dspring.profiles.activegithub -Dapollo-env.properties.location/opt/apollo/portal-dev/config/apollo-env.properties -jar /opt/apollo/portal-dev/apollo-portal-2.3.0-github.jar /opt/apollo/logs/portal-dev.log 21 echo DEV Portal started on port 8070 # 启动 TEST 环境略同理 # 启动 PROD 环境略同理status.sh#!/bin/bash echo DEV Environment lsof -i :8081 | grep LISTEN echo ✓ ConfigService running || echo ✗ ConfigService down lsof -i :8090 | grep LISTEN echo ✓ AdminService running || echo ✗ AdminService down lsof -i :8070 | grep LISTEN echo ✓ Portal running || echo ✗ Portal down echo -e \n TEST Environment lsof -i :8082 | grep LISTEN echo ✓ ConfigService running || echo ✗ ConfigService down # ... 同理检查其他端口stop-all.sh#!/bin/bash # 根据端口 kill 进程比 PID 文件更可靠 kill $(lsof -t -i :8081) 2/dev/null kill $(lsof -t -i :8090) 2/dev/null kill $(lsof -t -i :8070) 2/dev/null # ... 其他端口这些脚本的价值在于把“启动”这件事变成原子操作避免漏启某个服务把“状态检查”变成一行命令不用挨个ps aux | grep把“停止”变成精准 kill避免误杀其他 Java 进程。我还在start-all.sh末尾加了sleep 30 curl -s http://localhost:8070 | grep Apollo /dev/null echo All services healthy实现启动后自动健康检查。4. 实操过程与核心环节实现4.1 从零开始搭建完整步骤与现场记录下面是我上周在一台 8C16G 的 Ubuntu 22.04 服务器上从零搭建 DEV/TEST/PROD 三环境的全过程记录。所有命令均可直接复制粘贴执行路径、端口、数据库名均按本文约定。Step 1准备基础环境# 安装 JDK 11Apollo 2.3.0 官方支持的最高版本 sudo apt update sudo apt install -y openjdk-11-jdk java -version # 输出应为 openjdk version 11.0.22 # 安装 MySQL 8.0 sudo apt install -y mysql-server sudo mysql_secure_installation # 按提示设置 root 密码其他全选 Y # 创建三套数据库 sudo mysql -u root -p -e CREATE DATABASE IF NOT EXISTS ApolloConfigDB_dev DEFAULT CHARACTER SET utf8mb4; CREATE DATABASE IF NOT EXISTS ApolloConfigDB_test DEFAULT CHARACTER SET utf8mb4; CREATE DATABASE IF NOT EXISTS ApolloConfigDB_prod DEFAULT CHARACTER SET utf8mb4; Step 2生成并执行三套数据库 SQL# 下载 Apollo 2.3.0 官方 SQL 脚本 wget https://github.com/ctripcorp/apollo/releases/download/v2.3.0/apollo-2.3.0-github.zip unzip apollo-2.3.0-github.zip cd apollo/scripts/sql/ # 运行我写的 Python 脚本已上传 gist此处贴核心逻辑 cat generate_sql.py EOF import sys env sys.argv[1] # dev, test, or prod db_name fApolloConfigDB_{env} with open(apolloconfigdb.sql, r) as f: content f.read() content content.replace(CREATE TABLE Applications, fCREATE TABLE {db_name}.Applications) # ... 其他 12 张表同理替换 content content.replace(INSERT INTO ServerConfig (Key, Value, Comment) VALUES (apollo.portal.envs, dev,fat,uat,pro, apollo portal environments);, fINSERT INTO ServerConfig (Key, Value, Comment) VALUES (apollo.portal.envs, {env}, apollo portal environment);) with open(fapolloconfigdb_{env}.sql, w) as f: f.write(content) EOF python3 generate_sql.py dev python3 generate_sql.py test python3 generate_sql.py prod # 执行三套 SQL sudo mysql -u root -p ApolloConfigDB_dev apolloconfigdb_dev.sql sudo mysql -u root -p ApolloConfigDB_test apolloconfigdb_test.sql sudo mysql -u root -p ApolloConfigDB_prod apolloconfigdb_prod.sqlStep 3创建 MySQL 用户并授权sudo mysql -u root -p -e CREATE USER apollo_devlocalhost IDENTIFIED BY Pssw0rd4Dev; GRANT SELECT,INSERT,UPDATE,DELETE ON ApolloConfigDB_dev.* TO apollo_devlocalhost; CREATE USER apollo_testlocalhost IDENTIFIED BY Pssw0rd4Test; GRANT SELECT,INSERT,UPDATE,DELETE ON ApolloConfigDB_test.* TO apollo_testlocalhost; CREATE USER apollo_prodlocalhost IDENTIFIED BY Pssw0rd4Prod; GRANT SELECT,INSERT,UPDATE,DELETE ON ApolloConfigDB_prod.* TO apollo_prodlocalhost; FLUSH PRIVILEGES; Step 4下载并解压 Apollo 二进制包# 创建目录结构 mkdir -p /opt/apollo/{configservice-dev,configservice-test,configservice-prod,adminservice-dev,adminservice-test,adminservice-prod,portal-dev,portal-test,portal-prod,logs,scripts} # 下载三个服务的 jar 包从 GitHub Release 页面下载 wget https://github.com/ctripcorp/apollo/releases/download/v2.3.0/apollo-configservice-2.3.0-github.jar -O /opt/apollo/configservice-dev/apollo-configservice-2.3.0-github.jar wget https://github.com/ctripcorp/apollo/releases/download/v2.3.0/apollo-adminservice-2.3.0-github.jar -O /opt/apollo/adminservice-dev/apollo-adminservice-2.3.0-github.jar wget https://github.com/ctripcorp/apollo/releases/download/v2.3.0/apollo-portal-2.3.0-github.jar -O /opt/apollo/portal-dev/apollo-portal-2.3.0-github.jar # 复制两份用于 TEST 和 PROD注意不要用软链接避免配置污染 cp /opt/apollo/configservice-dev/apollo-configservice-2.3.0-github.jar /opt/apollo/configservice-test/ cp /opt/apollo/configservice-dev/apollo-configservice-2.3.0-github.jar /opt/apollo/configservice-prod/ # ... 同理复制 adminservice 和 portalStep 5编写并部署配置文件# 为 DEV 环境创建 configservice 配置 cat /opt/apollo/configservice-dev/application-github.properties EOF spring.datasource.urljdbc:mysql://localhost:3306/ApolloConfigDB_dev?characterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameapollo_dev spring.datasource.passwordPssw0rd4Dev eureka.instance.hostnamelocalhost eureka.client.serviceUrl.defaultZonehttp://localhost:8080/eureka/ server.port8081 apollo.profilegithub EOF # 为 DEV 环境创建 adminservice 配置 cat /opt/apollo/adminservice-dev/application-github.properties EOF spring.datasource.urljdbc:mysql://localhost:3306/ApolloConfigDB_dev?characterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameapollo_dev spring.datasource.passwordPssw0rd4Dev apollo.config-service.urlshttp://localhost:8081 eureka.client.serviceUrl.defaultZonehttp://localhost:8080/eureka/ server.port8090 apollo.profilegithub EOF # 为 DEV 环境创建 portal 配置 cat /opt/apollo/portal-dev/application-github.properties EOF spring.datasource.urljdbc:mysql://localhost:3306/ApolloConfigDB_dev?characterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameapollo_dev spring.datasource.passwordPssw0rd4Dev apollo.portal.envsdev apollo.admin-service.urlhttp://localhost:8090 apollo-env.properties.location/opt/apollo/portal-dev/config/apollo-env.properties server.port8070 apollo.profilegithub EOF # 创建 apollo-env.propertiesDEV mkdir -p /opt/apollo/portal-dev/config/ cat /opt/apollo/portal-dev/config/apollo-env.properties EOF dev.metahttp://localhost:8081 EOF # 同理为 TEST 和 PROD 创建对应配置端口和 database 名称按约定替换Step 6启动并验证# 赋予脚本执行权限 chmod x /opt/apollo/scripts/*.sh # 启动所有服务 /opt/apollo/scripts/start-all.sh # 等待 60 秒检查状态 /opt/apollo/scripts/status.sh # 验证curl 三个 Portal 地址 curl -s http://localhost:8070 | grep Apollo # 应返回 HTML 片段 curl -s http://localhost:8071 | grep Apollo # TEST Portal curl -s http://localhost:8072 | grep Apollo # PROD Portal实测结果从Step 1到Step 6全程耗时 22 分钟三套 Portal 均可正常访问登录后能看到各自环境下的应用列表创建 namespace、发布配置、查看历史版本全部功能正常。configservice日志里没有ERRORadminservice日志里Eureka registration SUCCESS出现三次portal日志里Loading envs: [dev]显示正确。4.2 使用 apollo save tool 实现配置流水线apollo save tool是社区工具GitHub 地址是https://github.com/kezhenxu94/apollo-save-tool。它用 Go 编写编译后只有一个二进制文件非常适合集成到 CI 流水线。安装与配置# 下载最新 release wget https://github.com/kezhenxu94/apollo-save-tool/releases/download/v1.2.0/apollo-save-tool-linux-amd64 -O /usr/local/bin/apollo-save-tool chmod x /usr/local/bin/apollo-save-tool # 创建配置文件 ~/.apollo-save-tool.yaml cat ~/.apollo-save-tool.yaml EOF environments: dev: url: http://localhost:8070 token: # dev 环境通常不用 token test: url: http://localhost:8071 token: prod: url: http://localhost:8072 token: EOF典型工作流导出 DEV 环境配置模板apollo-save-tool export --env dev --app some-app --namespace application --output ./templates/some-app-dev.json修改模板如改数据库 URL、开关 flagsed -i s/jdbc:mysql:\/\/dev-db/jdbc:mysql:\/\/test-db/g ./templates/some-app-dev.json导入到 TEST 环境apollo-save-tool import --env test --app some-app --namespace application --input ./templates/some-app-dev.jsonQA 验证通过后一键推送到 PRODapollo-save-tool import --env prod --app some-app --namespace application --input ./templates/some-app-dev.json这个流程把原来需要 15 分钟的手动操作压缩到 30 秒内完成且 100% 可重复、可审计。我在一个电商项目里用它实现了“代码提交 → 自动构建 → 配置同步 → 预发验证 → 生产发布”的全链路自动化配置错误率为 0。5. 常见问题与排查技巧实录5.1 典型问题速查表问题现象可能原因排查命令解决方案Portal 登录后空白页F12 看 Network 里http://localhost:8070/返回 404portal的server.port与实际监听端口不一致或 Nginx 反代配置错误lsof -i :8070检查application-github.properties的server.port确认无空格、无注释adminservice日志反复报Cannot find config serviceapollo.config-service.urls配置错误或configservice未启动/端口被占curl -v http://localhost:8081确保 URL 是 HTTP 地址非 Eureka且configservice进程在运行configservice启动时报Access denied for user apollo_devlocalhostMySQL 用户 host 不匹配或密码错误mysql -u apollo_dev -p -h localhost -D ApolloConfigDB_dev用CREATE USER apollo_devlocalhost显式指定 host不要用%三个 Portal 都能打开但都只显示 DEV 环境的应用ServerConfig表里apollo.portal.envs值被覆盖为dev,fat,uat,prosudo mysql -u root -p -e SELECT * FROM ApolloConfigDB_dev.ServerConfig WHERE Keyapollo.portal.envs;删除ApolloConfigDB_test和ApolloConfigDB_prod里的apollo.portal.envs记录只保留本环境的单值portal登录后看不到任何应用提示No applications foundApplications表为空或apollo-adminservice没权限读取sudo mysql -u root -p -e SELECT COUNT(*) FROM ApolloConfigDB_dev.Applications;手动插入一条测试应用INSERT INTO Applications (AppId, Name, OwnerName, OwnerEmail) VALUES (some-app, Some App, dev, devexample.com);5.2 我踩过的三个深坑与独家避坑技巧坑一JDK 版本陷阱Apollo 2.3.0 官方文档写支持 JDK 8/11/17但实测 JDK 17.0.2 在portal启动时org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext会因java.lang.ClassNotFoundException: javax.xml.bind.DatatypeConverter报错。这是因为 JDK 17 移除了 JAXB 模块。解决方案不是降级 JDK而是给 java -
返回列表