Deployment

生产环境部署

Tagtag Starter 生产环境部署指南,包括服务器配置、数据库优化和安全配置。

本文档详细介绍 Tagtag Starter 项目在生产环境的部署配置,包括服务器选型、后端部署、前端部署、数据库优化和安全配置等内容。

1. 服务器选型与配置

1.1 服务器架构

Tagtag Starter 采用前后端分离架构,生产环境建议使用以下服务器配置:

服务类型推荐配置数量用途
负载均衡4核8G1流量分发、SSL 终止
后端应用8核16G2+运行 Spring Boot 应用
前端应用4核8G2运行 Nginx 服务,部署静态资源
数据库16核32G1主1从运行 MySQL 数据库
Redis4核8G1主1从缓存、会话存储
监控4核8G1运行 Prometheus、Grafana 等监控工具

1.2 操作系统配置

建议使用 CentOS 7.9 或 Ubuntu 20.04 LTS 作为服务器操作系统。

系统优化建议

# 关闭不必要的服务
systemctl stop firewalld
systemctl disable firewalld
systemctl stop postfix
systemctl disable postfix

# 设置系统时区
timedatectl set-timezone Asia/Shanghai

# 关闭 SELinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0

# 优化文件描述符限制
cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
EOF

# 优化内核参数
cat >> /etc/sysctl.conf << EOF
# 网络优化
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.ip_local_port_range = 1024 65535

# 内存优化
vm.swappiness = 10
vm.overcommit_memory = 1
EOF

# 应用内核参数
sysctl -p

2. 后端部署

2.1 构建打包

步骤

  1. 克隆代码仓库
  2. 配置环境变量
  3. 构建 Maven 项目
  4. 生成 Docker 镜像(可选)

命令示例

# 克隆代码
git clone https://github.com/your-org/tagtag.git
cd tagtag

# 配置环境变量
export MAVEN_OPTS="-Xmx2g -Xms1g"

# 构建项目
mvn clean package -DskipTests

# 生成 Docker 镜像(可选)
docker build -t tagtag/backend:latest .

2.2 部署方式

2.2.1 传统部署

步骤

  1. 将构建好的 JAR 文件上传到服务器
  2. 创建启动脚本
  3. 配置 Systemd 服务
  4. 启动服务

示例

# 创建部署目录
mkdir -p /opt/tagtag/backend
cd /opt/tagtag/backend

# 上传 JAR 文件
scp target/tagtag-backend.jar root@server:/opt/tagtag/backend/

# 创建启动脚本
cat > start.sh << EOF
#!/bin/bash
java -jar -Xmx8g -Xms4g -Dspring.profiles.active=prod tagtag-backend.jar
EOF

chmod +x start.sh

# 配置 Systemd 服务
cat > /etc/systemd/system/tagtag-backend.service << EOF
[Unit]
Description=Tagtag Starter Backend Service
After=network.target

[Service]
User=root
WorkingDirectory=/opt/tagtag/backend
ExecStart=/opt/tagtag/backend/start.sh
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

# 启动服务
systemctl daemon-reload
systemctl start tagtag-backend
systemctl enable tagtag-backend

2.2.2 Docker 部署

步骤

  1. 安装 Docker
  2. 拉取或构建 Docker 镜像
  3. 创建 Docker Compose 文件
  4. 启动服务

Docker Compose 示例

version: '3.8'

services:
  tagtag-backend:
    image: tagtag/backend:latest
    container_name: tagtag-backend
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - DB_HOST=mysql
      - DB_PORT=3306
      - DB_USERNAME=root
      - DB_PASSWORD=password
      - REDIS_HOST=redis
      - REDIS_PORT=6379
    depends_on:
      - mysql
      - redis
    restart: always
    volumes:
      - ./logs:/opt/tagtag/logs

  mysql:
    image: mysql:8.0
    container_name: mysql
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=password
      - MYSQL_DATABASE=tagtag
    restart: always
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/conf:/etc/mysql/conf.d

  redis:
    image: redis:7.0
    container_name: redis
    ports:
      - "6379:6379"
    restart: always
    volumes:
      - ./redis/data:/data

2.3 配置文件管理

生产环境配置文件application-prod.yml

核心配置项

# 服务器配置
server:
  port: 8080
  servlet:
    context-path: /api
  tomcat:
    threads:
      max: 200
      min-spare: 10
    connection-timeout: 30000

# 数据库配置
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/tagtag?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: password
    hikari:
      maximum-pool-size: 50
      minimum-idle: 10
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

# Redis 配置
  redis:
    host: localhost
    port: 6379
    password: 
    database: 0
    timeout: 3000ms
    lettuce:
      pool:
        max-active: 100
        max-idle: 20
        min-idle: 5
        max-wait: -1ms

# JWT 配置
jwt:
  secret: your-secret-key
  expiration: 3600
  refresh-expiration: 86400

# 日志配置
logging:
  level:
    root: info
    com.tagtag: debug
  file:
    name: /opt/tagtag/logs/tagtag.log
    max-size: 100MB
    max-history: 30

3. 前端部署

3.1 构建打包

步骤

  1. 克隆代码仓库
  2. 安装依赖
  3. 构建生产版本
  4. 生成 Docker 镜像(可选)

命令示例

# 克隆代码
git clone https://github.com/your-org/tagtag.git
cd tagtag/tagtag-ui

# 安装依赖
pnpm install

# 构建生产版本
pnpm build

# 生成 Docker 镜像(可选)
docker build -t tagtag/frontend:latest .

3.2 Nginx 部署

步骤

  1. 安装 Nginx
  2. 配置 Nginx 虚拟主机
  3. 将构建好的静态文件复制到 Nginx 目录
  4. 启动 Nginx 服务

示例

# 安装 Nginx
yum install -y nginx

# 创建部署目录
mkdir -p /usr/share/nginx/html/tagtag

# 复制静态文件
cp -r dist/* /usr/share/nginx/html/tagtag/

# 配置 Nginx
cat > /etc/nginx/conf.d/tagtag.conf << EOF
server {
    listen 80;
    server_name tagtag.your-domain.com;
    
    # 静态资源配置
    location / {
        root /usr/share/nginx/html/tagtag;
        index index.html;
        try_files $uri $uri/ /index.html;
    }
    
    # API 代理配置
    location /api {
        proxy_pass http://backend-server:8080;
        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;
        
        # WebSocket 支持
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    
    # 日志配置
    access_log /var/log/nginx/tagtag.access.log main;
    error_log /var/log/nginx/tagtag.error.log error;
}
EOF

# 检查 Nginx 配置
nginx -t

# 重启 Nginx
systemctl restart nginx
systemctl enable nginx

3.3 SSL 配置

步骤

  1. 申请 SSL 证书(推荐使用 Let's Encrypt)
  2. 配置 Nginx SSL
  3. 强制 HTTPS 跳转

示例

# 安装 Certbot
yum install -y epel-release
yum install -y certbot python3-certbot-nginx

# 申请 SSL 证书
certbot --nginx -d tagtag.your-domain.com

# 自动续约
echo "0 3 * * * certbot renew --quiet" >> /var/spool/cron/root

Nginx SSL 配置

server {
    listen 443 ssl http2;
    server_name tagtag.your-domain.com;
    
    # SSL 配置
    ssl_certificate /etc/letsencrypt/live/tagtag.your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/tagtag.your-domain.com/privkey.pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:MozSSL:10m;
    ssl_session_tickets off;
    
    # TLS 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    
    # HSTS 配置
    add_header Strict-Transport-Security "max-age=63072000" always;
    
    # 其他配置...
}

# 强制 HTTPS 跳转
server {
    listen 80;
    server_name tagtag.your-domain.com;
    return 301 https://$server_name$request_uri;
}

4. 数据库优化

4.1 MySQL 配置优化

核心配置项

# /etc/my.cnf

[mysqld]
# 基础配置
user = mysql
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
pid-file = /var/run/mysqld/mysqld.pid

# 字符集配置
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4'

# 内存配置
innodb_buffer_pool_size = 20G  # 建议为服务器内存的 50%-70%
innodb_log_buffer_size = 128M
key_buffer_size = 256M
query_cache_size = 0
query_cache_type = 0

# 连接配置
max_connections = 2000
max_connect_errors = 10000
wait_timeout = 600
interactive_timeout = 600

# InnoDB 配置
innodb_file_per_table = 1
innodb_flush_log_at_trx_commit = 2  # 生产环境建议设置为 2
innodb_log_file_size = 2G
innodb_log_files_in_group = 2
innodb_io_capacity = 4000
innodb_io_capacity_max = 8000
innodb_doublewrite = 1
innodb_thread_concurrency = 0

# 日志配置
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/slow.log
long_query_time = 2
log_queries_not_using_indexes = 0

# 其他配置
skip-name-resolve
lower_case_table_names = 1

4.2 索引优化

索引设计原则

  • 为经常查询的字段创建索引
  • 为 JOIN 条件字段创建索引
  • 为 ORDER BY 和 GROUP BY 字段创建索引
  • 避免创建过多索引
  • 使用复合索引时,将最常用的字段放在前面
  • 定期优化表和重建索引

示例

-- 创建复合索引
CREATE INDEX idx_user_name_email ON sys_user(username, email);

-- 重建索引
ALTER TABLE sys_user ENGINE=InnoDB;

-- 分析表
ANALYZE TABLE sys_user;

4.3 查询优化

优化建议

  • 使用 EXPLAIN 分析查询计划
  • 避免 SELECT *,只查询需要的字段
  • 避免在 WHERE 子句中使用函数
  • 避免在 WHERE 子句中对字段进行运算
  • 使用 LIMIT 限制返回结果数量
  • 合理使用 JOIN,避免笛卡尔积

示例

-- 不好的查询
SELECT * FROM sys_user WHERE DATE(create_time) = '2023-01-01';

-- 优化后的查询
SELECT id, username, email FROM sys_user WHERE create_time BETWEEN '2023-01-01 00:00:00' AND '2023-01-01 23:59:59';

4.4 分库分表

当数据量达到一定规模时,建议考虑分库分表:

  • 水平分表:将同一张表的数据按照一定规则分散到多个表中
  • 垂直分表:将一张表的字段按照访问频率和大小分散到多个表中
  • 分库:将不同业务的数据分散到不同的数据库中

分表策略

  • 按时间分表(如按月份)
  • 按 ID 分表(如哈希分表)
  • 按业务字段分表(如按用户 ID)

5. Redis 优化

5.1 配置优化

核心配置项

# /etc/redis.conf

# 基础配置
bind 0.0.0.0
protected-mode yes
port 6379
daemonize yes
pidfile /var/run/redis_6379.pid
logfile /var/log/redis/redis.log

# 内存配置
maxmemory 6G  # 建议为服务器内存的 50%-70%
maxmemory-policy allkeys-lru  # 内存不足时的淘汰策略

# 持久化配置
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
dir /var/lib/redis
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec  # 生产环境建议设置为 everysec

# 连接配置
timeout 300
maxclients 10000

# 其他配置
tcp-keepalive 300

5.2 缓存优化

优化建议

  • 设置合理的缓存过期时间
  • 避免缓存雪崩、缓存击穿和缓存穿透
  • 使用缓存预热
  • 定期清理过期缓存
  • 合理使用 Redis 数据结构

缓存雪崩解决方案

  • 设置随机过期时间
  • 使用 Redis 集群
  • 实现缓存降级

缓存穿透解决方案

  • 使用布隆过滤器
  • 缓存空值
  • 限流和熔断

6. 安全配置

6.1 网络安全

  • 使用防火墙限制访问端口
  • 配置 VPN 或专线连接
  • 使用 SSL/TLS 加密传输
  • 定期进行安全扫描
  • 配置入侵检测系统(IDS)

6.2 服务器安全

  • 定期更新系统和软件包
  • 使用强密码和密钥认证
  • 禁用 root 远程登录
  • 配置 sudo 权限
  • 启用日志审计
  • 定期备份服务器配置

6.3 应用安全

  • 实现细粒度的权限控制
  • 对敏感数据进行加密存储
  • 防止 SQL 注入
  • 防止 XSS 攻击
  • 防止 CSRF 攻击
  • 实现 API 限流和熔断
  • 定期进行代码审计

6.4 数据安全

  • 定期备份数据库
  • 实现数据加密
  • 配置访问控制列表(ACL)
  • 数据脱敏处理
  • 实现数据恢复机制
  • 定期进行数据完整性检查

7. 监控与日志

7.1 监控系统

推荐使用 Prometheus + Grafana 搭建监控系统:

  • Prometheus:收集监控数据
  • Grafana:可视化监控数据
  • Node Exporter:监控服务器指标
  • JMX Exporter:监控 Java 应用
  • MySQL Exporter:监控 MySQL 数据库
  • Redis Exporter:监控 Redis

7.2 日志管理

  • ELK Stack:Elasticsearch + Logstash + Kibana
  • Loki:轻量级日志聚合系统
  • Filebeat:日志采集器

日志配置建议

  • 统一日志格式
  • 包含必要的上下文信息
  • 实现日志分级
  • 定期清理过期日志
  • 配置日志告警

8. 备份与恢复

8.1 数据库备份

全量备份

# 使用 mysqldump 进行全量备份
mysqldump -u root -p --all-databases --single-transaction --routines --triggers --events > /backup/mysql/full_backup_$(date +%Y%m%d_%H%M%S).sql

# 使用 xtrabackup 进行全量备份
xtrabackup --backup --target-dir=/backup/mysql/full_backup_$(date +%Y%m%d_%H%M%S)

增量备份

# 使用 xtrabackup 进行增量备份
xtrabackup --backup --target-dir=/backup/mysql/incremental_$(date +%Y%m%d_%H%M%S) --incremental-basedir=/backup/mysql/full_backup_20230101_000000

定时备份脚本

cat > /usr/local/bin/mysql_backup.sh << EOF
#!/bin/bash

BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
FULL_BACKUP_DIR="$BACKUP_DIR/full_$DATE"

# 创建备份目录
mkdir -p $FULL_BACKUP_DIR

# 执行全量备份
mysqldump -u root -p"password" --all-databases --single-transaction --routines --triggers --events > $FULL_BACKUP_DIR/full_backup.sql

# 压缩备份文件
tar -czf $BACKUP_DIR/full_backup_$DATE.tar.gz -C $BACKUP_DIR full_$DATE

# 删除临时目录
rm -rf $FULL_BACKUP_DIR

# 删除 7 天前的备份
find $BACKUP_DIR -name "full_backup_*.tar.gz" -mtime +7 -delete
EOF

# 添加到定时任务
chmod +x /usr/local/bin/mysql_backup.sh
echo "0 2 * * * /usr/local/bin/mysql_backup.sh" >> /var/spool/cron/root

8.2 应用备份

示例

# 备份应用配置和数据
BACKUP_DIR="/backup/app"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR/$DATE

# 备份配置文件
cp -r /opt/tagtag/backend/config $BACKUP_DIR/$DATE/

# 备份日志(可选)
cp -r /opt/tagtag/backend/logs $BACKUP_DIR/$DATE/

# 备份静态资源
cp -r /usr/share/nginx/html/tagtag $BACKUP_DIR/$DATE/

# 压缩备份文件
tar -czf $BACKUP_DIR/app_backup_$DATE.tar.gz -C $BACKUP_DIR $DATE

# 删除临时目录
rm -rf $BACKUP_DIR/$DATE

# 删除 7 天前的备份
find $BACKUP_DIR -name "app_backup_*.tar.gz" -mtime +7 -delete

9. 性能测试

9.1 负载测试工具

  • JMeter:功能强大的负载测试工具
  • Gatling:基于 Scala 的高性能负载测试工具
  • k6:现代化的负载测试工具
  • Apache Benchmark (ab):简单易用的 HTTP 负载测试工具

9.2 测试场景

  • 并发测试:测试系统在不同并发数下的性能
  • 压力测试:测试系统的极限性能
  • 稳定性测试:长时间运行测试,检查系统稳定性
  • 容量测试:测试系统的最大容量

JMeter 测试示例

  1. 创建测试计划
  2. 添加线程组
  3. 添加 HTTP 请求
  4. 添加监听器(如聚合报告、图表结果)
  5. 运行测试
  6. 分析结果

10. 常见问题与解决方案

10.1 应用启动失败

问题:应用启动后立即退出

解决方案

# 查看日志
cat /opt/tagtag/backend/logs/application.log

# 检查端口占用
netstat -tlnp | grep 8080

# 检查数据库连接
telnet mysql-server 3306

# 检查 Redis 连接
telnet redis-server 6379

10.2 数据库连接失败

问题:应用无法连接到数据库

解决方案

# 检查数据库服务状态
systemctl status mysqld

# 检查数据库用户权限
mysql -u root -p -e "SHOW GRANTS FOR 'tagtag'@'%';"

# 检查防火墙设置
firewall-cmd --list-ports

# 检查 SELinux 设置
getenforce

10.3 前端页面无法访问

问题:访问前端页面显示 404 或空白页

解决方案

# 检查 Nginx 配置
nginx -t

# 检查 Nginx 日志
cat /var/log/nginx/tagtag.error.log

# 检查静态文件权限
ls -la /usr/share/nginx/html/tagtag/

# 检查前端路由配置
# 确保 Nginx 配置了 try_files $uri $uri/ /index.html;

11. 总结

生产环境部署是一个复杂的过程,需要考虑服务器配置、应用部署、数据库优化、安全配置、监控日志和备份恢复等多个方面。本文档提供了 Tagtag Starter 项目在生产环境部署的详细指南,希望能帮助您顺利完成部署工作。

在实际部署过程中,建议根据您的业务需求和服务器资源情况,灵活调整配置参数,确保系统的高性能、高可用性和高安全性。