Apollo配置中心部署实战:从源码编译到服务启动与热更新
大学小学期实践课的第四节课我们安排的是Apollo软件部署实操。如果你没接触过这门课前面三节分别是Linux基础命令、MySQL数据库使用、Git和Maven工程管理到这节突然上了一个配置中心组件很多同学第一反应是为什么要单独装一个软件管配置直接在配置文件里改不行吗这节实操课结束之后我才发现Apollo这个选型其实非常贴合小学期实践的调性——它不像某些课程那样一句已经部署好了大家直接用就带过而是需要学生自己拉源码、配数据库、打包、启动三个Java服务中间会遇到一堆真实部署才会碰到的问题。今天这篇就把整节课的完整过程、踩坑记录和给学生讲的核心原理梳理一遍给准备上同样内容的朋友一个参考。1. 课程背景为什么小学期第四课要选Apollo来练部署1.1 前三节课的铺设逻辑很多小学期课程容易走两个极端要么全是理论课学生听三天PPT然后交一份报告要么直接丢一个高大上的项目学生照着文档复制粘贴根本不知道自己在干什么。我们这门课的实际思路是先让你有操作Linux、操作数据库、管理工程代码的底子再拿一个真实可用的开源软件让你独立部署一遍把前面三节课的知识全部串起来。部署Apollo这件事恰好能把前三节全部用上你需要用Linux命令解压、创建目录、查看进程需要连MySQL建库导数据需要用Maven拉依赖打jar包需要改配置文件然后用Git版本管理你的改动。如果前面三节课是散的点这节就是一条把它们拧在一起的线。1.2 Apollo配置中心到底解决什么问题先跟完全没接触过的同学说一下Apollo是什么。假设你现在维护五个微服务每个服务里都有一份application.yml里面写着数据库地址、Redis地址、各种开关参数。哪天数据库地址变了你得挨个改五个文件然后挨个重新打包、重新部署、重启服务一整套流程下来半小时起步。Apollo做的事情就是把所有配置集中到一个管理界面上服务启动的时候从Apollo拉取配置你在Apollo后台改一个配置项运行中的服务能在几秒内自动拿到新值不需要重新打包也不用重启。这种配置集中管理动态下发的能力是微服务架构里非常基础的一环。单纯讲概念学生很难有体感但让他自己部署一遍再写个demo验证配置实时生效理解就完全不一样了。2. 部署前必须理清的两个认知三组件分工和两套数据库2.1 Config Service、Admin Service、Portal三者的关系Apollo整体拆成了三个Java服务名字很容易混淆但分工其实很清晰。Config Service负责给业务系统的客户端提供配置读取、订阅推送功能。业务应用启动时会连它拿配置配置变更时也是它把最新值推给客户端。它默认端口是8080。Admin Service负责给管理后台提供配置管理、发布、回滚等功能。你可以理解成它是干活的管理后台的所有操作最终由它落到数据库里。默认端口8090。Portal管理员操作的可视化网页默认端口8070。它本身不直接操作业务配置而是通过Admin Service完成操作。刚开始部署时学生最容易搞混的就是这三个服务的职责我通常会打一个比方Portal是餐厅前台Admin Service是后厨Config Service是外卖窗口。顾客业务应用去外卖窗口取餐前台负责下单后厨负责做饭三者不能互相替代。2.2 两个数据库分别存什么Apollo部署需要初始化两个MySQL数据库这个也是初学者容易搞乱的地方。ApolloConfigDB存的是配置本身包括每个项目的配置项、发布历史、灰度规则等Config Service和Admin Service都用这个库。ApolloPortalDB存的是Portal后台的用户信息、项目列表、权限等门户数据Portal服务使用这个库。为什么拆成两个而不是一个因为ConfigDB是运行时数据业务依赖非常重写操作频繁PortalDB是管理端数据相对独立。拆开之后我们可以把ConfigDB做更细的读写分离和容灾Portal的日常维护也不会影响配置读写链路。你在执行SQL脚本的时候一定分清哪个脚本进哪个库装反了后面会非常痛苦。3. 部署实操链路从源码编译到三个服务全部启动3.1 获取源码与工程结构我们课程里让学生从官方仓库Clone了Apollo的源码工程也可以用课程组准备的离线包反正结构是一样的。Clone下来之后主目录下有几个子工程重点看这三个apollo-configserviceapollo-adminserviceapollo-portal它们的共同父工程里管理着Maven依赖版本。我建议学生先不要改任何代码先跑通官方默认配置成功之后再尝试改端口、改数据库连接这样排查问题的时候能分清楚是环境问题还是代码问题。3.2 初始化数据库的具体步骤用MySQL客户端连上数据库后执行官方项目里的两个SQL脚本一个叫apolloconfigdb.sql一个叫apolloportaldb.sql。需要说明的是不同版本脚本内容有差异最好和源码版本保持一致不要拿1.x的脚本配2.x的代码。执行命令大概是这样的mysql -u root -p apolloconfigdb.sql mysql -u root -p apolloportaldb.sql执行完可以进MySQL看一眼SHOW DATABASES; USE ApolloConfigDB; SHOW TABLES;正常情况下能看到一堆表比如APP、ITEM、RELEASE等没有报错说明导入成功。这里有两个小坑建库时字符集需要是utf8mb4否则后面如果存了Emoji之类的特殊字符会报错。如果之前执行过脚本想重新导入建议先DROP DATABASE再重新执行避免残留数据干扰。3.3 打包编译与启动参数的调整源码工程拿到并且数据库就绪后进到Apollo工程根目录执行打包mvn clean package -DskipTests这一步会拉取大量依赖耗时比较长建议提前把Maven仓库配好国内镜像。打包完成后三个子工程的target目录下会各自生成一个可执行的jar包类似apollo-configservice-2.x.x.jarapollo-adminservice-2.x.x.jarapollo-portal-2.x.x.jar在没有改任何配置的情况下直接启动默认连的是开发者本机的localhost数据库密码为空。实际教学环境里MySQL一定有密码所以必须改数据库连接配置。这个配置在三个服务各自的application.properties里核心配置如下# Config Service 和 Admin Service 都需要改 spring.datasource.urljdbc:mysql://localhost:3306/ApolloConfigDB?characterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.password你的密码 # Portal 改的是自己的库 spring.datasource.urljdbc:mysql://localhost:3306/ApolloPortalDB?characterEncodingutf8serverTimezoneAsia/Shanghai spring.datasource.usernameroot spring.datasource.password你的密码这里如果MySQL是8.x版本连接串里建议加上useSSLfalse和allowPublicKeyRetrievaltrue不然启动时经常报Public Key Retrieval is not allowed这个错我在几个学生机器上反复见到过。3.4 按顺序启动服务并验证注册情况配置改好之后按顺序启动。先启动Config Servicejava -Xms256m -Xmx512m -jar apollo-configservice-2.x.x.jar看到日志里出现Tomcat started on port 8080并且没有异常堆栈说明Config Service起来了。然后启动Admin Servicejava -Xms256m -Xmx512m -jar apollo-adminservice-2.x.x.jar它的日志里会包含向注册中心注册自己的信息。最后启动Portaljava -Xms256m -Xmx512m -jar apollo-portal-2.x.x.jar三个服务全部启动后浏览器访问http://localhost:8080可以看到一个Eureka注册中心页面正常的话应该列出CONFIG-SERVICE和ADMIN-SERVICE两个服务实例。这一步是整个部署过程中的核心验证点——如果Eureka页面能看到两个服务说明前两个服务注册成功如果只有Config Service或者两个都没有那问题就出在注册链路或数据库连接上。4. 实测中躲不开的几个坑与排查思路4.1 服务起不来先查数据库连接日志前面说的数据库连接问题是最常见的一类。学生启动服务时经常出现进程起来了服务自己也打印了启动日志但几秒之后就报错退出。这种时候第一反应应该是去看最后几行异常信息而不是重新启动一次。我之前带学生排查过一个案例某同学MySQL使用的是8.x版本密码没问题连接地址也没问题但没加allowPublicKeyRetrievaltrue报错内容是Public Key Retrieval is not allowed。这个报错信息其实已经告诉你了——MySQL8默认使用caching_sha2_password认证第一次连接时需要从服务端获取公钥来加密密码传输连接参数里没允许这个行为就拒绝执行。加上参数就好了。还有一种情况是数据库连接串里的serverTimezone没设置Java驱动和MySQL时区不一致会直接抛异常。这类问题在教学中出现的频率比我预想的高很多根源是很多同学习惯照抄别人的连接串却不知道每个参数是干什么用的。4.2 Eureka页面显示两个服务但Portal登录后看不到环境另一个高频坑是Eureka页面一切正常Config Service和Admin Service都注册上了Portal也能登录进去但界面上找不到环境选项或者创建项目时无法选择环境。这个问题的根子在Portal这个服务需要知道自己该往哪个环境发布配置。它读取的配置项是apollo.portal.envs和dev.metaapollo.portal.envsdev dev.metahttp://localhost:8080第一行告诉Portal当前系统里有哪些环境我们只准备了一个dev环境所以就是dev。第二行告诉Portaldev环境的元数据服务地址是Config Service的地址也就是8080端口。这里有个特别容易写错的地方dev.meta填的是Config Service的地址不是Admin Service也不是Portal自己。很多同学会想当然地填成8090或者8070结果就是后台永远感知不到配置服务的存在。如果这个配置没写Portal会出现一种很迷惑的状态能登录、能进后台但是看不到任何环境按钮项目创建流程没法完成。这个时候别急着检查容器网络先看一眼Portal的配置文件里有没有这两行。4.3 Eureka自我保护模式下的红色告警误判还有一次遇到的情况很有意思某个同学的Eureka页面是正常的黄色背景上面有一行红色WARNING提示大意是自我保护模式已启用某个服务实例可能已经崩溃。这位同学以为自己部署失败了紧张地截图发过来。其实这是Eureka自我保护机制触发了。如果服务实例心跳不健康Eureka宁可让旧实例待在注册表里也不轻易把它踢出去防止因网络抖动导致大面积下线。在单机部署的Apollo里只有一个Config Service实例和一个Admin Service实例没有其他副本做心跳备份很容易进入这个状态。遇到这种情况不要慌重点看页面上的实例列表只要CONFIG-SERVICE和ADMIN-SERVICE都在UP状态就说明服务是正常的。如果确实是DOWN了再去翻对应服务的日志多半是配置变更或内存不足导致的而不是自我保护机制本身的问题。4.4 教学机的内存限制与启动参数调整小学期教室里的电脑配置一般不会太好每台机器还要同时开虚拟机、数据库、浏览器如果三个Java服务都用默认参数启动内存会很紧张。默认情况下JVM堆可能分配得比较大学生机器直接卡死的情况我们都遇到过。建议在课程开始时统一让大家用这个参数启动java -Xms128m -Xmx256m -jar apollo-configservice-2.x.x.jar java -Xms128m -Xmx256m -jar apollo-adminservice-2.x.x.jar java -Xms64m -Xmx128m -jar apollo-portal-2.x.x.jar把堆内存调小之后三个服务加起来大约占400MB左右教学机完全扛得住。不过堆内存太小会让GC频繁一些在练习环境里完全够用这是教学演示场景下非常实用的一个取舍。5. 部署完成后的验证闭环从管理后台到客户端热更新5.1 管理后台创建项目并发布一条配置部署不是终点得真正用起来才算完成。登录Portalhttp://localhost:8070默认账号是apollo密码是admin不过不同版本初始账号可能不同以官方文档为准。登进去后第一步是创建项目应用IDAppId建议取一个唯一值比如demo001应用名称随便填应用部门/负责人填空或随便填都可以创建完成以后进入配置管理界面新增一个配置项。比如Keytest.nameValuehello-apollo填完点击发布。到这里你已经在Apollo里成功发布了一条配置到dev环境这条配置现在对任何配置了AppIddemo001的客户端开放了。5.2 写一个最小的Spring Boot客户端来拉取配置为了让学生真实感受到配置下发链路我们要求每人写一个极简的Spring Boot工程来连接Apollo。核心依赖和代码就几行但信息密度很高。先在pom.xml里引入客户端依赖dependency groupIdcom.ctrip.framework.apollo/groupId artifactIdapollo-client/artifactId version2.x.x/version /dependency创建一个Spring Boot入口类加上Apollo配置注解SpringBootApplication EnableApolloConfig public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } }然后在application.properties里指定当前项目的AppId和Apollo地址app.iddemo001 apollo.metahttp://localhost:8080这里app.id必须和你在Portal里创建项目时填的完全一致Apollo就是靠这个app.id去定位配置的。apollo.meta指向Config Service端口不是Admin也不是Portal。接着写一个接口读取配置RestController public class ConfigController { Value(${test.name:default}) private String testName; GetMapping(/test) public String test() { return testName; } }启动这个Spring Boot应用访问http://localhost:8081/test能看到返回hello-apollo说明客户端从Apollo拉到了配置。5.3 热更新演示不重启应用的配置修改验证热更新是整节课最直观的高潮环节。保持Spring Boot应用不重启回到Portal后台把test.name的值从hello-apollo改成hello-again点发布然后再次访问客户端的/test接口。正常情况下几秒钟后返回结果就变成了hello-again全程不需要重启任何进程。这个体验对初次接触配置中心的同学来说非常震撼——原来改配置可以不用发版本。背后是客户端和Config Service之间维持了一条长连接服务端配置变化时会主动推送变更事件给客户端客户端收到事件后刷新Spring容器里的配置值。这一环是整个实操课程里最值得花时间讲透的部分。前面所有部署、踩坑、排错都是为了最后这一刻能顺滑地演示配置发布即生效的效果。6. 这节实操课我的总结与建议Apollo的部署实操放到小学期第四课从难度上说刚好卡在一个微妙的位置——比单纯装软件难比从零写框架简单非常适合用来锻炼学生排查问题的基本功。我在带课过程中最深的一个体会是大部分学生第一次部署失败都不是因为步骤写得不清楚而是遇到报错后慌慌张张重来一遍没有先理解报错信息在说什么。建议准备上类似课程的同学无论你是老师还是学生都提前做三件事把数据库连接串里的每个参数弄清楚再动手尤其是时区、SSL、认证方式这些容易被忽略的项它们在现代MySQL版本里会频繁出来找麻烦。理解三个服务加两个数据库的拓扑关系后再敲命令不要照着文档一路启动否则出了问题你连哪个服务挂了都判断不了。把部署成功后的验证环节当成课程的一部分每次都加一个客户端拉配置的demo确保整个链路确实通了而不是停留在页面能打开的表面成功。最后说一个我实际带课时给学生的经验部署类实操最容易出错的地方往往不是大段代码逻辑而是那些看起来最不起眼的配置文件单行参数。教大家在排查问题的时候先看配置文件再看数据库连接最后才去看代码——按这个顺序排查大部分问题都能在十分钟内定位。小学期的价值不在于把每一个工具都玩得精通而在于建立部署、验证、排错这个完整闭环的直觉这比记住任何一条具体命令都重要。

相关新闻

基于SSM框架的家庭健康管理系统设计与实现详解

基于SSM框架的家庭健康管理系统设计与实现详解

简介:基于SSM框架的家庭健康管理系统完整源码包,面向Java后端初学者、课程设计与毕业设计人群,覆盖家庭管理、成员管理、健康指标管理、指标上报、健康报告等核心业务模块。系统前端采用HTML、JSP、JavaScript,后端以Java/SpringM…

2026/10/15 0:33:32 阅读更多 →
职场英语回应力:破解Do you agree的三重暗礁

职场英语回应力:破解Do you agree的三重暗礁

1. 项目概述:这不是辩论赛,而是一场职业场景下的真实沟通压力测试“21-1职业沟通Do you agree”这个标题乍看像一道英语课堂练习题,但实际拆解下来,它精准指向当前职场中一个高频、高危、却极少被系统训练的沟通断层——在非对称权…

2026/10/15 0:33:32 阅读更多 →
NetFlow Analyzer 9.0实战:网络流量分析、部署配置与告警调优指南

NetFlow Analyzer 9.0实战:网络流量分析、部署配置与告警调优指南

简介:ManageEngine NetFlowAnalyzer 9.0 是一套面向网络运维人员的流量监控与分析工具包,基于NetFlow等技术采集网络设备数据,帮助管理员实时掌握带宽占用、识别异常流量并辅助故障排查与带宽规划。压缩包采用7z格式封装,共含3个文…

2026/10/15 0:32:31 阅读更多 →

最新新闻

ECharts柱状图配置全解析:从基础到动态排序与性能优化

ECharts柱状图配置全解析:从基础到动态排序与性能优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 1:57:11 阅读更多 →
LVGL 图像按钮(lv_imgbtn)实战指南:Simple Image button 示例全解与源码原理

LVGL 图像按钮(lv_imgbtn)实战指南:Simple Image button 示例全解与源码原理

嵌入式物联网智能硬件嵌入式GUI硬件开发 【免费下载链接】HoloCubic 带网络功能的伪全息透明显示桌面站 项目地址: https://gitcode.com/gh_mirrors/ho/HoloCubic 点击查看 免费下载 本篇文章围绕 HoloCubic 固件所采用的 LVGL 图形库中的 lv_imgbtn(图…

2026/10/15 1:57:11 阅读更多 →
深入解析 LAMMPS `compute msd/chunk`:逐块均方位移的计算原理与实战配置

深入解析 LAMMPS `compute msd/chunk`:逐块均方位移的计算原理与实战配置

科研科学计算高性能计算 【免费下载链接】lammps Public development project of the LAMMPS MD software package 项目地址: https://gitcode.com/gh_mirrors/la/lammps 点击查看 免费下载 导读 compute msd/chunk 是 LAMMPS 中用于按 chunk(原子分组…

2026/10/15 1:57:11 阅读更多 →
车机双系统下用ASAN抓内存踩踏:8155p上Android.mk与Android.bp配置实战

车机双系统下用ASAN抓内存踩踏:8155p上Android.mk与Android.bp配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 1:57:11 阅读更多 →
Go 1.27.1 内存局部性调优实录:压榨 CPU 缓存行命中率的工程实践

Go 1.27.1 内存局部性调优实录:压榨 CPU 缓存行命中率的工程实践

在微服务吞吐量达到数万 QPS 的高性能网关或高频事件调度引擎中,单纯依赖算法时间复杂度(如将 $O(N)$ 降为 $O(1)$)已经无法进一步带来数量级的性能突破。很多底层服务开发者发现,即便 CPU 利用率跑满了 100%,服务处理…

2026/10/15 1:57:11 阅读更多 →
Start Bootstrap 主题 One Page Wonder 详解:基于 Bootstrap 4 快速构建单页网站

Start Bootstrap 主题 One Page Wonder 详解:基于 Bootstrap 4 快速构建单页网站

前端文档 【免费下载链接】startbootstrap A library of free and open source Bootstrap themes and templates 项目地址: https://gitcode.com/gh_mirrors/st/startbootstrap 点击查看 免费下载 One Page Wonder 是 Start Bootstrap 开源仓库中的一款经典单页主题…

2026/10/15 1:56:09 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →