部署微服务系统步骤与最佳实践

一、前言

随着业务复杂度的增加,单体应用架构已经无法满足大型系统的需求,微服务架构因其灵活性、可扩展性和可维护性成为主流选择。然而,部署和管理分布式微服务系统比传统单体应用更为复杂,需要系统性的规划和执行。本文将详细介绍微服务系统的部署步骤和最佳实践,以若依微服务框架为例进行说明。

二、微服务部署前的准备工作

(一)环境规划

在部署微服务系统前,需要对环境进行合理规划:

  1. 服务器资源评估

    • 根据业务量和服务数量估算所需服务器资源
    • 区分开发、测试、预发布和生产环境
    • 规划每个服务的CPU、内存和存储需求
  2. 网络规划

    • 设计内部服务网络结构
    • 规划服务间通信策略
    • 确定对外服务的网络策略和安全措施
  3. 中间件选型

    • 注册中心:Nacos、Eureka、Consul等
    • 配置中心:Nacos、Apollo、Spring Cloud Config等
    • 消息队列:RabbitMQ、Kafka、RocketMQ等
    • 网关:Spring Cloud Gateway、Zuul等
    • 分布式事务:Seata等

(二)基础设施准备

  1. 容器化环境搭建

    • Docker环境安装与配置
    • Kubernetes集群搭建(可选)
    • Harbor私有镜像仓库部署(可选)
  2. 持续集成/持续部署(CI/CD)工具

    • Jenkins/GitLab CI/GitHub Actions等工具准备
    • 构建流水线设计
    • 自动化测试环境准备
  3. 监控和日志系统

    • 监控系统:Prometheus + Grafana
    • 日志收集:ELK(Elasticsearch, Logstash, Kibana)或EFK(Elasticsearch, Fluentd, Kibana)
    • 链路追踪:SkyWalking、Zipkin、Jaeger等

三、若依微服务系统部署步骤

(一)基础环境部署

  1. JDK安装与配置
1
2
3
4
5
6
7
8
9
10
# 安装JDK
apt update
apt install -y openjdk-8-jdk
# 或者
yum install -y java-1.8.0-openjdk

# 配置JAVA_HOME
echo 'export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64' >> /etc/profile
echo 'export PATH=$PATH:$JAVA_HOME/bin' >> /etc/profile
source /etc/profile
  1. MySQL安装与配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装MySQL
apt install -y mysql-server
# 或者
yum install -y mysql-server

# 启动MySQL并设置开机自启
systemctl start mysqld
systemctl enable mysqld

# 安全配置
mysql_secure_installation

# 创建数据库和用户
mysql -u root -p
CREATE DATABASE ry-config DEFAULT CHARACTER SET utf8mb4;
CREATE DATABASE ry-cloud DEFAULT CHARACTER SET utf8mb4;
# 创建其他所需数据库...
  1. Redis安装与配置
1
2
3
4
5
6
7
8
9
10
11
12
13
# 安装Redis
apt install -y redis-server
# 或者
yum install -y redis

# 启动Redis并设置开机自启
systemctl start redis
systemctl enable redis

# 修改Redis配置
sed -i 's/bind 127.0.0.1/bind 0.0.0.0/g' /etc/redis/redis.conf
sed -i 's/# requirepass foobared/requirepass yourpassword/g' /etc/redis/redis.conf
systemctl restart redis

(二)中间件服务部署

  1. Nacos部署(注册中心和配置中心)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 下载Nacos
wget https://github.com/alibaba/nacos/releases/download/2.0.3/nacos-server-2.0.3.tar.gz
tar -xzvf nacos-server-2.0.3.tar.gz
cd nacos

# 配置数据库持久化(修改conf/application.properties)
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=nacos
db.password.0=nacos

# 启动Nacos
./bin/startup.sh -m standalone
  1. RabbitMQ部署(消息队列)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 安装RabbitMQ
apt install -y rabbitmq-server
# 或者
yum install -y rabbitmq-server

# 启动RabbitMQ并设置开机自启
systemctl start rabbitmq-server
systemctl enable rabbitmq-server

# 启用管理插件
rabbitmq-plugins enable rabbitmq_management

# 创建管理用户
rabbitmqctl add_user admin password
rabbitmqctl set_user_tags admin administrator
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
  1. Sentinel部署(服务熔断与限流)
1
2
3
4
5
# 下载Sentinel
wget https://github.com/alibaba/Sentinel/releases/download/1.8.2/sentinel-dashboard-1.8.2.jar

# 启动Sentinel
nohup java -Dserver.port=8718 -Dcsp.sentinel.dashboard.server=localhost:8718 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.2.jar > sentinel.log 2>&1 &

(三)微服务应用部署

  1. 准备若依微服务代码
1
2
3
4
5
6
# 克隆若依微服务代码
git clone https://gitee.com/y_project/RuoYi-Cloud.git
cd RuoYi-Cloud

# 修改配置
# 根据环境修改nacos配置中心的配置
  1. 编译打包
1
2
3
4
5
# 使用Maven打包
mvn clean package -DskipTests

# 或者使用脚本打包
sh bin/package.sh
  1. 服务部署顺序

按照依赖关系依次部署各个服务:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 1. 部署网关服务
cd ruoyi-gateway
nohup java -jar ruoyi-gateway.jar > gateway.log 2>&1 &

# 2. 部署认证服务
cd ../ruoyi-auth
nohup java -jar ruoyi-auth.jar > auth.log 2>&1 &

# 3. 部署系统服务
cd ../ruoyi-modules/ruoyi-system
nohup java -jar ruoyi-system.jar > system.log 2>&1 &

# 4. 部署其他业务服务
# ...依次类推

(四)容器化部署(Docker方式)

  1. 编写Dockerfile

为每个服务创建Dockerfile:

1
2
3
4
FROM openjdk:8-jdk-alpine
WORKDIR /app
COPY target/*.jar app.jar
ENTRYPOINT ["java","-jar","app.jar"]
  1. 构建镜像并推送
1
2
3
4
5
6
7
8
9
10
# 构建镜像
docker build -t ruoyi-gateway:1.0 .
docker build -t ruoyi-auth:1.0 .
docker build -t ruoyi-system:1.0 .
# ...其他服务

# 推送到私有仓库(如果有)
docker tag ruoyi-gateway:1.0 registry.example.com/ruoyi/ruoyi-gateway:1.0
docker push registry.example.com/ruoyi/ruoyi-gateway:1.0
# ...其他服务
  1. 使用docker-compose部署

创建docker-compose.yml文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
version: '3'
services:
ruoyi-gateway:
image: ruoyi-gateway:1.0
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR=nacos:8848
depends_on:
- nacos
restart: always

ruoyi-auth:
image: ruoyi-auth:1.0
environment:
- SPRING_PROFILES_ACTIVE=prod
- SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR=nacos:8848
depends_on:
- nacos
- ruoyi-gateway
restart: always

# 其他服务...

nacos:
image: nacos/nacos-server:2.0.3
environment:
- MODE=standalone
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=mysql
- MYSQL_SERVICE_PORT=3306
- MYSQL_SERVICE_DB_NAME=nacos
- MYSQL_SERVICE_USER=nacos
- MYSQL_SERVICE_PASSWORD=nacos
ports:
- "8848:8848"
depends_on:
- mysql
restart: always

mysql:
image: mysql:5.7
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=nacos
- MYSQL_USER=nacos
- MYSQL_PASSWORD=nacos
volumes:
- mysql-data:/var/lib/mysql
restart: always

redis:
image: redis:6
command: redis-server --requirepass yourpassword
volumes:
- redis-data:/data
restart: always

volumes:
mysql-data:
redis-data:

启动服务:

1
docker-compose up -d

(五)Kubernetes部署(进阶)

  1. 准备Kubernetes清单文件

为每个服务创建deployment.yaml和service.yaml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# ruoyi-gateway-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: ruoyi-gateway
spec:
replicas: 2
selector:
matchLabels:
app: ruoyi-gateway
template:
metadata:
labels:
app: ruoyi-gateway
spec:
containers:
- name: ruoyi-gateway
image: registry.example.com/ruoyi/ruoyi-gateway:1.0
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "prod"
- name: SPRING_CLOUD_NACOS_DISCOVERY_SERVER-ADDR
value: "nacos-service:8848"
resources:
requests:
memory: "512Mi"
cpu: "200m"
limits:
memory: "1Gi"
cpu: "500m"
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 120
periodSeconds: 20
---
# ruoyi-gateway-service.yaml
apiVersion: v1
kind: Service
metadata:
name: ruoyi-gateway-service
spec:
selector:
app: ruoyi-gateway
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
  1. 部署到Kubernetes集群
1
2
3
4
5
6
7
8
9
10
# 创建命名空间
kubectl create namespace ruoyi

# 部署服务
kubectl apply -f ruoyi-gateway-deployment.yaml -n ruoyi
kubectl apply -f ruoyi-gateway-service.yaml -n ruoyi
# ...其他服务

# 部署Ingress暴露服务
kubectl apply -f ruoyi-ingress.yaml -n ruoyi

四、部署后的配置与验证

(一)服务健康检查

  1. 检查服务状态
1
2
3
4
5
6
7
8
# 检查Java进程
ps -ef | grep java

# 检查Docker容器
docker ps

# 检查Kubernetes Pod
kubectl get pods -n ruoyi
  1. 检查服务注册情况

访问Nacos控制台(http://nacos-server:8848/nacos),确认所有服务都已正常注册。

  1. 检查服务日志
1
2
3
4
5
6
7
# 查看服务日志
tail -f gateway.log
tail -f auth.log
# ...其他服务

# Docker环境
docker logs -f ruoyi-gateway

(二)系统配置调优

  1. JVM参数优化
1
2
# 修改启动脚本,添加JVM参数
java -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -jar app.jar
  1. 数据库连接池优化

在Nacos配置中心修改数据库连接池配置:

1
2
3
4
5
6
7
8
spring:
datasource:
hikari:
minimum-idle: 5
maximum-pool-size: 20
idle-timeout: 30000
max-lifetime: 1800000
connection-timeout: 30000
  1. 线程池优化

在Nacos配置中心修改线程池配置:

1
2
3
4
thread-pool:
core-pool-size: 10
maximum-pool-size: 100
keep-alive-time: 60

(三)安全加固

  1. 防火墙配置
1
2
3
4
5
6
# 只开放必要端口
ufw allow 22
ufw allow 8080
ufw allow 8848
# ...其他必要端口
ufw enable
  1. 服务间通信加密

配置TLS/SSL证书,确保服务间通信安全。

  1. API网关安全配置

配置网关的认证、授权、限流等安全措施。

五、持续集成与部署(CI/CD)

(一)Jenkins流水线配置

  1. 创建Jenkinsfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
pipeline {
agent any

stages {
stage('Checkout') {
steps {
checkout scm
}
}

stage('Build') {
steps {
sh 'mvn clean package -DskipTests'
}
}

stage('Build Docker Images') {
steps {
sh 'docker build -t ruoyi-gateway:${BUILD_NUMBER} ./ruoyi-gateway'
sh 'docker build -t ruoyi-auth:${BUILD_NUMBER} ./ruoyi-auth'
// ...其他服务
}
}

stage('Push Docker Images') {
steps {
sh 'docker tag ruoyi-gateway:${BUILD_NUMBER} registry.example.com/ruoyi/ruoyi-gateway:${BUILD_NUMBER}'
sh 'docker push registry.example.com/ruoyi/ruoyi-gateway:${BUILD_NUMBER}'
// ...其他服务
}
}

stage('Deploy to Kubernetes') {
steps {
sh "sed -i 's|image: registry.example.com/ruoyi/ruoyi-gateway:.*|image: registry.example.com/ruoyi/ruoyi-gateway:${BUILD_NUMBER}|' kubernetes/ruoyi-gateway-deployment.yaml"
sh 'kubectl apply -f kubernetes/ruoyi-gateway-deployment.yaml -n ruoyi'
// ...其他服务
}
}
}

post {
success {
echo 'Deployment successful!'
}
failure {
echo 'Deployment failed!'
}
}
}
  1. 配置Jenkins任务

在Jenkins中创建Pipeline任务,指向代码仓库中的Jenkinsfile。

(二)GitLab CI/CD配置

  1. 创建.gitlab-ci.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
stages:
- build
- package
- deploy

variables:
MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository"

cache:
paths:
- .m2/repository

build:
stage: build
image: maven:3.6-jdk-8
script:
- mvn clean package -DskipTests
artifacts:
paths:
- "*/target/*.jar"

package:
stage: package
image: docker:19.03.12
services:
- docker:19.03.12-dind
script:
- docker build -t registry.example.com/ruoyi/ruoyi-gateway:$CI_COMMIT_SHORT_SHA ./ruoyi-gateway
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD registry.example.com
- docker push registry.example.com/ruoyi/ruoyi-gateway:$CI_COMMIT_SHORT_SHA
# ...其他服务

deploy:
stage: deploy
image: bitnami/kubectl:latest
script:
- kubectl config use-context my-cluster
- sed -i "s|image: registry.example.com/ruoyi/ruoyi-gateway:.*|image: registry.example.com/ruoyi/ruoyi-gateway:$CI_COMMIT_SHORT_SHA|" kubernetes/ruoyi-gateway-deployment.yaml
- kubectl apply -f kubernetes/ruoyi-gateway-deployment.yaml -n ruoyi
# ...其他服务
environment:
name: production

六、运维与监控

(一)监控系统部署

  1. Prometheus + Grafana部署
1
2
3
# 使用Helm部署Prometheus和Grafana
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/kube-prometheus-stack -n monitoring
  1. 配置Spring Boot Actuator

在每个微服务中添加Actuator依赖并配置:

1
2
3
4
5
6
7
8
9
management:
endpoints:
web:
exposure:
include: "*"
metrics:
export:
prometheus:
enabled: true
  1. 配置Grafana仪表盘

导入Spring Boot和JVM监控仪表盘模板。

(二)日志系统部署

  1. ELK部署
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# 使用Docker Compose部署ELK
cat > docker-compose-elk.yml << EOF
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.0
environment:
- discovery.type=single-node
ports:
- "9200:9200"
volumes:
- elasticsearch-data:/usr/share/elasticsearch/data

logstash:
image: docker.elastic.co/logstash/logstash:7.12.0
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
depends_on:
- elasticsearch

kibana:
image: docker.elastic.co/kibana/kibana:7.12.0
ports:
- "5601:5601"
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
depends_on:
- elasticsearch

volumes:
elasticsearch-data:
EOF

# 创建Logstash配置
cat > logstash.conf << EOF
input {
tcp {
port => 5000
codec => json_lines
}
}

filter {
# 添加过滤器
}

output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "ruoyi-%{+YYYY.MM.dd}"
}
}
EOF

# 启动ELK
docker-compose -f docker-compose-elk.yml up -d
  1. 配置微服务日志输出

在每个微服务的logback配置中添加:

1
2
3
4
5
6
7
8
9
10
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>logstash-server:5000</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder"/>
</appender>

<root level="INFO">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE"/>
<appender-ref ref="LOGSTASH"/>
</root>

(三)链路追踪部署

  1. SkyWalking部署
1
2
3
4
5
6
7
# 下载SkyWalking
wget https://archive.apache.org/dist/skywalking/8.7.0/apache-skywalking-apm-8.7.0.tar.gz
tar -xzvf apache-skywalking-apm-8.7.0.tar.gz
cd apache-skywalking-apm-bin

# 启动SkyWalking
./bin/startup.sh
  1. 配置微服务接入SkyWalking

在微服务启动参数中添加:

1
java -javaagent:/path/to/skywalking-agent.jar -Dskywalking.agent.service_name=ruoyi-gateway -jar ruoyi-gateway.jar

七、常见问题与解决方案

(一)服务注册与发现问题

  1. 服务无法注册到Nacos

    • 检查Nacos服务是否正常运行
    • 检查网络连通性
    • 检查服务配置中的Nacos地址是否正确
  2. 服务注册成功但无法被发现

    • 检查服务实例健康状态
    • 检查服务名称是否一致
    • 检查命名空间和分组配置

(二)配置中心问题

  1. 无法从配置中心获取配置

    • 检查配置文件命名是否正确(应用名-环境.yml)
    • 检查命名空间和分组配置
    • 检查配置中心连接是否正常
  2. 配置更新后服务未生效

    • 检查是否配置了动态刷新注解(@RefreshScope)
    • 检查服务是否订阅了配置变更事件

(三)微服务间通信问题

  1. 服务调用失败

    • 检查服务是否正常注册
    • 检查Feign或RestTemplate配置
    • 检查网络连通性和防火墙设置
  2. 服务调用超时

    • 检查超时配置
    • 检查目标服务负载情况
    • 考虑增加服务实例数量

(四)数据库连接问题

  1. 数据库连接失败

    • 检查数据库服务是否正常运行
    • 检查数据库连接配置
    • 检查网络连通性和防火墙设置
  2. 数据库连接池耗尽

    • 增加连接池大小
    • 优化SQL减少连接占用时间
    • 检查是否存在连接泄漏

八、扩展与优化

(一)系统扩容

  1. 水平扩展

    • 增加服务实例数量
    • 配置负载均衡
    • 确保服务无状态化
  2. 垂直扩展

    • 增加单个服务实例的资源配置
    • 优化JVM参数
    • 调整线程池配置

(二)性能优化

  1. 服务优化

    • 代码级优化
    • 缓存策略优化
    • 异步处理优化
  2. 数据库优化

    • 索引优化
    • SQL优化
    • 读写分离
    • 分库分表

(三)高可用设计

  1. 多活部署

    • 多区域部署
    • 灾备方案
    • 故障自动切换
  2. 限流熔断

    • 配置Sentinel限流规则
    • 配置熔断降级策略
    • 配置热点参数限流

九、总结

部署微服务系统是一个系统工程,需要考虑多个方面的因素,包括基础设施、中间件、应用服务、监控运维等。本文以若依微服务框架为例,详细介绍了微服务系统的部署步骤和最佳实践,希望能为读者提供有价值的参考。

在实际部署过程中,应根据具体的业务需求和技术栈进行调整,并不断优化和完善部署流程,以提高系统的稳定性、可靠性和可维护性。

参考资料

  1. 若依微服务框架官方文档: https://doc.ruoyi.vip/ruoyi-cloud/
  2. Spring Cloud Alibaba文档: https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/en-us/index.html
  3. Kubernetes官方文档: https://kubernetes.io/docs/home/
  4. Docker官方文档: https://docs.docker.com/
  5. 《微服务架构设计模式》- Chris Richardson
  6. 《DevOps实践指南》- Gene Kim等