news 2026/10/22 3:12:06

Apollo 1.4.0配置中心部署指南:从单机搭建到客户端接入

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apollo 1.4.0配置中心部署指南:从单机搭建到客户端接入

简介:Apollo 1.4.0 源码适配包面向需要将 Apollo 配置中心数据源从 MySQL 切换为 PostgreSQL 的 Java 开发与运维人员。官方默认仅支持 MySQL,该压缩包通过改动源码解除此限制,适配 PostgreSQL 11.4,并集成 42.2.5 版本 JDBC 驱动。资源共 2000 个文件,约 11.46MB,包含 646 个 Java 源文件、607 个编译后的 class 文件、64 个 SQL 脚本、61 个 XML 与 40 个 yml 配置,以及构建脚本、Dockerfile、前端静态资源等,便于直接查看改动点、编译部署或按需二次调整。.properties 与 yml 为主的配置模块和 SQL 初始化脚本均保持完整,可快速定位数据源相关的全部改动。内容预览中的 README 与 build.bat 提示包内保留构建说明和编译入口,ReleaseService 等核心类则有助于追踪服务端改造逻辑。目前已有 4184 人学习/下载,适合正在规划 Apollo 数据源扩展或需要落地 PostgreSQL 高可用方案的团队参考。

1. 拿到 apollo-1.4.0.zip 先别急着解压:先搞清它解决什么问题

一个微服务拆到十几个之后,配置管理就会变成最磨人的杂活。改一个开关要登服务器改文件再重启,开发、测试、生产三套环境各改各的,时间一长连自己都记不清哪台机器上的配置是新的。apollo-1.4.0.zip 这个压缩包,对应的就是一套开源的分布式配置中心,核心作用是把散落在各服务里的配置收拢到一个管理界面上,发布之后客户端自动感知、动态刷新,不用再为改配置重启服务。1.4.0 这个版本在配置中心里属于被验证得比较充分的一个版本,部署方式不复杂,单台机器就能跑完整套环境。这篇笔记适合正在搭微服务基座、想自己先跑通 Config Service、Admin Service、Portal 三个服务的团队,也适合手里只有这个 zip 包、想搞明白从解压到客户端接入完整链路的人。

2. 部署前准备:环境核对、数据库初始化、解压三件套

2.1 Java 环境与端口占用:两个容易忽略的前置条件

Apollo 的服务端是 Spring Boot 打的包,启动脚本本质上是 Java 进程,所以第一件事是确认机器上有 JDK。1.4.0 这个版本要求 JDK 8 及以上,我一般会用java -version先看一眼,确认不是只装了 JRE 就动手。很多部署卡在启动脚本报Unable to locate a Java Runtime这种错,根源就是 PATH 里没找到 java 或者 JAVA_HOME 指错了位置。

端口方面,默认端口是固定的:Config Service 是 8080,Admin Service 是 8090,Portal 是 8070。部署前用下面命令确认这些端口没被别的进程占用,我用的是 Golang 项目里常见的lsof,Linux 上也可以换ss -lntp。

lsof -i :8080 -i :8090 -i :8070

提示:如果机器上同时跑着别的 Java 应用,8080 被占用的概率很高。不建议为了迁就端口去改系统里其他应用的配置,直接改 Apollo 的server.port更干净,后面会讲到具体改哪几个文件。

内存方面,三个服务加起来大约需要 1.5GB 左右的堆内存,如果机器本身只有 2GB,建议只部署 Config Service 和 Portal,Admin Service 可以等用到管理功能时再起。这个取舍在初期验证阶段完全够用。

2.2 初始化数据库:两套 SQL 脚本的区别与执行顺序

服务端有三个模块,但数据库只需要两个库:ApolloPortalDB 和 ApolloConfigDB。PortalDB 存的是用户、权限、项目列表这类管理数据,ConfigDB 存的是真正的配置内容、发布历史、灰度规则。解压后 sql 目录下一般能看到两个脚本,分别对应这两个库。

一个常见的误操作是只导入了 ConfigDB,结果 Portal 能登录但看不到任何项目。两个库都要建,而且字符集建议直接指定utf8mb4,原因是配置内容里可能出现特殊字符或扩展字符集内容,默认的 latin1 会直接导致乱码。

mysql -u root -p -e "CREATE DATABASE ApolloPortalDB DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" mysql -u root -p -e "CREATE DATABASE ApolloConfigDB DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" mysql -u root -p ApolloPortalDB < apolloportaldb.sql mysql -u root -p ApolloConfigDB < apolloconfigdb.sql

这里先建库再导数据,顺序不能反。如果先导数据再建库,MySQL 会直接报Unknown database。脚本执行完毕后,可以用SHOW TABLES;各看一眼,PortalDB 里常见的是users、permissions这类表,ConfigDB 里应该能看到app、item、release等表。看到这些表基本说明导入成功了。

2.3 解压后该认得哪些目录:配置文件的改动范围

zip 包解压后,常见做法是得到一个或多个按模块命名的目录,每个目录里都有conf和scripts两个关键目录。conf里放着application.properties和startup.sh,这两个文件就是要改的全部;scripts里是启动辅助脚本,正常不需要动。

我第一次部署时把所有文件都翻了一遍,后来发现真正需要改的就三类:数据源连接串、Eureka 地址、Portal 的访问地址。其他配置保持默认即可。这个认知能帮你省不少时间——不要被目录里大量配置文件干扰,Apollo 的默认行为已经适合大多数场景。

3. 单机部署三个服务:从配置修改到启动验证

3.1 修改 configservice 与 adminservice 的配置

先处理 Config Service。进入它的conf目录,打开application.properties,主要改数据源。默认文件里会有一段 Spring 数据源的配置,需要替换成你自己的 MySQL 地址、账号、密码。关键是要在连接串里带characterEncoding=utf8和serverTimezone,否则后面启动时可能报时区错误或者出现中文乱码。

spring.datasource.url = jdbc:mysql://127.0.0.1:3306/ApolloConfigDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai spring.datasource.username = root spring.datasource.password = your_password

Config Service 内部嵌了 Eureka,所以它自己不需要额外指定注册中心地址,只要保证数据库能连上即可。Admin Service 的配置改动方式和它一样,只是连接的数据库同样是ApolloConfigDB,两个服务共享这一个库。这里有个细节:Admin Service 的application.properties里需要指定eureka.service.url指向 Config Service 的地��,默认值是http://127.0.0.1:8080/eureka/,单机部署不用改,但如果是多机部署,就要把127.0.0.1换成 Config Service 所在机器的实际 IP。

eureka.service.url = http://127.0.0.1:8080/eureka/

注意:很多部署问题出在把 Config Service 和 Admin Service 的 IP 写成了localhost,而客户端或 Portal 在另一台机器上解析不到。单机验证无所谓,一旦要给别人访问,统一用内网 IP。

3.2 配置 portal:数据源、地址、登录账号

Portal 是管理界面,配置项比前两个多一处。它的application.properties同样要改数据源,但连接的是ApolloPortalDB,而不是 ConfigDB。这一点最容易糊涂。另外还要配置 Admin Service 的访问地址,Portal 管理配置时实际是调用 Admin Service 的接口,所以这个地址错了会出现能登录但发布配置失败的情况。

spring.datasource.url = jdbc:mysql://127.0.0.1:3306/ApolloPortalDB?characterEncoding=utf8&serverTimezone=Asia/Shanghai spring.datasource.username = root spring.datasource.password = your_password apollo.portal.envs = dev apollo.portal.meta.servers = {"dev":"http://127.0.0.1:8080"}

apollo.portal.envs声明了当前环境列表,这里只写dev就够单机验证;如果你想模拟多环境,把dev和pro都写上,然后apollo.portal.meta.servers里对应给每个环境配置不同的 Config Service 地址。登录账号要自己往apollo-portal的conf目录下的apollo-env.properties里加,或者在数据库里直接插入一条用户记录,我一般图省事用后者。默认库里会有一个apollo用户,密码存在users表里,常见值是$2a$10$7fU7DVN0cJwkQzpB7pIqOuuASzqP8F6pGjVgJYvWQx6jzTZ1aTk6W这种 BCrypt 哈希,对应明文密码admin,注意这是一版很常见的默认组合,部署后第一件事就该改掉。

3.3 启动顺序与验证命令:三个端口必须各就各位

启动顺序我一般固定是 Config Service → Admin Service → Portal。原因不复杂:Config Service 内含 Eureka,Admin Service 启动时要向它注册,Portal 启动后要拉环境列表和 Admin Service 信息,链路是从下往上的。如果顺序反了,服务本身不会崩,但日志里全是连接超时,排查起来费神。

启动脚本都在各模块的scripts目录下,直接执行:

./startup.sh

脚本内部会调java -jar,并把日志写到logs目录。启动后不要急着看界面,先用命令确认端口监听状态,每个服务启动大约要 10 到 20 秒,Eureka 注册可能需要更久。

ss -lntp | grep -E "8080|8090|8070"

三个端口都出现在输出里,说明进程起来了。接着验证 Eureka 是否正常工作,Config Service 的 Eureka 接口可以直接用 curl 探:

curl http://127.0.0.1:8080/eureka/apps

返回一段 XML,里面包含 Admin Service 和 Config Service 的注册信息,就说明注册中心正常。此时打开http://127.0.0.1:8070,能看到登录页,用默认账号登录后就是空的项目列表界面。到这里服务端就绪,可以开始接客户端了。

4. 客户端接入:Spring Boot 项目里配两个键、写一段读取逻辑

4.1 引入客户端依赖与版本对齐

服务端是 1.4.0,客户端依赖版本也要保持一致。在 Spring Boot 项目的pom.xml里加入 Apollo 客户端依赖,版本号直接写 1.4.0。很多人在这一步栽过跟头:客户端用了新版本或者旧版本,连上服务端后出现序列化不兼容或者接口 404。

<dependency> <groupId>com.ctrip.framework.apollo</groupId> <artifactId>apollo-client</artifactId> <version>1.4.0</version> </dependency>

这个依赖会带入apollo-core和apollo-client-api,不需要额外手工添加。如果你的项目里同时有别的配置中心依赖,建议先排除掉或者确认接口不冲突,Apollo 的@Value注解在 Spring Boot 环境里会和原生注解冲突,后面会细说。

4.2 元数据配置:app.id 与 apollo.meta 的作用边界

客户端启动时要连到 Config Service 拿配置,它需要知道两件事:自己是谁、去哪找配置中心。前者是app.id,后者是apollo.meta。在application.yml里写:

app: id: sample-service apollo: meta: http://192.168.1.100:8080 bootstrap: enabled: true eagerLoad: enabled: true

app.id对应 Portal 里创建项目时填的应用 ID,两边必须完全一致,大小写和特殊字符都要一字不差。apollo.meta填的是 Config Service 的地址,注意不是 Portal 的地址,也不是 Admin Service 的。eagerLoad.enabled建议设为true,否则配置是异步加载的,程序里第一次读取配置时可能拿到null,这个坑很隐蔽,尤其在 Spring Boot 启动阶段读取配置的场景里。

在 1.4.0 这个版本里,客户端拿到apollo.meta后会请求它的/eureka/apps接口获取 Config Service 实例列表,所以即使apollo.meta配的是内网 IP,也要保证客户端机器能访问到那个地址的 8080 端口。

4.3 两种读配置姿势:注解与程序化获取

接入 Apollo 后,代码里读配置的方式和原来差不多,但有一个关键区别需要注意。直接用@Value是最常见的姿势:

@Component public class CacheService { @Value("${redis.cache.ttl:300}") private int cacheTtl; public int getCacheTtl() { return cacheTtl; } }

逻辑说明:@Value注解在 Spring 容器启动时注入属性值,${redis.cache.ttl:300}的意思是读 Apollo 上redis.cache.ttl这个配置项,如果不存在则用默认值 300。Apollo 的动态刷新能力在这里的体现是:当你在 Portal 上修改这个配置并发布后,Spring 容器里的cacheTtl字段会被自动更新,不需要重启服务。

参数说明:redis.cache.ttl这个 key 必须在 Apollo 配置里存在,否则走默认值;默认值冒号后面不能留空格。有一点容易翻车——如果你在类里同时用了@Value和自定义的 ConfigurationProperties 类读取同一份配置,刷新时前者会更新而后者不会,因为 Apollo 只对注解字段做注入。程序化获取是更可靠的方式:

Config config = ConfigService.getAppConfig(); Integer ttl = config.getIntProperty("redis.cache.ttl", 300);

这种方式适合在非 Spring 管理的类里使用,或者需要动态获取多个配置项的场景。它每次都会实时取 Apollo 的本地缓存,配合监听器可以感知配置变更。两种姿势可以混用,但同一份配置别同时用两种方式维护,否则调试时不知道哪个值生效。

5. Apollo 1.4.0 部署避坑实录:五条现象与排查路径

5.1 configservice 启动日志一直报 Eureka 连接被拒

现象:Config Service 进程起来了,8080 端口也监听着,但日志每隔几秒刷一条Connection refused: connect,指向的地址是自己。

原因:Config Service 内嵌的 Eureka 在启动初期会尝试注册自己,而此时注册中心还没完全就绪,于是反复重试。另一个常见原因是你把eureka.service.url配置里的 localhost 写成了别的 IP,导致自行探测时连到了错误地址。

解决:如果日志里的地址是 127.0.0.1:8080,这属于正常启动过程,等 30 秒左右观察日志是否停止报错即可。如果持续报错,检查application.properties里eureka.instance.homePageUrl和eureka.service.url是否一致,全部改成机器实际内网 IP,然后重启。

5.2 portal 登录后项目列表一直空白

现象:登录 Portal 成功,但界面上看不到任何项目,手动创建项目时下拉框里也没有环境。

原因:最常见的是 Portal 连接的数据库不对,或者apollo.portal.envs和apollo.portal.meta.servers的配置有问题。Portal 启动后要请求 Config Service 获取环境信息,拿不到就会显示空白。

解决:先用 curl 确认 Config Service 的 Eureka 接口能返回服务列表,再检查 Portal 的application.properties里apollo.portal.meta.servers的 JSON 格式是否正确。这个配置项是字符串,不是 YAML 对象,常见错误是漏了外层引号或者写了单引号,导致解析失败。修正后重启 Portal。

5.3 客户端启动直接报 Apollo config not found

现象:Spring Boot 项目启动时抛异常,提示找不到 Apollo 配置,网上搜到的说法是配置地址连不上,但地址明明能 ping 通。

原因:apollo.meta配的是 Portal 地址而不是 Config Service 地址,或者app.id在 Portal 里还没创建对应的项目。前者会导致客户端请求到错误的端口,后者会让 Config Service 返回App not found。

解决:先确认 Portal 里已经创建了和app.id同名的项目。然后检查apollo.meta,这个地址一定要指向 Config Service 的 8080 端口。如果确认都正确,打开客户端的 debug 日志,在application.yml加一句logging.level.com.ctrip.framework.apollo=DEBUG,启动时会打印实际请求的 meta 地址和响应内容,问题瞬间定位。

5.4 配置改了但不生效:本地缓存与监听器两个疑点

现象:Portal 上修改配置并发布,客户端日志看不到拉取动作,代码里读取的值还是旧的,重启后才生效。

原因:Apollo 客户端默认有本地缓存,它会在启动后台线程定期拉取更新,但频率不是秒级的。另外如果代码里用了@ApolloConfigChangeListener但监听器内部逻辑有异常,刷新会失败,而 Spring 的@Value注入依赖的是配置变更事件,事件被异常中断后不会重放。

解决:先确认客户端日志里有没有Config changed字样,没有就查客户端是否真正连接到了 Config Service,可以用curl直接请求配置接口:curl http://192.168.1.100:8080/configs/sample-service/default/application,能返回 JSON 就说明服务端有配置。有日志但没生效,检查监听器方法内部是否抛了异常,把监听器逻辑精简为只打日志,确认事件流畅通后再加业务逻辑。另外注意,Apollo 发布是有版本概念的,修改后要点“发布”按钮,不是保存就算生效,这个操作很多人漏掉。

5.5 数据库连接串少了两个参数,页面乱码、写入超时

现象:Portal 页面能打开,但配置项里输入中文保存后变问号,或者偶发写入超时。

原因:数据库连接串没有指定characterEncoding,MySQL 客户端默认用了latin1做连接字符集;同时没指定serverTimezone时,在新版 MySQL 驱动下会报时区错误或者使用服务器本地时区导致时间不一致。

解决:在前面提到的三处数据源连接串中统一加上?characterEncoding=utf8&serverTimezone=Asia/Shanghai。注意utf8在 MySQL 里是utf8mb3的别名,如果你希望完全支持 emoji 字符,数据库和连接串都要用utf8mb4,连接串参数写成characterEncoding=utf8即可,因为 JDBC 驱动的utf8对应的是utf8mb4。改完连接串后重启三个服务,重新导入一次数据最稳妥。

6. 部署验收三步走:热更新、灰度回滚、缓存日志观测

服务端和客户端都跑通之后,不要急着写业务,先用三个小实验把 Apollo 的核心能力验证一遍。第一步是热更新验证。在 Portal 里新建一个配置项,比如test.refresh=true,在客户端代码里用@Value注入它,然后修改为false并发布。观察客户端日志,正常情况下 2 到 3 秒内会出现Config changed的打印,程序无需重启,值就变了。这一步过了,说明 Spring 集成和事件通知链路是通的。

第二步验证灰度发布与回滚。Apollo 的灰度是针对实例 IP 的,在 Portal 里把配置发布到灰度环境,指定某个客户端实例的 IP,然后检查只有那台机器收到了新值,其他机器保持旧值。回滚操作在发布历史里,找到上一次发布记录,点“回滚”即可。这个能力在生产环境非常关键,出了问题能在秒级恢复到上一个稳定版本,比重启快太多。

第三步看本地缓存与日志。找到客户端机器上~/data/{appId}/目录下的缓存文件,里面是配置的 JSON 快照,确认它和服务端一致。这一步的价值在于验证“客户端在服务端不可达时,如何用本地缓存兜底”。你可以把 Config Service 停掉,再重启客户端,观察它是否能用缓存启动,启动后配置是否正确。这个实验建议每个环境都做一遍。

我自己的习惯是部署完写一个一页纸的检查单,把端口、数据库、Eureka 地址、app.id 四项核对完再收工。这套流程走下来,后面接真实业务配置时基本不会再被底层问题绊住。希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 3:11:23

分布式全局唯一ID生成方案实战:雪花算法与号段模式选型指南

1. 从一个“看起来很简单”的需求说起分布式系统里生成一个不重复的 ID&#xff0c;这件事听起来像是入门级需求&#xff0c;但真正在线上跑过高并发业务的人都清楚&#xff0c;它是个不折不扣的深水区。我最早接触这个问题是在一个订单系统里&#xff0c;当时用的是数据库自增…

作者头像 李华
网站建设 2026/10/22 3:11:07

上下文工程实战指南:从提示词到智能体记忆管理的系统方法

1. 从“调提示词”到“管上下文”&#xff1a;这个角色到底在解决什么问题先说个现象。过去一年里&#xff0c;我接触了不少做AI应用研发团队&#xff0c;大家普遍有一个错觉&#xff1a;模型能力不行&#xff0c;换个更强的模型就行&#xff1b;输出不对&#xff0c;把prompt写…

作者头像 李华
网站建设 2026/10/22 3:11:05

LatentVLA:端到端自动驾驶的潜在动作表示与闭环评测新思路

做端到端自动驾驶的人&#xff0c;今年绕不开三个词&#xff1a;世界模型、VLA、闭环评测。VLA&#xff08;Vision-Language-Action&#xff09;把视觉、语言、决策压缩进同一个网络&#xff0c;听起来很优雅&#xff0c;但真正把它往车端送的时候&#xff0c;问题就来了——动…

作者头像 李华
网站建设 2026/10/22 3:11:05

5G NOMA功率分配仿真:FTPA与注水算法实现及避坑指南

简介&#xff1a;资源包围绕5G非正交多址接入&#xff08;NOMA&#xff09;的功率分配问题&#xff0c;整理了完整的实现与学习资料&#xff0c;适合通信工程专业学生及5G物理层算法研究人员。包内含MATLAB脚本、Simulink仿真模型、相关论文PDF及图文说明&#xff0c;覆盖从NOM…

作者头像 李华
网站建设 2026/10/22 3:10:12

RDMA队列管理与连接建立实战:功能测试与踩坑解析

最近在做某个RDMA子系统的控制面功能验证&#xff0c;正好推进到“队列管理 连接建立”这一环&#xff0c;也就是这个系列文档的第58篇对应的实测阶段。RDMA说白了就是绕过内核和CPU&#xff0c;让数据直接从一端网卡搬到另一端应用内存&#xff0c;但真正把它跑通&#xff0c…

作者头像 李华
网站建设 2026/10/22 3:10:09

Git分支与版本控制实战:从指针原理到冲突解决

做开发这几年&#xff0c;如果说有一个工具让我从“会用”逐渐变成“离不开”&#xff0c;Git 一定是排在最前面的那个。Git 分支和版本控制&#xff0c;听起来像是每个程序员入门的必修课&#xff0c;但见过太多人把git commit、git push当成例行公事&#xff0c;遇到回退、冲…

作者头像 李华