Apollo 配置中心入门:一所“小学校“读懂 Portal、Meta Server、Config Service

Apollo 配置中心入门:一所"小学校"读懂 Portal、Meta Server、Config Service

写在前面:最近在做配置中心联调时,发现团队里最容易混淆的不是"怎么配",而是

三个组件分别存了什么、谁能写、谁只能读 。这篇用一个"小学校"的比喻 + 真实

链路拆解,把这几个概念一次讲透。文中所有地址均已脱敏。


一、先认识三件套

Apollo 由三个核心角色组成,用一所学校来比喻(想象课程表 = 我们要管理的配置):

角色 比喻 干什么的
Portal 🏢 教务处(校长办公室) 管理控制台。改配置必须来这:出示工作证、登记、盖章发布
Meta Server 🪧 校门口的指示牌 新同学问"公告栏在哪",它负责指路
Config Service 📋 楼层公告栏 贴的都是教务处正式盖章发布的课表,大家只来看

一张表记住区别

存什么 能改配置吗
Portal 应用/权限/草稿/发布历史(管理态) ✅ 全系统唯一能写的
Meta Server 当前活着的 Config Service 节点名单 ❌ 只指路,不存配置
Config Service 已发布版本的缓存(发布态) ❌ 只给读

冷知识:Meta 和 Config 是"一家人"

两者其实是同一个程序(apollo-configservice)扮演的两个角色,部署在一起------

  • 走 /services/config 这个门 → 它是 Meta Server(指路模式)
  • 走 /configs、/notifications 这些门 → 它是 Config Service(发配置模式)

所以别纠结"Meta 和 Config 的机器有什么区别"------通常没有区别,区别在接口角色。


二、各自"手里"拿的是什么(最容易糊涂的点)

Meta Server 手里 Config Service 手里
存的内容 值班表:活着的节点名单(IP:端口) 课程表:已发布配置的键值 + 版本号
数据会变吗 会!节点上线添一行、宕机划一行(动态) 发布一次换一版(版本号递增)
正本在哪 它自己内存(名单即正本) 数据库 (正本),它只是加了缓存的只读窗口

一句话:Meta 存"人名名单",Config 存"配置内容",配置的正本永远在数据库。


三、架构总览(两条链路)

复制代码
══════════════ 发布链路(写)═══════════════

   配置变更发起
        │
        ▼
   ┌───────────────────────────┐
   │ 发布服务                  │
   │  ① 查询当前配置           │
   │  ② 修改配置项             │
   │  ③ 发布生效               │
   └────────────┬──────────────┘
                │  每步携带 token
                ▼
   ┌───────────────────────────┐
   │ Portal(唯一写入口)      │
   │  鉴权 → 落库 → 生成版本   │
   └────────────┬──────────────┘
                 ▼
   ┌───────────────────────────┐
   │ Config Service(只读分发)│
   └───────────────────────────┘

══════════════ 消费链路(读)═══════════════

   业务服务启动
        │
        ▼
   ① 问路
   ┌───────────────────────────┐
   │ Meta Server               │
   │ 【存】活着的节点名单       │
   └──────┬────────────────────┘
          │ 返回节点列表
          ▼
   ② 看板 + 登记(长轮询)
   ┌───────────────────────────┐
   │ Config Service            │
   │ GET /configs/{appId}/{ns} │
   └──────┬────────────────────┘
          ▼
   ③ 配置进本地缓存 → 业务生效
   (此后有新发布,秒级自动推送,无需重启)

一句话记法:写的找 Portal,读的找 Meta;appId 定谁家,namespace 定哪份。


四、为什么"发布走 Portal、消费走 Meta"?

这是 Apollo 的架构分工决定的------写的入口只有一个:

  • 发布一个配置 = 改 item → 落库 → 生成 release → 记录审计 → 通知各 Config Service 刷新。
    这套事务性流程只有 Portal 能执行;token 鉴权、修改人、灰度也全挂在 Portal 侧。
  • Meta Server 和 Config Service 在架构上就是只读角色 ,从它们"提交"配置,
    接口根本不存在。
  • 绕过 Portal 直写数据库是反模式------破坏审计、权限与刷新通知机制。

对应到配置文件上:

复制代码
消费服务 yaml:                      发布服务 yaml:
app.id: <应用ID>      ← 读谁家       portal-url: <Portal 地址>   ← 写入口
apollo.meta: <meta 地址> ← 去哪找    token: <开放授权 token>     ← 工作证
apollo.bootstrap.namespaces: ...     app-id / namespace          ← 写到哪

--

补充:Portal 为什么是图形化页面?是 Apollo 的"必然"吗?

不是必然,而是定位决定的。

  • Portal 是 Apollo 的管理控制台(Web UI),面向人做配置的增删改、发布、权限与审计,所以天然做成浏览器可访问的图形界面。
  • 图形化只是 Portal 的前端表现 ,底层仍是 HTTP 接口;发布服务走的就是 Portal 的 Open API(/openapi/v1/...),并不依赖页面。
  • 反过来,Meta Server 和 Config Service 是纯服务端只读角色 ,只提供 HTTP 接口(/services/config、/configs、/notifications),没有也不需要图形界面。

所以结论是:Portal 图形化是"管理控制台"这一定位的自然结果,而不是 Apollo 架构上的强制要求------你完全可以不用页面,只用 Open API 完成同样的发布操作。

五、真实链路走一遍(数据已脱敏)

🕗 8:00 --- 消费服务启动

第 1 步:问指示牌(Meta Server 只干这一件事)

http 复制代码
GET http://<meta地址>/services/config

返回"值班表":

json 复制代码
[
  {"appName":"apollo-configservice","instanceId":"10.x.x.1:8080","port":8080},
  {"appName":"apollo-configservice","instanceId":"10.x.x.2:8080","port":8080},
  {"appName":"apollo-configservice","instanceId":"10.x.x.3:8080","port":8080}
]

第 2 步:找公告栏要配置

http 复制代码
GET http://10.x.x.1:8080/configs/<appId>/default/<namespace>
json 复制代码
{
  "appId": "<appId>",
  "namespaceName": "<namespace>",
  "configurations": {
    "some.config.key": "{ ... 业务配置 JSON ... }"
  }
}

第 3 步:登记"有更新喊我"(长轮询)

http 复制代码
GET /notifications/v2?appId=<appId>&namespace=<ns>&notificationId=38

这个请求挂住不立即返回 ;一旦有新发布,立刻吐回 notificationId=39,

客户端重新拉一次配置,本地缓存更新。

🕑 14:00 --- 改配置(发布服务三步 Open API)

http 复制代码
① GET  /openapi/v1/envs/{env}/apps/{appId}/clusters/{cluster}/namespaces/{ns}/items/{key}
       → 教务处先把现有底稿给你看
② PUT  同路径  Body: {"value":"新值","comment":"变更说明"}
       → 改底稿(此刻只是草稿,公告栏还是旧的!)
③ POST /openapi/v1/envs/{env}/apps/{appId}/clusters/{cluster}/namespaces/{ns}/releases
       → 盖章发布(生效开关)

Portal 落库后的两张表(这就是"教务处存什么"):

复制代码
Item 表(草稿态)                Release 表(发布快照)
┌──────────┬──────────┐         ┌──────────────┬─────────────┐
│ key      │ value    │         │ releaseTitle │ 配置快照     │
│ some.key │ {..v3..} │         │ rel-v3       │ {some.key:  │
└──────────┴──────────┘         └──────────────┘  {..v3..}}  │

⚡ 14:00:01 --- 自动生效

复制代码
Portal 发布 → Config Service 发现新快照 → 缓存换新
→ 挂着的长轮询立刻返回新 notificationId
→ 消费服务重新 GET /configs → 拿到新值 → 下一个请求即生效

六、联调踩过的坑(附排查方法论)

坑 1:只改 item,不点发布

② 修改 之后 ③ 发布 没执行------Item 表是 v3、Release 表还是 v2,

而 Config Service 只认 Release 快照 → 消费方永远读到旧值。

发布三步不是仪式感,第 ③ 步是生效开关。

坑 2:发布服务的 Portal 地址配错

三个故障形态,一条命令即可判别(把地址换成待测的):

bash 复制代码
curl -is "http://<待测地址>/openapi/v1/envs/{env}/apps/{appId}/clusters/{cluster}/namespaces/{ns}/items/{key}"
返回 结论
401 + JSON ✅ 路由正确(没带 token 被 Portal 鉴权拦截,正是我们要的)
404 + Spring 默认错误体(message 为空) ❌ 该地址没有路由 Open API ------Portal 对任何 /openapi/* 请求都会先鉴权后 404,没带 token 就拿到 404 说明请求根本没到 Portal
连接被拒 / 超时 ❌ 端口上没服务或网络不通

经验:"管理入口域名"≠"Open API 入口域名" 。一个网关后可能同时挂着

Web 控制台、服务发现、Open API 三类路由,域名对不代表路径通。务必实测。

坑 3:bootstrap.namespaces 与按需读取分不清

  • apollo.bootstrap.namespaces:启动即加载 进 Spring(供 @Value 注入用)
  • 代码里 ConfigService.getConfig(namespace):按需读取,首次调用才拉取并注册长轮询

业务代码按需读时不需要 挤进 bootstrap;只有要用 @Value 直接注入时才加。

坑 4:跨应用读取

配置放在别的应用名下时,消费方需要显式声明目标(如 appId:namespace 形态或

客户端双参 API)。但优先考虑把配置放到消费方自己的应用下 ,发布方经

Open API 跨应用写入------权限边界更清晰。

七、端口速查表(8080 / 8070 / 8090 ...分别是谁)

Apollo 各组件默认端口容易记混,先给结论:

端口 组件 说明
8070 Portal 管理控制台(Web UI)+ Open API 写入口,浏览器访问 http://<portal地址>:8070
8080 Config Service 配置读取接口 /configs、长轮询 /notifications/v2
8090 Admin Service Portal 与数据库之间的管理接口,供 Portal 调用,业务方一般不直连
8080(同一进程) Meta Server 与 Config Service 同进程,走 /services/config 指路接口

几个容易踩的点:

  • Meta Server 没有独立端口 :它就是 Config Service 进程里的 /services/config 接口,所以「Meta 的端口」= Config Service 的端口(默认 8080)。
  • Portal 是 8070,不是 8080 :很多人把 Portal 和 Config Service 的端口记反,结果 portal-url 配成 8080,请求打到 Config Service 上自然 404。
  • Admin Service 8090 不用暴露给业务方:它只服务于 Portal,业务侧只需要 Portal(8070)和 Config Service(8080)。
  • 以上都是默认值 ,实际部署常被改(如容器化后统一走网关),以 apollo-configservice、apollo-adminservice、apollo-portal 各自 application.yml 里的 server.port 为准。

一句话记法:8070 写(Portal)、8080 读(Config/Meta)、8090 内部(Admin)。



七、配置键速查表

配置键 配在哪 作用
app.id 消费服务 yaml 读谁家(默认读自己应用名下的 namespace)
apollo.meta 消费服务 yaml 服务发现地址(只找节点,不读配置)
apollo.bootstrap.namespaces 消费服务 yaml 启动即加载的 namespace 列表
portal-url 发布服务配置 Open API 写入口(必须是Portal 的地址)
token 发布服务配置(环境变量注入) Portal 开放授权的工作证,按 appId+namespace 授权
app-id / namespace 发布服务配置 写入目标(建议支持按环境/站点覆盖)
env 双方 环境标识(如 DEV/UAT/PRO,以 Portal 实际注册为准)

八、总结

  • 改课程表去教务处,看课程表先看指示牌再去公告栏------指示牌自己可没有课程表
  • 写入口全系统唯一(Portal + Open API + token),读路径全靠"Meta 找节点 +
    Config 只读分发 + 长轮询自动刷新"
  • 排查三板斧:401 说明路通了、404 先怀疑路由、refused 先怀疑端口
  • 记住"草稿 vs 快照":改了不发布 = 抽屉里改了、公告栏没换

有问题欢迎交流。文中比喻纯属帮助记忆,生产请以 Apollo 官方文档为准。

相关推荐
cfm_29141 小时前
偏向锁的Epoch优化机制
java
CRMEB系统商城1 小时前
家电零售的供应商协同与物流提效
java·开发语言·人工智能·小程序·1024程序员节
jason.zeng@15022071 小时前
Nginx 配置详解(静态 HTML、下载目录、API 反向代理三套场景)
java·vue.js·1024程序员节
鬼手点金1 小时前
从 API 消息到模型 Token:Chat Template
java·前端·javascript·数据库·人工智能·深度学习·1024程序员节
Shadow(⊙o⊙)1 小时前
LangChain 自定义工具全解析:从 @tool 到 bind_tools 的完整调用链路
java·服务器·前端·1024程序员节
王大师王文峰1 小时前
Java+AI 面试题(二):业务场景设计 10 例【客服机器人、合同审查、Text2SQL、告警降噪、成本优化】场景题答法与追问链路
java·开发语言·人工智能
CHHH_HHH2 小时前
【Linux网络篇】初识网络与Socket编程基础
linux·服务器·c语言·开发语言·网络·后端·1024程序员节
弦儿2 小时前
后端 Web 实战:员工管理(新增员工 + 事务管理 + 文件上传)
java·后端
Gopher_HBo2 小时前
Go reflect包值操作 Value 的读写、可设置性与 interface 布局
后端