Nacos 高可用部署
高可用架构
集群架构
┌─────────────────────────────────────────────────────┐
│ Nginx / SLB │
│ (负载均衡器) │
└───────────────────┬─────────────────────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Nacos 1 │ │ Nacos 2 │ │ Nacos 3 │
│ :8848 │ │ :8848 │ │ :8848 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼───────────────┘
│
┌────────▼────────┐
│ MySQL 集群 │
│ (数据持久化) │
└─────────────────┘
核心特性
- 数据一致性:支持 AP 和 CP 模式切换
- 故障转移:节点故障自动切换
- 数据同步:集群节点数据实时同步
- 负载均衡:支持多种负载均衡策略
集群部署
1. 环境准备
# 服务器规划
nacos1: 192.168.1.101
nacos2: 192.168.1.102
nacos3: 192.168.1.103
# MySQL 准备
mysql: 192.168.1.200:3306
database: nacos_config
user: nacos
password: nacos123
2. 数据库初始化
-- 创建数据库
CREATE DATABASE nacos_config CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 初始化表结构
SOURCE /path/to/nacos/conf/nacos-mysql.sql;
3. 配置文件
application.properties(所有节点)
# 集群模式
nacos.core.auth.enabled=true
nacos.core.auth.server.identity.key=serverIdentity
nacos.core.auth.server.identity.value=security
# 数据源配置
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://192.168.1.200:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
db.user=nacos
db.password=nacos123
# 集群配置
nacos.naming.cluster.conf=192.168.1.101:8848,192.168.1.102:8848,192.168.1.103:8848
# 节点标识
server.tomcat.basedir=/opt/nacos/tomcat
cluster.conf(所有节点相同)
192.168.1.101:8848
192.168.1.102:8848
192.168.1.103:8848
4. 启动集群
# 节点 1
cd /opt/nacos/bin
sh startup.sh -m cluster
# 节点 2
cd /opt/nacos/bin
sh startup.sh -m cluster
# 节点 3
cd /opt/nacos/bin
sh startup.sh -m cluster
5. 验证集群
# 查看集群状态
curl http://192.168.1.101:8848/nacos/v1/ns/operator/servers
# 查看节点健康状态
curl http://192.168.1.101:8848/nacos/v1/console/health/readiness
Nginx 负载均衡配置
基础配置
upstream nacos_cluster {
server 192.168.1.101:8848 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8848 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.103:8848 weight=1 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name nacos.example.com;
location /nacos {
proxy_pass http://nacos_cluster/nacos;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 连接超时
proxy_connect_timeout 10s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓冲配置
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
}
}
HTTPS 配置
server {
listen 443 ssl http2;
server_name nacos.example.com;
ssl_certificate /etc/nginx/ssl/nacos.crt;
ssl_certificate_key /etc/nginx/ssl/nacos.key;
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location /nacos {
proxy_pass http://nacos_cluster/nacos;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name nacos.example.com;
return 301 https://$server_name$request_uri;
}
Docker 部署
docker-compose.yml
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: nacos-mysql
environment:
MYSQL_ROOT_PASSWORD: root123
MYSQL_DATABASE: nacos_config
MYSQL_USER: nacos
MYSQL_PASSWORD: nacos123
volumes:
- mysql_data:/var/lib/mysql
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
networks:
- nacos-network
nacos1:
image: nacos/nacos-server:2.2.0
container_name: nacos1
environment:
- MODE=cluster
- NACOS_SERVERS=nacos1:8848;nacos2:8848;nacos3:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos123
- JVM_XMS=512m
- JVM_XMX=512m
ports:
- "8848:8848"
depends_on:
- mysql
networks:
- nacos-network
nacos2:
image: nacos/nacos-server:2.2.0
container_name: nacos2
environment:
- MODE=cluster
- NACOS_SERVERS=nacos1:8848;nacos2:8848;nacos3:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos123
- JVM_XMS=512m
- JVM_XMX=512m
ports:
- "8849:8848"
depends_on:
- mysql
networks:
- nacos-network
nacos3:
image: nacos/nacos-server:2.2.0
container_name: nacos3
environment:
- MODE=cluster
- NACOS_SERVERS=nacos1:8848;nacos2:8848;nacos3:8848
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos_config
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos123
- JVM_XMS=512m
- JVM_XMX=512m
ports:
- "8850:8848"
depends_on:
- mysql
networks:
- nacos-network
nginx:
image: nginx:alpine
container_name: nacos-nginx
ports:
- "80:80"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- nacos1
- nacos2
- nacos3
networks:
- nacos-network
volumes:
mysql_data:
networks:
nacos-network:
driver: bridge
K8s 部署
StatefulSet
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nacos
labels:
app: nacos
spec:
serviceName: nacos
replicas: 3
selector:
matchLabels:
app: nacos
template:
metadata:
labels:
app: nacos
spec:
containers:
- name: nacos
image: nacos/nacos-server:2.2.0
ports:
- containerPort: 8848
name: client
- containerPort: 9848
name: client-rpc
- containerPort: 9849
name: raft-rpc
env:
- name: MODE
value: "cluster"
- name: NACOS_SERVERS
value: "nacos-0.nacos:8848;nacos-1.nacos:8848;nacos-2.nacos:8848"
- name: SPRING_DATASOURCE_PLATFORM
value: "mysql"
- name: MYSQL_SERVICE_HOST
value: "mysql.default.svc.cluster.local"
- name: MYSQL_SERVICE_PORT
value: "3306"
- name: MYSQL_SERVICE_DB_NAME
value: "nacos_config"
- name: MYSQL_SERVICE_USER
value: "nacos"
- name: MYSQL_SERVICE_PASSWORD
value: "nacos123"
resources:
requests:
memory: "512Mi"
cpu: "250m"
limits:
memory: "1Gi"
cpu: "500m"
livenessProbe:
httpGet:
path: /nacos/v1/console/health/readiness
port: 8848
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /nacos/v1/console/health/readiness
port: 8848
initialDelaySeconds: 10
periodSeconds: 5
Service
apiVersion: v1
kind: Service
metadata:
name: nacos
labels:
app: nacos
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 8848
name: client
targetPort: 8848
- port: 9848
name: client-rpc
targetPort: 9848
- port: 9849
name: raft-rpc
targetPort: 9849
selector:
app: nacos
---
apiVersion: v1
kind: Service
metadata:
name: nacos-headless
labels:
app: nacos
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: 8848
name: http
selector:
app: nacos
性能优化
JVM 配置
# bin/startup.sh 中修改
JAVA_OPT="${JAVA_OPT} -server -Xms2g -Xmx2g -Xmn1g"
JAVA_OPT="${JAVA_OPT} -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m"
JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow -XX:+HeapDumpOnOutOfMemoryError"
JAVA_OPT="${JAVA_OPT} -XX:HeapDumpPath=/opt/nacos/logs/java_heapdump.hprof"
JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages"
数据库连接池
# application.properties
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://mysql:3306/nacos_config?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false
db.user=nacos
db.password=nacos123
# HikariCP 配置
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=50
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
日志配置
<!-- conf/nacos-logback.xml -->
<configuration>
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${nacos.home}/logs/nacos.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${nacos.home}/logs/nacos.log.%d{yyyy-MM-dd}.%i</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE"/>
</root>
</configuration>
监控告警
Prometheus 配置
# prometheus.yml
scrape_configs:
- job_name: 'nacos'
static_configs:
- targets: ['nacos1:8848', 'nacos2:8848', 'nacos3:8848']
metrics_path: '/nacos/actuator/prometheus'
Grafana 面板
导入 Nacos 监控面板(Dashboard ID: 10475)
告警规则
# alert_rules.yml
groups:
- name: nacos
rules:
- alert: NacosNodeDown
expr: up{job="nacos"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Nacos 节点 {{ $labels.instance }} 宕机"
description: "Nacos 节点 {{ $labels.instance }} 已经宕机超过 1 分钟"
- alert: NacosServiceCountLow
expr: nacos_naming_service_count < 10
for: 5m
labels:
severity: warning
annotations:
summary: "Nacos 服务数量过低"
description: "Nacos 注册的服务数量低于 10 个"
常见问题
1. 集群启动失败
问题:节点无法加入集群
解决方案:
- 检查 cluster.conf 配置
- 检查网络连通性
- 查看日志文件
2. 数据不一致
问题:集群节点数据不一致
解决方案:
- 检查数据库连接
- 检查节点间通信
- 重启问题节点
3. 性能问题
问题:集群响应慢
解决方案:
- 优化 JVM 参数
- 增加数据库连接池
- 检查网络延迟
总结
Nacos 集群部署可以实现服务注册中心的高可用性,通过合理的架构设计和配置优化,可以确保系统的稳定运行。
在生产环境中,建议部署至少 3 个节点,使用独立的数据库,并配置完善的监控告警机制。