“银行有 Dev、Test、UAT、Pre-Prod、Prod 五个环境。每个环境一套数据库、一套中间件、一套配置。Nacos 把这些配置集中管理,让’在正确环境运行正确配置’这件事变得可审计、可追溯、可回滚。“
前言
在 HSBC 的微服务架构里,Nacos 是服务治理的基础设施:
- 服务注册发现:Payment Service 启动时自动注册,Account Service 通过服务名找到它,无需硬编码 IP
- 配置中心:所有环境的配置文件(数据库密码、API 地址、开关)统一管理,支持热更新
- 命名空间隔离:Dev/Test/UAT/Prod 完全隔离,配置文件不会串环境
- 审计追溯:谁在什么时间改了哪个配置,全部有记录(银行合规要求)
Nacos = Naming Configuration Service,是阿里巴巴开源的微服务基础设施,Spring Cloud Alibaba 默认集成。
1. Nacos 架构
Nacos 架构:
┌─────────────────────────────────────────────────────────┐
│ Nacos Console (Web UI) │
│ 服务列表 | 配置列表 | 命名空间 | 权限管理 │
└──────────────────────┬────────────────────────────────┘
│ Open API / SDK
┌─────────────┼─────────────┐
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ Dev 服务注册 │ │ Test 服务注册 │ │ Prod 服务注册 │
│ (命名空间:dev) │ │ (命名空间:test)│ │ (命名空间:prod)│
└────────┬───────┘ └───────┬────────┘ └───────┬────────┘
│ │ │
│ ┌─────────────┴─────────────┐ │
│ │ Nacos Server 集群 │ │
│ │ :8848 Console/API │ │
│ │ :9848 gRPC │ │
│ │ MySQL/Embedded DB 存储 │ │
│ └───────────────────────────┘ │
│ │
▼ ▼
┌────────────────────────┐ ┌────────────────────────┐
│ Spring Cloud 微服务 │ │ Spring Cloud 微服务 │
│ Payment Service │ │ Account Service │
│ │ │ │
│ bootstrap.yml: │ │ @EnableDiscoveryClient │
│ nacos: │ │ │
│ server-addr: ... │ │ │
│ namespace: dev │ │ │
└────────────────────────┘ └────────────────────────┘
1.1 运行模式
| 模式 | 数据存储 | 适用场景 | 生产推荐 |
|---|---|---|---|
| 单机 | Embedded(内存) | 开发/测试 | ❌ |
| 集群 | MySQL | 生产环境 | ✅ |
| 多机房 | MySQL + DR | 银行两地三中心 | ✅ |
2. Kubernetes 集群部署
2.1 Helm 部署 Nacos 集群
# nacos-helm/values.yaml
nacos:
image:
repository: nacos/nacos-server
tag: 2.3.2
replicaCount: 3 # 生产至少 3 节点
# 外置 MySQL 数据库(生产必须)
persistence:
enabled: true
storageClass: "nfs-client"
size: 10Gi
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 2000m
memory: 2Gi
# JVM 参数(Nacos 需要较大内存)
jvmOptions: "-Xms512m -Xmx512m -Dnacos.standalone=false"
service:
type: ClusterIP
port: 8848
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- nacos.bank.internal
tls:
- hosts: [nacos.bank.internal]
secretName: nacos-tls
# 外置数据库配置
externalDatabase:
host: mysql-prod.bank.internal
port: 3306
dbName: nacos_config
user: nacos
password: ${NACOS_DB_PASSWORD}
# 安装
helm install nacos nacos/nacos -n nacos \
--create-namespace \
-f nacos-helm/values.yaml \
--set-string externalDatabase.password=$NACOS_DB_PASSWORD
# 验证
kubectl get pods -n nacos -l app=nacos
# → nacos-0 Running, nacos-1 Running, nacos-2 Running
2.2 MySQL 数据库初始化
-- Nacos 需要专门的数据库
CREATE DATABASE nacos_config CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Nacos 自动建表(首次启动时会创建 11 张表)
-- config_info:配置内容
-- config_tags_relation:配置标签
-- group_capacity:分组容量
-- his_config_info:配置历史(审计)
-- service商机注册信息
3. 服务注册与发现
3.1 微服务接入 Nacos
<!-- pom.xml -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2023.0.1.2</version>
</dependency>
# bootstrap.yml(必须用 bootstrap,不是 application.yml)
# bootstrap 优先级高于 application,用于引导配置加载
spring:
application:
name: payment-service # 注册到 Nacos 的服务名(必须唯一)
cloud:
nacos:
# 服务发现
discovery:
enabled: true
server-addr: nacos.bank.internal:8848
namespace: ${NACOS_NAMESPACE:dev} # 命名空间隔离环境
group: ${NACOS_GROUP:DEFAULT_GROUP} # 分组(不同业务线)
cluster-name: ${NACOS_CLUSTER:cluster-a} # 集群名(用于同机房优先)
# 主动心跳(生产推荐关闭,用 VPC 网络检测)
heart-beat-interval: 5000
heart-beat-timeout: 15000
ip-delete-timeout: 30s
# 元数据:附加信息(机房、成本中心)
metadata:
datacenter: ${DATACENTER:hk}
cost-center: CC-PAYMENT
version: ${APP_VERSION:unknown}
# 配置中心(下一节详解)
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${NACOS_NAMESPACE:dev}
file-extension: yaml
3.2 服务调用:服务名代替 IP
// RestTemplate 方式(简单场景)
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced // 关键:启用负载均衡,用服务名代替 IP
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@Service
@RequiredArgsConstructor
public class PaymentService {
private final RestTemplate restTemplate;
// ❌ 硬编码 IP(禁止)
// restTemplate.getForObject("http://192.168.1.10:8080/accounts/123", Account.class)
// ✅ 使用服务名(推荐)
// Nacos 自动解析 account-service → 可用的 Pod IP 列表
public Account getAccount(String accountId) {
return restTemplate.getForObject(
"http://account-service/api/v1/accounts/{id}",
Account.class,
accountId
);
}
}
// OpenFeign 方式(推荐,银行系统标准)
@FeignClient(name = "account-service", fallback = AccountServiceFallback.class)
public interface AccountServiceClient {
@GetMapping("/api/v1/accounts/{accountId}")
Account getAccount(@PathVariable String accountId);
@PostMapping("/api/v1/accounts/{accountId}/freeze")
void freezeAccount(@PathVariable String accountId, @RequestBody FreezeRequest request);
}
// 降级实现(Account Service 宕机时执行)
@Component
@Slf4j
public class AccountServiceFallback implements AccountServiceClient {
@Override
public Account getAccount(String accountId) {
log.error("Account Service 不可用,降级返回兜底数据: accountId={}", accountId);
return Account.builder()
.accountId(accountId)
.status("UNAVAILABLE")
.build();
}
@Override
public void freezeAccount(String accountId, FreezeRequest request) {
log.warn("Account Service 不可用,跳过冻结操作");
}
}
3.3 同机房优先调用
Nacos 提供了权重路由和同机房优先能力,避免跨地域调用延迟:
spring:
cloud:
nacos:
discovery:
# 同机房优先:优先调用同一 cluster 的实例
cluster-name: ${NACOS_CLUSTER:cluster-a}
# Nacos 控制台 → 服务详情 → 集群管理
# 可为每个实例设置权重(0-1),用于灰度发布:
# 实例 v1: weight=1.0 (100% 流量)
# 实例 v2: weight=0.05 (5% 流量)
4. 配置中心:多环境管理
4.1 核心概念
配置管理三要素:
命名空间(Namespace):隔离环境
├── dev → 开发环境
├── test → 测试环境
├── uat → 用户验收测试
├── pre-prod → 预生产
└── prod → 生产
分组(Group):隔离业务线
├── DEFAULT_GROUP → 默认
├── RBWM_GROUP → 零售银行
├── CMB_GROUP → 工商金融
└── GBM_GROUP → 环球银行
Data ID:配置文件名
payment-service.yaml → payment-service 的配置
application.yaml → 所有服务共享的配置
4.2 共享配置与私有配置
# 场景 1:所有服务共享的配置(application.yaml)
# Data ID: application.yaml
# Group: DEFAULT_GROUP
# Namespace: dev
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
logging:
level:
root: INFO
com.hsbc.bank: DEBUG
# 场景 2:payment-service 私有配置
# Data ID: payment-service.yaml
# Group: DEFAULT_GROUP
# Namespace: dev
payment:
clearing:
endpoint: https://clearing-sandbox.hsbc.com/api # 沙箱地址
timeout: 5000
retry:
max-attempts: 3
backoff-ms: 1000
limits:
daily-max-amount: 500000 # 日限额(CNY)
single-max-amount: 50000 # 单笔限额
# 场景 3:prod 环境专用(覆盖 dev 配置)
# Data ID: payment-service-prod.yaml
# Group: DEFAULT_GROUP
# Namespace: prod
payment:
clearing:
endpoint: https://clearing.hsbc.com/api # 生产地址
timeout: 3000 # 生产超时更短
limits:
daily-max-amount: 5000000
single-max-amount: 500000
4.3 Spring Boot 接入配置中心
# bootstrap.yml(完整配置)
spring:
cloud:
nacos:
config:
# 配置中心地址
server-addr: nacos.bank.internal:8848
namespace: ${NACOS_NAMESPACE:dev}
# 自动加载以下配置文件(优先级从低到高):
# 1. shared-dataids:所有服务共享
# 2. ${prefix}-${spring.profiles.active}.${file-extension}
# 3. ${prefix}-${file-extension}
# 共享配置(从小到大的优先级)
shared-dataids: application.yaml
refreshable-dataids: application.yaml
# 文件扩展名
file-extension: yaml
encode: UTF-8
# 配置监听:变化时自动刷新(无需重启)
refresh-enabled: true
# 超时
timeout: 3000
profiles:
active: ${SPRING_PROFILES_ACTIVE:dev}
// 自动刷新配置(无需重启)
@Service
@Slf4j
public class PaymentService {
// 方式 1:@RefreshScope 注解(推荐)
// 配置变化时,Spring 自动重新注入新值
@RefreshScope
@ConfigurationProperties(prefix = "payment")
@Data
public static class PaymentConfig {
private Clearing clearing = new Clearing();
private Limits limits = new Limits();
@Data
public static class Clearing {
private String endpoint;
private int timeout;
}
@Data
public static class Limits {
private BigDecimal dailyMaxAmount;
private BigDecimal singleMaxAmount;
}
}
private final PaymentConfig config;
// 方式 2:@NacosConfigurationProperties(更简洁)
// 直接绑定配置,前缀 payment.clearing
@NacosConfigurationProperties(prefix = "payment.clearing", autoRefreshed = true)
@Data
public static class ClearingConfig {
private String endpoint;
private int timeout = 5000;
}
@NacosValue("${payment.limits.daily-max-amount:0}")
private BigDecimal dailyLimit;
// 使用配置
public void processPayment(Payment payment) {
if (payment.getAmount().compareTo(dailyLimit) > 0) {
throw new PaymentLimitExceededException("超出日限额: " + dailyLimit);
}
// 调用清算接口
clearingClient.call(config.getClearing().getEndpoint(), payment);
}
}
4.4 配置热更新:开关驱动业务
Nacos 最重要的能力之一:运行时修改配置,业务自动感知。
// Nacos 配置监听器(精细控制)
@NacosInjected
private ConfigService configService;
@PostConstruct
public void init() throws NacosException {
String dataId = "payment-service.yaml";
String group = "DEFAULT_GROUP";
String namespace = "prod";
// 监听配置变化
configService.addListener(dataId, group, new Listener() {
@Override
public Executor getExecutor() {
return Executors.newSingleThreadExecutor();
}
@Override
public void receiveConfigInfo(String configInfo) {
log.info("配置变更收到: {}", configInfo);
// 解析配置,更新内存状态
PaymentConfig newConfig = parseYaml(configInfo);
updateConfig(newConfig);
}
});
}
# 生产开关:无需发版即可关闭功能
# Data ID: feature-flags.yaml
# Group: RBWM_GROUP
# Namespace: prod
feature:
enable-batch-payment: true # 批量支付功能(刚上线,灰度中)
enable-crypto-remittance: false # 加密货币汇款(监管未批准)
enable-instant-settlement: false # 实时结算(压测中)
enable-ai-approval: true # AI 审批辅助(已上线)
5. 命名空间隔离:银行多环境
银行标准五环境:
┌─────────────────────────────────────────────────────────────┐
│ Nacos Console │
│ │
│ Namespace: dev │
│ ├── payment-service.yaml │
│ ├── account-service.yaml │
│ │
│ Namespace: test │
│ ├── payment-service.yaml (独立配置,IP/密码都不同) │
│ ├── account-service.yaml │
│ │
│ Namespace: uat │
│ ├── payment-service.yaml │
│ │
│ Namespace: pre-prod │
│ ├── payment-service.yaml │
│ │
│ Namespace: prod │
│ ├── payment-service.yaml (最高安全级别,只读权限) │
│ └── account-service.yaml │
└─────────────────────────────────────────────────────────────┘
5.1 K8s 中通过环境变量切换命名空间
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: payment-service
namespace: payments
spec:
replicas: 3
template:
spec:
containers:
- name: payment-service
env:
# 根据 K8s 命名空间自动选择 Nacos 命名空间
- name: NACOS_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: SPRING_PROFILES_ACTIVE
value: prod
- name: NACOS_SERVER_ADDR
value: "nacos.nacos:8848"
5.2 环境差异对比
# Nacos 控制台支持配置对比(跨命名空间)
# 场景:发布前对比 UAT 和 Pre-Prod 的 payment-service.yaml 差异
# 典型差异项:
# ┌──────────────────────┬──────────────┬──────────────────┐
# │ 配置项 │ UAT │ Pre-Prod │
# ├──────────────────────┼──────────────┼──────────────────┤
# │ database.host │ uat-mysql │ preprod-mysql │
# │ database.maxPool │ 10 │ 30 │
# │ clearing.endpoint │ uat-clearing │ preprod-clearing │
# │ monitoring.enabled │ true │ true │
# └──────────────────────┴──────────────┴──────────────────┘
6. 权限控制与审计
银行对配置变更有严格的合规要求:谁可以改配置?改了之后是否可追溯?
6.1 Nacos 权限模型
# Nacos 内置三种角色:
# admin → 全部权限(只能有 2-3 人)
# dev → 读写自己业务的配置
# readonly → 只能查看(业务人员、审计人员)
# 权限配置通过 Nacos 控制台或 API:
# 控制台 → 权限控制 → 用户管理 → 角色管理
6.2 配置变更审计
-- Nacos 的 his_config_info 表记录了所有配置变更历史
-- 银行合规要求:至少保留 1 年
SELECT
data_id,
group_id,
app_name,
content,
operater,
operate_time,
op_type -- INSERT / UPDATE / DELETE
FROM his_config_info
WHERE data_id = 'payment-service.yaml'
AND app_name = 'payment-service'
AND operate_time > DATE_SUB(NOW(), INTERVAL 1 YEAR)
ORDER BY operate_time DESC;
6.3 敏感配置加密
# Nacos 支持配置加密(使用 AES 算法)
# 适用场景:数据库密码、API Key、证书
# 1. 在 Nacos Server 配置加密密钥
# conf/application.properties
nacos.config.encryption.algorithm=AES
nacos.config.encryption.key=${NACOS_ENCRYPTION_KEY}
# 2. 存储时用 {aes}前缀 包裹
# Data ID: payment-service.yaml
spring:
datasource:
password: {aes}7fK2x9Pq4mZ3vN5jR8tU1wY0eA6sD3fG # 加密存储
# 3. Spring Boot 启动时自动解密(SDK 内置)
7. 高可用与多集群部署
7.1 双机房容灾
银行两地三中心架构:
香港主数据中心 深圳灾备数据中心
┌─────────────────┐ ┌─────────────────┐
│ Nacos 集群 (HK) │◄── 同步 ────▶│ Nacos 集群 (SZ) │
│ 节点: 3 │ MySQL 主从 │ 节点: 3 │
│ Cluster-A │ │ Cluster-B │
└────────┬────────┘ └────────┬────────┘
│ │
│ VIP(Virtual IP) │
└────────────┬─────────────────────┘
│
┌───────┴────────┐
│ VIP Manager │
│ (K8s MetalLB) │
└───────┬────────┘
│ 自动切换
┌─────────────┼─────────────┐
▼ ▼ ▼
payment-svc account-svc gateway-svc
# 微服务配置:同时注册到两个 Nacos 集群
spring:
cloud:
nacos:
discovery:
# 主集群优先
server-addr: nacos-hk.bank.internal:8848,nacos-sz.bank.internal:8848
# 如果主集群全部不可用,自动切换到备集群
failover: true
7.2 Nacos 集群节点配置
# nacos/conf/cluster.conf(每个节点都要配置)
# 格式:IP:Port(必须是内网 IP,不能是域名)
10.100.1.10:8848
10.100.1.11:8848
10.100.1.12:8848
8. 与 Spring Cloud Alibaba 集成完整示例
# bootstrap.yml(生产级完整配置)
spring:
application:
name: account-service
cloud:
nacos:
discovery:
enabled: true
server-addr: ${NACOS_SERVER_ADDR:nacos.bank.internal:8848}
namespace: ${NACOS_NAMESPACE:prod}
group: ${NACOS_GROUP:RBWM_GROUP}
cluster-name: ${NACOS_CLUSTER:cluster-a}
# 元数据(控制台显示用)
metadata:
environment: ${NACOS_NAMESPACE}
version: ${APP_VERSION:unknown}
git-commit: ${GIT_COMMIT_SHA:unknown}
# 健康检查
health-check-interval: 10s
config:
server-addr: ${spring.cloud.nacos.discovery.server-addr}
namespace: ${NACOS_NAMESPACE:prod}
group: ${NACOS_GROUP:RBWM_GROUP}
file-extension: yaml
refresh-enabled: true
shared-dataids: application.yaml
refreshable-dataids: application.yaml
timeout: 5000
encode: UTF-8
profiles:
active: ${SPRING_PROFILES_ACTIVE:prod}
# actuator:暴露 Nacos 端点
management:
endpoints:
web:
exposure:
include: health,info,nacos-discovery,nacos-config
endpoint:
health:
show-details: always
相关阅读:Spring Cloud 微服务入门完全指南 · Spring Cloud Gateway 银行网关实战 · 服务治理:限流熔断与降级