云服务器部署指南

一、云服务器环境准备

1.1 服务器选择

选择云服务器就像是给项目选房子,要考虑预算、位置、周边配套等多种因素。我总结出几家主流厂商的对比:

服务商 适用场景 优势 劣势 价格区间(2核4G) 官网地址
阿里云ECS 国内主流业务 国内访问速度最快,BGP线路覆盖全面,技术支持响应及时,中文服务完善,DDoS防护免费 价格相对较高,国际带宽成本贵,某些高级功能需要额外付费 150-200元/月 https://www.aliyun.com/product/ecs
腾讯云CVM 预算有限项目 性价比极高,经常有优惠活动,新用户享受大额代金券,微信小程序/公众号集成便捷 高并发性能略逊于阿里云,某些区域网络稳定性一般 120-160元/月 https://cloud.tencent.com/product/cvm
AWS EC2 国际化业务 全球覆盖最广,服务生态最完善,按秒计费成本控制精确,自动化运维工具丰富 国内访问速度较慢需要备案,界面全英文学习成本高,支付和客服支持复杂 $15-25/月 https://aws.amazon.com/ec2/
华为云ECS 政企项目 企业级安全性高,国产化程度高,政企项目首选合规性强,硬件配置稳定性能可靠 价格偏高个人用户不友好,文档和社区相对较少,某些配置灵活性不足 160-220元/月 https://www.huaweicloud.com/product/ecs.html

实际选择时,建议根据项目性质来决定:如果是面向国内用户的首选阿里云,预算有限可以考虑腾讯云的优惠活动,有海外业务需求那AWS是绕不开的选择,政府或企业项目华为云会更合适一些。价格方面,经常关注各家的活动,有时候能拿到很好的折扣。

1.2 基础环境配置

系统更新 - 必须执行的第一步

系统安全是服务器运维的基础,第一时间更新系统可以修复已知的安全漏洞,这是最基本的防护措施。内核补丁不仅能提升系统稳定性,还能优化性能。更新软件包仓库则能确保后续安装的软件都是最新版本,避免使用有漏洞的旧版本。

执行方法:

# Ubuntu/Debian系统
sudo apt update && sudo apt upgrade -y

# CentOS/RHEL系统  
sudo yum update -y

# 查看系统版本
lsb_release -a  # Ubuntu
cat /etc/redhat-release  # CentOS
基础开发工具安装 - 项目部署的必备组件

部署过程中这些工具都是必备的。wget和curl用于下载各种软件包和脚本,git用于从代码仓库拉取项目代码,vim或nano则是服务器上的文本编辑器。nginx作为反向代理服务器,处理HTTP请求和静态文件服务是标配。htop能帮你快速查看系统资源占用情况,unzip和tar处理各种压缩文件。虽然看起来工具不少,但这些都是运维过程中经常用到的。

安装命令:

# Ubuntu/Debian
sudo apt install -y wget curl git vim nginx htop unzip tar build-essential

# CentOS/RHEL
sudo yum install -y wget curl git vim nginx htop unzip tar gcc gcc-c++ make
时区和时间同步 - 确保日志时间准确

时间同步虽然看起来是个小事,但在生产环境中特别重要。统一的时间戳能让你在排查问题时快速定位事件发生的时间,不会因为时间不一致而误判。定时任务比如备份、日志清理等都依赖准确的时间。还有SSL证书验证对时间很敏感,时间不正确可能导致证书验证失败,直接影响HTTPS访问。

配置方法:

# 设置时区为东八区
sudo timedatectl set-timezone Asia/Shanghai

# 启用NTP时间同步
sudo timedatectl set-ntp yes

# 查看时间状态
timedatectl status
防火墙基础配置 - 服务器安全第一道防线

防火墙就像是服务器的门卫,只允许必要的流量通过。默认情况下应该关闭所有端口,然后只开放SSH(22端口)、HTTP(80端口)和HTTPS(443端口)这几个必需的端口。这样能有效防止端口扫描和恶意攻击,大大降低服务器被入侵的风险。记住,安全策略应该是默认拒绝,明确允许。

配置步骤:

# 启用UFW防火墙
sudo ufw enable

# 允许SSH连接(重要:否则会被锁在服务器外)
sudo ufw allow ssh

# 允许HTTP和HTTPS
sudo ufw allow 80
sudo ufw allow 443

# 查看防火墙状态
sudo ufw status verbose
SSH安全配置 - 远程管理安全加固

SSH是服务器管理的生命线,也是黑客攻击的重点目标。暴力破解SSH密码是最常见的攻击方式之一,一定要禁用密码认证改用密钥认证。root账号权限太大,被攻破后果严重,建议禁用直接登录,日常操作使用普通用户。密钥认证不仅安全性更高,还便于自动化部署脚本的执行。

配置方法:

# 编辑SSH配置文件
sudo vim /etc/ssh/sshd_config

# 修改以下配置项:
Port 22                    # 可以改为其他端口
PermitRootLogin no         # 禁止root登录
PasswordAuthentication no  # 禁用密码认证
PubkeyAuthentication yes   # 启用密钥认证
UsePAM no                 # 禁用PAM认证

# 重启SSH服务
sudo systemctl restart sshd

1.3 安全配置

创建专用部署用户 - 权限分离最佳实践

千万不要图省事直接用root用户操作服务器,这是很多新手的坏习惯。创建专门的部署用户可以避免误操作造成系统级损坏,比如不小心rm掉了重要系统文件。应用和系统权限分离后,即使应用被攻破,攻击者也只能拿到有限权限,无法控制系统。这样还便于日志审计和责任追踪。

操作步骤:

# 创建部署用户
sudo useradd -m -s /bin/bash deploy

# 设置用户密码
sudo passwd deploy

# 将用户添加到sudo组
sudo usermod -aG sudo deploy

# 创建.ssh目录
sudo mkdir -p /home/deploy/.ssh
sudo chmod 700 /home/deploy/.ssh
sudo chown deploy:deploy /home/deploy/.ssh
SSH密钥认证配置 - 替代密码认证

SSH密钥认证比密码安全太多了,密码再复杂也可能被暴力破解,但密钥几乎不可能被破解。配置一次后就不用每次输入密码,登录更方便也支持自动化脚本执行。现在的CI/CD流水线、自动化部署工具都依赖SSH密钥认证,这是现代DevOps实践的基础。

配置方法:

# 在本地机器生成SSH密钥对
ssh-keygen -t rsa -b 4096 -C "your-email@example.com"

# 将公钥复制到服务器
ssh-copy-id deploy@your-server-ip

# 或者手动复制
cat ~/.ssh/id_rsa.pub | ssh deploy@your-server-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# 设置权限
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
fail2ban入侵防护 - 自动封禁恶意IP

fail2ban就像一个自动化的保安,能实时监控SSH登录日志,发现暴力破解行为就自动封禁IP。现在的网络环境很复杂,各种扫描器和僵尸程序24小时不间断地尝试攻击服务器,人工防护根本忙不过来。配置fail2ban后,大部分低水平的攻击都会被自动处理,大大减轻服务器的安全压力。

安装配置:

# 安装fail2ban
sudo apt install fail2ban -y

# 创建本地配置文件
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

# 编辑配置
sudo vim /etc/fail2ban/jail.local
[DEFAULT]
bantime = 3600
findtime = 600
maxretry = 3

[sshd]
enabled = true
port = ssh
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
# 启动fail2ban服务
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
sudo systemctl status fail2ban

# 查看封禁状态
sudo fail2ban-client status sshd
系统安全加固 - 内核参数优化

Linux内核参数优化能从系统层面提升安全性和性能。开启SYN cookies等防护参数可以有效防止SYN洪水攻击,关闭IP转发功能防止IP欺骗。调整网络相关参数能提升并发连接处理能力,这对于高并发应用特别重要。还要记得关闭不需要的系统服务,每个运行的服务都是潜在的安全风险点。

配置方法:

# 编辑系统参数
sudo vim /etc/sysctl.conf
# IP安全配置
net.ipv4.ip_forward = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.icmp_echo_ignore_broadcasts = 1

# 防止SYN洪水攻击
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2

# 文件描述符限制
fs.file-max = 65535
# 应用配置
sudo sysctl -p
日志监控配置 - 及时发现异常

日志监控就像是服务器的健康监测系统,能帮你及时发现问题。实时监控登录日志可以发现异常登录行为,比如有人在半夜尝试登录或者短时间内大量失败尝试。定期检查系统资源使用情况能发现性能瓶颈或异常进程。很多安全事件在发生前都会有预兆,通过日志分析能提前预警,避免问题扩大化。

配置方法:

# 查看登录日志
sudo tail -f /var/log/auth.log

# 安装logwatch进行日志分析
sudo apt install logwatch -y

# 配置logwatch
sudo vim /etc/logwatch/conf/logwatch.conf
# 发送日志到邮箱
MailTo = your-email@example.com
Range = yesterday
Detail = Med

二、Java项目部署

2.1 Java环境安装

# 安装OpenJDK 11
sudo apt install openjdk-11-jdk -y

# 验证安装
java -version
javac -version

# 设置JAVA_HOME
echo 'export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64' >> ~/.bashrc
source ~/.bashrc

2.2 数据库配置

MySQL安装配置 - 关系型数据库首选

MySQL是Java项目的老搭档了,性能稳定、配置简单,文档和社区资源都很丰富。它的读写性能在大多数场景下都够用,特别是配合Java Spring框架使用时,集成度非常高。主从复制配置也相对简单,适合中小型项目的读写分离需求。虽然PostgreSQL在某些高级功能上更强大,但MySQL的简单性和稳定性让它在实际项目中更受欢迎。

安装步骤:

# 安装MySQL服务器
sudo apt install mysql-server -y

# 安全配置向导
sudo mysql_secure_installation

# 启动并设置开机自启
sudo systemctl enable mysql
sudo systemctl start mysql

# 登录MySQL
sudo mysql -u root -p

创建数据库和用户:

-- 创建应用数据库
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 创建应用用户
CREATE USER 'appuser'@'localhost' IDENTIFIED BY 'StrongPassword123!';

-- 授权
GRANT ALL PRIVILEGES ON myapp.* TO 'appuser'@'localhost';

-- 刷新权限
FLUSH PRIVILEGES;

-- 退出
EXIT;

MySQL性能优化配置:

# 编辑MySQL配置文件
sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
# 基础配置
bind-address = 127.0.0.1
port = 3306

# 内存配置
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2

# 连接配置
max_connections = 200
max_connect_errors = 1000

# 查询缓存
query_cache_type = 1
query_cache_size = 64M
PostgreSQL安装配置 - 高级功能数据库

PostgreSQL可以说是最强大的开源关系型数据库了。它的JSON支持非常完善,对于现代应用很有用。事务处理能力很强,ACID特性完整,适合金融等对数据一致性要求极高的场景。PostgreSQL的扩展性也很强,可以自定义函数和数据类型。虽然是开源免费,但功能不输任何商业数据库,特别适合Django项目,因为Django对PostgreSQL的原生支持很好。

安装步骤:

# 安装PostgreSQL
sudo apt install postgresql postgresql-contrib -y

# 启动服务
sudo systemctl enable postgresql
sudo systemctl start postgresql

# 切换到postgres用户
sudo -u postgres psql

创建数据库和用户:

-- 创建应用用户
CREATE USER django_user WITH PASSWORD 'StrongPassword123!';

-- 创建数据库
CREATE DATABASE mydjangoapp OWNER django_user;

-- 授权
GRANT ALL PRIVILEGES ON DATABASE mydjangoapp TO django_user;

-- 退出
\q

PostgreSQL配置优化:

# 编辑主配置文件
sudo vim /etc/postgresql/12/main/postgresql.conf
# 连接配置
listen_addresses = 'localhost'
port = 5432
max_connections = 100

# 内存配置
shared_buffers = 256MB
effective_cache_size = 1GB
work_mem = 4MB
maintenance_work_mem = 64MB

# WAL配置
wal_buffers = 16MB
checkpoint_completion_target = 0.9
# 编辑访问控制文件
sudo vim /etc/postgresql/12/main/pg_hba.conf
# 添加本地连接规则
local   all             postgres                                peer
local   all             all                                     md5
host    all             all             127.0.0.1/32            md5
数据库备份策略 - 数据安全保障

MySQL备份脚本:

#!/bin/bash
# mysql_backup.sh

BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="myapp"
DB_USER="appuser"

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

# 执行备份
mysqldump -u $DB_USER -p$DB_PASS $DB_NAME > $BACKUP_DIR/backup_$DATE.sql

# 压缩备份文件
gzip $BACKUP_DIR/backup_$DATE.sql

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

PostgreSQL备份脚本:

#!/bin/bash
# pg_backup.sh

BACKUP_DIR="/backup/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydjangoapp"

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

# 执行备份
pg_dump -U postgres $DB_NAME > $BACKUP_DIR/pg_backup_$DATE.sql

# 压缩备份文件
gzip $BACKUP_DIR/pg_backup_$DATE.sql

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

2.3 项目部署步骤

打包工具选择和安装 - 构建自动化工具

Maven - Java项目标准构建工具

Maven是Java项目的老牌构建工具了。最大的好处是依赖管理自动化,再也不用手动下载和管理jar包,也不用担心版本冲突问题。它的项目结构是标准化的,团队成员之间协作很方便。插件生态非常丰富,从编译、测试到打包部署,几乎每个环节都有对应的插件。在CI/CD流水线中集成也很简单,是大多数Java项目的首选。

安装配置:

# 下载Maven
cd /opt
sudo wget https://archive.apache.org/dist/maven/maven-3/3.8.6/binaries/apache-maven-3.8.6-bin.tar.gz

# 解压
sudo tar -xzf apache-maven-3.8.6-bin.tar.gz
sudo mv apache-maven-3.8.6 maven

# 配置环境变量
echo 'export M2_HOME=/opt/maven' >> ~/.bashrc
echo 'export PATH=$M2_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# 验证安装
mvn -version

Maven打包命令:

# 清理并打包
mvn clean package

# 跳过测试打包(生产环境不推荐)
mvn clean package -DskipTests

# 打包并安装到本地仓库
mvn clean install

# 多环境打包
mvn clean package -P prod

Gradle - 现代化构建工具

Gradle是新一代的构建工具,比Maven更灵活。它使用Groovy或Kotlin DSL,配置代码更加简洁易懂。增量构建机制让它在日常开发中构建速度更快,只编译变化的部分。除了Java,还支持Kotlin、Groovy等多种语言,特别适合Android开发。虽然学习曲线比Maven陡峭一些,但一旦上手就会发现它的强大和灵活。

安装配置:

# 下载Gradle
cd /opt
sudo wget https://services.gradle.org/distributions/gradle-7.5.1-bin.zip

# 解压
sudo unzip gradle-7.5.1-bin.zip
sudo mv gradle-7.5.1 gradle

# 配置环境变量
echo 'export GRADLE_HOME=/opt/gradle' >> ~/.bashrc
echo 'export PATH=$GRADLE_HOME/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

# 验证安装
gradle -version

Gradle打包命令:

# 构建项目
./gradlew build

# 跳过测试
./gradlew build -x test

# 打包发布版本
./gradlew clean assembleRelease

# 查看依赖树
./gradlew dependencies
项目上传工具 - 文件传输解决方案

SCP - 安全复制协议

SCP是基于SSH的安全传输协议,传输过程全程加密,安全性很高。命令语法很简单,很容易集成到自动化脚本中。而且几乎所有Linux系统都自带,不需要额外安装什么。对于简单的文件上传下载,SCP是最直接的选择,特别是在脚本化部署时用起来很顺手。

使用方法:

# 上传单个文件
scp target/myapp.jar deploy@your-server:/home/deploy/

# 上传整个目录
scp -r target/ deploy@your-server:/home/deploy/

# 指定端口
scp -P 2222 target/myapp.jar deploy@your-server:/home/deploy/

Rsync - 高效同步工具

Rsync是我最喜欢的同步工具,它只传输变化的文件部分,大大节省带宽和时间。网络中断后可以断点续传,不会传输一半重来一次。最重要的是它能保持文件的权限、时间戳等属性,和本地完全一致。对于项目代码同步和备份,Rsync是最佳选择,特别是项目文件较大时,优势特别明显。

安装和使用:

# 安装rsync
sudo apt install rsync -y

# 同步文件
rsync -avz --progress target/ deploy@your-server:/home/deploy/

# 删除目标目录多余文件
rsync -avz --delete target/ deploy@your-server:/home/deploy/

# 排除某些文件
rsync -avz --exclude '*.log' --exclude 'tmp/' target/ deploy@your-server:/home/deploy/

SFTP - 安全文件传输协议

SFTP提供了交互式的文件操作界面,可以像操作本地文件一样管理远程服务器。支持目录的创建、删除、重命名等操作,比SCP功能更丰富。它使用标准的SSH端口,一般不会被防火墙拦截。当你需要手动管理服务器文件或者查看远程目录结构时,SFTP是最方便的选择。

使用方法:

# 连接SFTP
sftp deploy@your-server

# SFTP命令
sftp> put target/myapp.jar /home/deploy/
sftp> get /home/deploy/app.log
sftp> mkdir /home/deploy/logs
sftp> ls -la
sftp> exit
启动脚本配置 - 应用生命周期管理

基础启动脚本

#!/bin/bash
# start.sh

# 设置环境变量
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
export PATH=$JAVA_HOME/bin:$PATH

# 应用配置
APP_NAME="myapp"
JAR_FILE="/home/deploy/myapp.jar"
PID_FILE="/home/deploy/myapp.pid"
LOG_FILE="/home/deploy/logs/myapp.log"

# 创建日志目录
mkdir -p /home/deploy/logs

# JVM参数配置
JVM_OPTS="-Xms512m -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
SPRING_OPTS="--spring.profiles.active=prod --server.port=8080"

# 启动应用
start() {
    if [ -f $PID_FILE ]; then
        echo "Application is already running with PID $(cat $PID_FILE)"
        return 1
    fi
    
    echo "Starting $APP_NAME..."
    nohup java $JVM_OPTS -jar $JAR_FILE $SPRING_OPTS > $LOG_FILE 2>&1 &
    echo $! > $PID_FILE
    echo "Application started with PID $(cat $PID_FILE)"
}

# 停止应用
stop() {
    if [ ! -f $PID_FILE ]; then
        echo "Application is not running"
        return 1
    fi
    
    PID=$(cat $PID_FILE)
    echo "Stopping $APP_NAME with PID $PID..."
    kill $PID
    rm -f $PID_FILE
    echo "Application stopped"
}

# 重启应用
restart() {
    stop
    sleep 2
    start
}

# 查看状态
status() {
    if [ -f $PID_FILE ]; then
        PID=$(cat $PID_FILE)
        if ps -p $PID > /dev/null 2>&1; then
            echo "Application is running with PID $PID"
        else
            echo "PID file exists but process is not running"
            rm -f $PID_FILE
        fi
    else
        echo "Application is not running"
    fi
}

# 主逻辑
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    status)
        status
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

高级启动脚本(带健康检查)

#!/bin/bash
# advanced_start.sh

APP_NAME="myapp"
JAR_FILE="/home/deploy/myapp.jar"
PORT=8080
HEALTH_CHECK_URL="http://localhost:$PORT/actuator/health"
MAX_RETRIES=30
RETRY_INTERVAL=5

# 健康检查函数
health_check() {
    local retries=0
    echo "Performing health check..."
    
    while [ $retries -lt $MAX_RETRIES ]; do
        if curl -f -s $HEALTH_CHECK_URL > /dev/null 2>&1; then
            echo "Application is healthy ✓"
            return 0
        fi
        
        echo "Health check failed, retrying in $RETRY_INTERVAL seconds... ($((retries+1))/$MAX_RETRIES)"
        sleep $RETRY_INTERVAL
        ((retries++))
    done
    
    echo "Health check failed after $MAX_RETRIES retries"
    return 1
}

# 启动应用并等待健康检查
start_with_health_check() {
    echo "Starting $APP_NAME with health check..."
    ./start.sh start
    
    echo "Waiting for application to be ready..."
    sleep 10
    
    if health_check; then
        echo "$APP_NAME started successfully ✓"
        return 0
    else
        echo "Failed to start $APP_NAME, rolling back..."
        ./start.sh stop
        return 1
    fi
}

# 执行带健康检查的启动
start_with_health_check

配置文件权限

# 设置执行权限
chmod +x start.sh advanced_start.sh

# 设置文件所有者
chown deploy:deploy *.sh

# 测试脚本
./start.sh status

2.4 进程管理(使用systemd)

# 创建服务文件
sudo vim /etc/systemd/system/myapp.service
[Unit]
Description=My Java Application
After=network.target

[Service]
Type=simple
User=deploy
WorkingDirectory=/home/deploy
ExecStart=/usr/bin/java -jar /home/deploy/myapp.jar
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
# 启用并启动服务
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp

2.5 反向代理配置(Nginx)

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://localhost: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;
    }
}

三、Django项目部署

3.1 Python环境配置

# 安装Python和pip
sudo apt install python3 python3-pip python3-venv -y

# 创建虚拟环境
python3 -m venv /home/deploy/myenv
source /home/deploy/myenv/bin/activate

# 安装依赖
pip install -r requirements.txt

3.2 数据库配置

# PostgreSQL安装
sudo apt install postgresql postgresql-contrib -y

# 创建数据库和用户
sudo -u postgres psql
CREATE DATABASE mydjangoapp;
CREATE USER django_user WITH PASSWORD 'password';
ALTER ROLE django_user SET client_encoding TO 'utf8';
GRANT ALL PRIVILEGES ON DATABASE mydjangoapp TO django_user;
\q

3.3 Django项目配置

settings.py生产环境配置
import os

# 安全设置
DEBUG = False
ALLOWED_HOSTS = ['your-domain.com', 'your-server-ip']

# 数据库配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydjangoapp',
        'USER': 'django_user',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

# 静态文件配置
STATIC_ROOT = '/var/www/django/static/'
MEDIA_ROOT = '/var/www/django/media/'
数据库迁移和静态文件收集
# 数据库迁移
python manage.py makemigrations
python manage.py migrate

# 收集静态文件
python manage.py collectstatic --noinput

# 创建超级用户
python manage.py createsuperuser

3.4 Gunicorn配置

# 安装Gunicorn
pip install gunicorn

# 创建Gunicorn配置文件
cat > gunicorn.conf.py << EOF
bind = "127.0.0.1:8000"
workers = 4
worker_class = "sync"
worker_connections = 1000
timeout = 30
keepalive = 2
max_requests = 1000
max_requests_jitter = 100
preload_app = True
EOF
测试Gunicorn运行
gunicorn --config gunicorn.conf.py myproject.wsgi:application

3.5 Systemd服务配置

# 创建Django服务文件
sudo vim /etc/systemd/system/django.service
[Unit]
Description=Django Gunicorn Service
After=network.target

[Service]
Type=notify
User=deploy
Group=deploy
WorkingDirectory=/home/deploy/myproject
Environment=PATH=/home/deploy/myenv/bin
ExecStart=/home/deploy/myenv/bin/gunicorn --config gunicorn.conf.py myproject.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
# 启用并启动服务
sudo systemctl enable django
sudo systemctl start django
sudo systemctl status django

3.6 Nginx配置

server {
    listen 80;
    server_name your-domain.com;

    location /static/ {
        alias /var/www/django/static/;
        expires 30d;
    }

    location /media/ {
        alias /var/www/django/media/;
        expires 30d;
    }

    location / {
        proxy_pass http://127.0.0.1:8000;
        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;
    }
}

四、额外配置

4.1 SSL证书配置 - HTTPS安全访问保障

SSL证书现在已经不是可选项,而是现代网站的标配。通过HTTPS加密可以有效防止数据在传输过程中被窃取或篡改,这对于用户登录、支付等敏感操作至关重要。浏览器会为HTTPS网站显示安全锁标,这直接影响用户对网站的信任度。从SEO角度来看,搜索引擎明确表示偏好HTTPS站点,采用HTTPS能获得更好的排名。另外,现在很多第三方服务(如支付接口、地图API等)都要求使用HTTPS,这是技术发展的必然趋势。

Let’s Encrypt免费证书配置:

# 安装Certbot
sudo apt install certbot python3-certbot-nginx -y

# 自动配置Nginx
sudo certbot --nginx -d your-domain.com -d www.your-domain.com

# 手动配置(选择此选项)
sudo certbot certonly --nginx -d your-domain.com

# 强制HTTPS重定向
sudo vim /etc/nginx/sites-available/your-domain
server {
    listen 80;
    server_name your-domain.com www.your-domain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    server_name your-domain.com www.your-domain.com;

    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
    
    # SSL配置优化
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    location / {
        proxy_pass http://localhost: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;
    }
}

自动续期配置:

# 测试续期
sudo certbot renew --dry-run

# 设置自动续期(系统自带)
sudo systemctl status certbot.timer

# 手动添加cron任务
sudo crontab -e
# 添加:0 12 * * * /usr/bin/certbot renew --quiet

4.2 监控和日志系统 - 运维可视化管理

系统服务监控

# 查看所有服务状态
sudo systemctl list-units --type=service --state=running

# 查看特定服务日志
sudo journalctl -u myapp -f
sudo journalctl -u nginx -f
sudo journalctl -u mysql -f

# 查看系统资源使用
htop
df -h
free -h
netstat -tulpn

应用日志配置

# 创建日志目录结构
mkdir -p /home/deploy/logs/{app,nginx,system}

# 配置日志轮转
sudo vim /etc/logrotate.d/myapp
/home/deploy/logs/app/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    create 644 deploy deploy
    postrotate
        systemctl reload myapp
    endscript
}

Prometheus + Grafana监控搭建

# 安装Prometheus
wget https://github.com/prometheus/prometheus/releases/download/v2.36.2/prometheus-2.36.2.linux-amd64.tar.gz
tar -xzf prometheus-2.36.2.linux-amd64.tar.gz
cd prometheus-2.36.2.linux-amd64

# 配置prometheus.yml
cat > prometheus.yml << EOF
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'myapp'
    static_configs:
      - targets: ['localhost:8080']
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']
EOF

# 启动Prometheus
./prometheus --config.file=prometheus.yml --web.listen-address=:9090

4.3 自动化部署流程 - CI/CD最佳实践

Git自动化部署脚本

#!/bin/bash
# auto_deploy.sh

set -e  # 遇到错误立即退出

# 配置变量
PROJECT_DIR="/home/deploy/myproject"
BACKUP_DIR="/backup/deploy"
LOG_FILE="/var/log/deploy.log"
DATE=$(date +%Y%m%d_%H%M%S)

# 日志函数
log() {
    echo "[$DATE] $1" | tee -a $LOG_FILE
}

# 错误处理
error_exit() {
    log "ERROR: $1"
    exit 1
}

# 创建备份
create_backup() {
    log "Creating backup..."
    mkdir -p $BACKUP_DIR
    cp -r $PROJECT_DIR $BACKUP_DIR/project_$DATE
    log "Backup created at $BACKUP_DIR/project_$DATE"
}

# 更新代码
update_code() {
    log "Updating code from git repository..."
    cd $PROJECT_DIR
    git pull origin main || error_exit "Git pull failed"
    log "Code updated successfully"
}

# Java项目部署
deploy_java() {
    log "Starting Java application deployment..."
    
    # 检查Maven
    if ! command -v mvn &> /dev/null; then
        error_exit "Maven not found"
    fi
    
    # 打包项目
    mvn clean package -DskipTests || error_exit "Maven build failed"
    
    # 备份当前jar包
    if [ -f "$PROJECT_DIR/target/myapp.jar" ]; then
        cp $PROJECT_DIR/target/myapp.jar $PROJECT_DIR/target/myapp.jar.backup
    fi
    
    # 重启服务
    sudo systemctl restart myapp || error_exit "Service restart failed"
    
    # 健康检查
    sleep 10
    if curl -f http://localhost:8080/actuator/health > /dev/null 2>&1; then
        log "Java application deployed successfully ✓"
    else
        log "Java application health check failed, rolling back..."
        cp $PROJECT_DIR/target/myapp.jar.backup $PROJECT_DIR/target/myapp.jar
        sudo systemctl restart myapp
        error_exit "Deployment failed, rollback completed"
    fi
}

# Django项目部署
deploy_django() {
    log "Starting Django application deployment..."
    
    # 激活虚拟环境
    source /home/deploy/myenv/bin/activate || error_exit "Virtual environment activation failed"
    
    # 安装依赖
    pip install -r requirements.txt || error_exit "Dependencies installation failed"
    
    # 数据库迁移
    python manage.py migrate || error_exit "Database migration failed"
    
    # 收集静态文件
    python manage.py collectstatic --noinput || error_exit "Static files collection failed"
    
    # 重启服务
    sudo systemctl restart django || error_exit "Service restart failed"
    
    # 健康检查
    sleep 5
    if curl -f http://localhost:8000/ > /dev/null 2>&1; then
        log "Django application deployed successfully ✓"
    else
        error_exit "Django application health check failed"
    fi
}

# 清理旧备份
cleanup_backups() {
    log "Cleaning up old backups..."
    find $BACKUP_DIR -name "project_*" -mtime +7 -exec rm -rf {} \;
    log "Old backups cleaned up"
}

# 主流程
main() {
    log "Starting automated deployment process..."
    
    create_backup
    update_code
    
    # 根据项目类型选择部署方式
    if [ -f "$PROJECT_DIR/pom.xml" ]; then
        deploy_java
    elif [ -f "$PROJECT_DIR/manage.py" ]; then
        deploy_django
    else
        error_exit "Unknown project type"
    fi
    
    cleanup_backups
    log "Deployment completed successfully ✓"
}

# 执行主流程
main

Webhook自动部署配置

# 安装webhook接收服务
pip install webhook-receiver

# 创建配置文件
cat > webhook_config.json << EOF
{
    "port": 9000,
    "secret": "your-webhook-secret",
    "commands": {
        "main": "/home/deploy/auto_deploy.sh"
    }
}
EOF

# 启动webhook服务
webhook-receiver --config webhook_config.json --daemon

4.4 备份和恢复策略 - 数据安全保障

全量备份脚本

#!/bin/bash
# full_backup.sh

BACKUP_ROOT="/backup"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="$BACKUP_ROOT/full_backup_$DATE"

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

# 数据库备份
echo "Backing up databases..."
mysqldump -u root -p --all-databases > $BACKUP_DIR/mysql_all_$DATE.sql
pg_dumpall -U postgres > $BACKUP_DIR/postgresql_all_$DATE.sql

# 应用文件备份
echo "Backing up application files..."
tar -czf $BACKUP_DIR/app_files_$DATE.tar.gz /home/deploy/

# 配置文件备份
echo "Backing up configuration files..."
tar -czf $BACKUP_DIR/config_files_$DATE.tar.gz /etc/nginx/ /etc/systemd/system/ /home/deploy/.ssh/

# 生成备份清单
echo "Backup Summary:" > $BACKUP_DIR/backup_info.txt
echo "Date: $DATE" >> $BACKUP_DIR/backup_info.txt
echo "MySQL Database: mysql_all_$DATE.sql" >> $BACKUP_DIR/backup_info.txt
echo "PostgreSQL Database: postgresql_all_$DATE.sql" >> $BACKUP_DIR/backup_info.txt
echo "Application Files: app_files_$DATE.tar.gz" >> $BACKUP_DIR/backup_info.txt
echo "Configuration Files: config_files_$DATE.tar.gz" >> $BACKUP_DIR/backup_info.txt

# 压缩整个备份目录
cd $BACKUP_ROOT
tar -czf full_backup_$DATE.tar.gz full_backup_$DATE/
rm -rf full_backup_$DATE/

echo "Full backup completed: full_backup_$DATE.tar.gz"

五、性能优化建议

5.1 JVM参数调优 - Java应用性能提升

内存配置优化

# 生产环境JVM参数示例
JAVA_OPTS="-Xms2g -Xmx4g \
           -XX:+UseG1GC \
           -XX:MaxGCPauseMillis=200 \
           -XX:+UnlockExperimentalVMOptions \
           -XX:+UseStringDeduplication \
           -XX:+OptimizeStringConcat \
           -XX:+UseCompressedOops \
           -XX:+UseCompressedClassPointers \
           -Djava.security.egd=file:/dev/./urandom \
           -Dfile.encoding=UTF-8 \
           -Duser.timezone=Asia/Shanghai"

Spring Boot应用优化

# application-prod.yml
server:
  tomcat:
    max-threads: 200
    min-spare-threads: 10
    max-connections: 8192
    accept-count: 100
  compression:
    enabled: true
    mime-types: text/html,text/xml,text/plain,text/css,text/javascript,application/javascript,application/json
    min-response-size: 1024

spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      idle-timeout: 300000
      max-lifetime: 1200000
      connection-timeout: 20000
  
  cache:
    type: redis
    redis:
      time-to-live: 600000

logging:
  level:
    root: WARN
    com.yourpackage: INFO
  file:
    max-size: 100MB
    max-history: 30

5.2 Django应用优化 - Python Web性能提升

数据库连接池配置

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydjangoapp',
        'USER': 'django_user',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
        'OPTIONS': {
            'MAX_CONNS': 20,
            'MIN_CONNS': 5,
        }
    }
}

# 连接池配置
CONN_MAX_AGE = 600

缓存配置优化

# Redis缓存配置
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': 'redis://127.0.0.1:6379/1',
        'OPTIONS': {
            'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            'COMPRESSOR': 'django_redis.compressors.zlib.ZlibCompressor',
            'IGNORE_EXCEPTIONS': True,
        },
        'KEY_PREFIX': 'myapp',
        'TIMEOUT': 300,
    }
}

# Session配置
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'

5.3 数据库性能优化

MySQL优化配置

[mysqld]
# InnoDB优化
innodb_buffer_pool_size = 2G
innodb_log_file_size = 512M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000
innodb_io_capacity_max = 4000

# 查询缓存
query_cache_type = 1
query_cache_size = 256M
query_cache_limit = 2M

# 连接优化
max_connections = 500
max_connect_errors = 1000
connect_timeout = 10
wait_timeout = 600

PostgreSQL优化配置

# postgresql.conf
shared_buffers = 1GB
effective_cache_size = 3GB
work_mem = 16MB
maintenance_work_mem = 128MB

# 检查点优化
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100

# 连接优化
max_connections = 200
superuser_reserved_connections = 3

5.4 Nginx性能优化

worker进程配置

# nginx.conf
worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 10240;
    use epoll;
    multi_accept on;
}

http {
    # 基础优化
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 100;
    
    # 压缩优化
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types
        text/plain
        text/css
        text/xml
        text/javascript
        application/javascript
        application/xml+rss
        application/json;
    
    # 缓存配置
    open_file_cache max=200000 inactive=20s;
    open_file_cache_valid 30s;
    open_file_cache_min_uses 2;
    open_file_cache_errors on;
}

5.5 系统级性能优化

内核参数调优

# 添加到 /etc/sysctl.conf
# 网络优化
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_congestion_control = bbr

# 文件描述符限制
fs.file-max = 2097152

# 虚拟内存优化
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5

磁盘I/O优化

# 设置I/O调度器
echo 'mq-deadline' > /sys/block/sda/queue/scheduler

# 磁盘参数优化
echo '0' > /proc/sys/vm/swappiness
echo '1' > /proc/sys/vm/drop_caches

5.6 CDN和负载均衡配置

多实例负载均衡

upstream app_servers {
    least_conn;
    server 127.0.0.1:8080 weight=1 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8081 weight=1 max_fails=3 fail_timeout=30s;
    server 127.0.0.1:8082 weight=1 max_fails=3 fail_timeout=30s;
}

server {
    listen 80;
    server_name your-domain.com;
    
    location / {
        proxy_pass http://app_servers;
        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 30s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

六、总结

经过无数次云服务器部署项目的实战经验,我深刻体会到,一个成功的部署不仅仅是把代码跑起来那么简单。真正的生产环境部署需要考虑安全性、稳定性、可维护性和性能的完美平衡。

从服务器选型开始,就要根据业务规模和用户群体做出明智选择 - 国内项目优先考虑阿里云的BGP网络优势,预算有限的项目可以借助腾讯云的高性价比,而国际化业务则离不开AWS的全球覆盖。环境配置看似繁琐,但每一步都有其存在的意义:系统更新是对安全的基本负责,时区同步确保日志的准确性,防火墙配置是安全的第一道防线。

在数据库选择上,我更倾向于PostgreSQL的强大功能和出色的并发处理能力,但MySQL的简单易用和成熟的生态系统也是不错的选择。无论是Java还是Django,一个好的启动脚本都能让运维工作事半功倍,配合systemd的服务管理和健康检查机制,才能真正做到无人值守运行。

SSL证书不再是可选项,而是现代网站的标配,Let’s Encrypt让HTTPS部署变得简单。监控和日志系统就像是医生听诊器,能让你在问题发生前就发现异常。自动备份策略则是最后的保险,确保即使出现最坏情况也能快速恢复。

性能优化是一个持续的过程,从JVM参数调优到数据库连接池配置,从Nginx worker进程优化到系统内核参数调整,每一个细节都可能影响最终的用户体验。记住,没有一刀切的优化方案,只有根据实际业务场景不断测试和调整,才能找到最佳的配置组合。

最终,一个稳定的生产环境就像一台精密的机器,需要每个部件都精心配置和维护。希望这些实战经验能帮助你在云服务器部署的道路上少走弯路,构建出真正企业级的应用服务。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐