服务器搭建

1.1 更新系统并安装基础依赖

bash 复制代码
# 更新系统包
sudo apt update
sudo apt upgrade -y

# 安装必要依赖
sudo apt install -y python3 python3-pip python3-venv nginx git
sudo apt install -y build-essential python3-dev

1.2 创建项目目录结构

bash 复制代码
# 创建项目目录
sudo mkdir -p /opt/mfc-server/{app,logs,data/uploads,data/files,config}
sudo mkdir -p /var/log/mfc-server

# 设置目录权限
sudo chown -R $USER:$USER /opt/mfc-server
sudo chmod -R 755 /opt/mfc-server

2. 创建 Flask 应用

2.1 创建虚拟环境

bash 复制代码
cd /opt/mfc-server
python3 -m venv venv
source venv/bin/activate

2.2 安装 Python 依赖

创建 requirements.txt

使用 vim 编辑器
bash 复制代码
vim requirements.txt

在vim中:

  • i 进入插入模式

  • 输入内容:

bash 复制代码
flask==2.3.3
gunicorn==21.2.0
python-dotenv==1.0.0
  • Esc 退出插入模式

  • 输入 :wq 保存并退出

安装依赖:

bash 复制代码
pip install -r requirements.txt

2.3 创建 Flask 应用

创建 /opt/mfc-server/app/__init__.py

bash 复制代码
import os
from flask import Flask
from dotenv import load_dotenv

load_dotenv()

def create_app():
    app = Flask(__name__)
    
    # 基础配置
    app.config['SECRET_KEY'] = os.getenv('SECRET_KEY', 'dev-secret-key')
    app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024  # 1MB
    
    return app

创建 /opt/mfc-server/app/main.py

bash 复制代码
import os
import json
import logging
from datetime import datetime
from flask import request, jsonify, send_file
from app import create_app

app = create_app()

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s %(levelname)s %(name)s %(message)s',
    handlers=[
        logging.FileHandler('/var/log/mfc-server/app.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# 数据目录
UPLOAD_DIR = '/opt/mfc-server/data/uploads'
FILE_DIR = '/opt/mfc-server/data/files'

@app.route('/api/v1/health', methods=['GET'])
def health_check():
    """健康检查端点"""
    return jsonify({
        "status": "healthy",
        "timestamp": datetime.now().isoformat(),
        "service": "mfc-data-server"
    })

@app.route('/api/v1/data', methods=['POST'])
def receive_data():
    """接收客户端数据"""
    try:
        client_ip = request.remote_addr
        timestamp = datetime.now().isoformat()
        
        # 记录请求信息
        logger.info(f"Data request from {client_ip}")
        
        # 获取数据
        if request.content_type == 'application/json':
            data = request.get_json()
            if data:
                data_str = json.dumps(data, ensure_ascii=False)
            else:
                data_str = ""
        else:
            data_str = request.get_data(as_text=True)
        
        # 验证数据大小
        if len(data_str) > 1024:  # 限制1KB
            logger.warning(f"Data too large from {client_ip}: {len(data_str)} bytes")
            return jsonify({"error": "Data too large"}), 400
        
        # 保存数据到文件
        date_str = datetime.now().strftime('%Y%m%d')
        log_file = os.path.join(UPLOAD_DIR, f"data_{date_str}.log")
        
        with open(log_file, 'a', encoding='utf-8') as f:
            log_entry = {
                "timestamp": timestamp,
                "client_ip": client_ip,
                "data": data_str,
                "data_length": len(data_str)
            }
            f.write(json.dumps(log_entry, ensure_ascii=False) + '\n')
        
        logger.info(f"Data saved from {client_ip}: {len(data_str)} bytes")
        
        return jsonify({
            "status": "success",
            "timestamp": timestamp,
            "received_bytes": len(data_str),
            "message": "Data received successfully"
        })
        
    except Exception as e:
        logger.error(f"Error processing data from {request.remote_addr}: {str(e)}")
        return jsonify({"error": "Internal server error"}), 500

@app.route('/api/v1/file', methods=['GET'])
def download_file():
    """提供文件下载"""
    try:
        filename = request.args.get('name', 'config.txt')
        file_path = os.path.join(FILE_DIR, filename)
        
        # 安全检查:防止目录遍历攻击
        if '..' in filename or filename.startswith('/'):
            return jsonify({"error": "Invalid filename"}), 400
        
        if not os.path.exists(file_path):
            logger.warning(f"File not found: {filename} requested by {request.remote_addr}")
            return jsonify({"error": "File not found"}), 404
        
        logger.info(f"File downloaded: {filename} by {request.remote_addr}")
        
        return send_file(file_path, as_attachment=True)
        
    except Exception as e:
        logger.error(f"Error serving file: {str(e)}")
        return jsonify({"error": "Internal server error"}), 500

@app.route('/api/v1/stats', methods=['GET'])
def get_stats():
    """获取服务器统计信息(可选)"""
    try:
        # 计算今日接收的数据量
        date_str = datetime.now().strftime('%Y%m%d')
        log_file = os.path.join(UPLOAD_DIR, f"data_{date_str}.log")
        
        count = 0
        if os.path.exists(log_file):
            with open(log_file, 'r', encoding='utf-8') as f:
                count = sum(1 for _ in f)
        
        return jsonify({
            "status": "success",
            "requests_today": count,
            "timestamp": datetime.now().isoformat()
        })
    except Exception as e:
        logger.error(f"Error getting stats: {str(e)}")
        return jsonify({"error": "Internal server error"}), 500

if __name__ == '__main__':
    # 确保目录存在
    os.makedirs(UPLOAD_DIR, exist_ok=True)
    os.makedirs(FILE_DIR, exist_ok=True)
    
    # 开发模式运行
    app.run(host='0.0.0.0', port=8082, debug=True)

创建 /opt/mfc-server/run.py

bash 复制代码
from app.main import app

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8082)

3. 配置 Gunicorn

3.1 创建 Gunicorn 配置文件

创建 /opt/mfc-server/config/gunicorn.conf.py

bash 复制代码
import multiprocessing

# 服务器绑定
bind = "127.0.0.1:8082"

# 工作进程数
workers = multiprocessing.cpu_count() * 2 + 1

# 工作模式
worker_class = "sync"

# 最大并发连接数
worker_connections = 1000

# 超时设置
timeout = 30
keepalive = 2

# 进程名称
proc_name = "mfc-server"

# 日志配置
accesslog = "/var/log/mfc-server/gunicorn_access.log"
errorlog = "/var/log/mfc-server/gunicorn_error.log"
loglevel = "info"

# 最大请求数(防止内存泄漏)
max_requests = 1000
max_requests_jitter = 100

# 预加载应用(减少内存占用和启动时间)
preload_app = True

# 守护进程模式(通过systemd管理,这里设为False)
daemon = False

3.2 创建启动脚本

创建 /opt/mfc-server/start_server.sh

bash 复制代码
#!/bin/bash

cd /opt/mfc-server

# 激活虚拟环境
source venv/bin/activate

# 启动Gunicorn
exec gunicorn -c config/gunicorn.conf.py "app.main:app"

设置执行权限:

bash 复制代码
chmod +x /opt/mfc-server/start_server.sh

4. 配置 Nginx

4.1 创建 Nginx 配置文件

创建 /etc/nginx/sites-available/mfc-server

bash 复制代码
# MFC数据服务器配置
server {
    listen 80;
    server_name your-domain.com;  # 替换为您的域名或IP
    
    # 客户端大小限制
    client_max_body_size 1M;
    
    # 访问日志
    access_log /var/log/nginx/mfc_access.log;
    error_log /var/log/nginx/mfc_error.log;
    
    # 静态文件服务(如果需要)
    location /static/ {
        alias /opt/mfc-server/static/;
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
    
    # API反向代理配置
    location /api/ {
        # 代理到Gunicorn
        proxy_pass http://127.0.0.1:8082;
        
        # 设置代理头
        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;
        
        # 超时设置
        proxy_connect_timeout 30s;
        proxy_send_timeout 30s;
        proxy_read_timeout 30s;
        
        # 缓冲区设置
        proxy_buffering on;
        proxy_buffer_size 4k;
        proxy_buffers 8 4k;
        
        # 禁用代理重定向
        proxy_redirect off;
    }
    
    # 根路径重定向到健康检查
    location = / {
        proxy_pass http://127.0.0.1:8082/api/v1/health;
        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;
    }
    
    # 安全设置:隐藏服务器版本
    server_tokens off;
}

4.2 启用 Nginx 站点

bash 复制代码
# 创建符号链接
sudo ln -s /etc/nginx/sites-available/mfc-server /etc/nginx/sites-enabled/

# 测试Nginx配置
sudo nginx -t

# 重启Nginx
sudo systemctl restart nginx

# 设置Nginx开机自启
sudo systemctl enable nginx

5. 创建 Systemd 服务

5.1 创建 Systemd 服务文件

创建 /etc/systemd/system/mfc-server.service

bash 复制代码
[Unit]
Description=MFC Data Server
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/mfc-server
Environment=PATH=/opt/mfc-server/venv/bin
ExecStart=/opt/mfc-server/venv/bin/gunicorn -c config/gunicorn.conf.py "app.main:app"
ExecReload=/bin/kill -s HUP $MAINPID
Restart=always
RestartSec=3

# 安全设置
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/opt/mfc-server /var/log/mfc-server

# 日志设置
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

5.2 启动并启用服务

bash 复制代码
# 重新加载systemd配置
sudo systemctl daemon-reload

# 启动服务
sudo systemctl start mfc-server

# 设置开机自启
sudo systemctl enable mfc-server

# 检查服务状态
sudo systemctl status mfc-server

6. 创建示例配置文件

6.1 创建示例配置文件

创建 /opt/mfc-server/data/files/config.txt

bash 复制代码
# MFC客户端配置文件
# 更新时间: 2024-01-01

[Server]
server_url=http://your-domain.com/api/v1/data
file_url=http://your-domain.com/api/v1/file

[Client]
device_id=default_device
check_interval=3600
max_retries=3

[Data]
format=json
encoding=utf-8

7. 配置日志轮转

7.1 配置 Logrotate

创建 /etc/logrotate.d/mfc-server

bash 复制代码
/var/log/mfc-server/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    copytruncate
    postrotate
        systemctl reload mfc-server > /dev/null 2>/dev/null || true
    endscript
}

8. 防火墙配置

8.1 配置防火墙(如果启用)

bash 复制代码
# 开放HTTP端口(80)
sudo ufw allow 80/tcp

# 如果使用其他防火墙工具,确保80端口开放

9. 部署验证

9.1 测试API端点

bash 复制代码
# 健康检查
curl http://your-domain.com/api/v1/health

# 发送测试数据
curl -X POST http://your-domain.com/api/v1/data \
  -H "Content-Type: application/json" \
  -d '{"device_id": "test_device", "data": "test message"}'

# 下载配置文件
curl -O http://your-domain.com/api/v1/file?name=config.txt

9.2 检查服务状态

bash 复制代码
# 检查应用服务
sudo systemctl status mfc-server

# 检查Nginx服务
sudo systemctl status nginx

# 检查日志
sudo tail -f /var/log/mfc-server/app.log
sudo tail -f /var/log/nginx/mfc_access.log

10. 监控和维护

10.1 创建监控脚本

创建 /opt/mfc-server/scripts/health_check.sh

bash 复制代码
#!/bin/bash

# 健康检查脚本
response=$(curl -s -o /dev/null -w "%{http_code}" http://localhost/api/v1/health)

if [ "$response" != "200" ]; then
    echo "Service is down! HTTP Code: $response"
    # 可以添加重启逻辑或发送通知
    systemctl restart mfc-server
else
    echo "Service is healthy"
fi

10.2 设置定时监控

bash 复制代码
# 编辑crontab
crontab -e

# 添加健康检查(每5分钟一次)
*/5 * * * * /opt/mfc-server/scripts/health_check.sh >> /var/log/mfc-server/health_check.log 2>&1

部署完成后的目录结构

bash 复制代码
/opt/mfc-server/
├── app/
│   ├── __init__.py
│   └── main.py
├── config/
│   └── gunicorn.conf.py
├── data/
│   ├── uploads/
│   └── files/
│       └── config.txt
├── logs/
├── scripts/
│   └── health_check.sh
├── venv/
├── requirements.txt
├── run.py
└── start_server.sh

如果有问题

问题诊断步骤

1. 首先检查Gunicorn服务状态

bash 复制代码
# 检查mfc-server服务状态
sudo systemctl status mfc-server


# 如果服务不存在或失败,重新加载并启动
sudo systemctl daemon-reload
sudo systemctl start mfc-server
sudo systemctl status mfc-server

# 查看服务日志
sudo journalctl -u mfc-server -f

2. 直接测试Gunicorn服务

bash 复制代码
# 直接在本地测试Gunicorn(确保服务在运行)
curl http://127.0.0.1:8082/api/v1/health

# 如果这个能工作,说明Flask应用正常
测试2:测试数据接收接口
bash 复制代码
curl -X POST http://127.0.0.1:8082/api/v1/data \
  -H "Content-Type: application/json" \
  -d '{"device_id": "test_device_001", "data": "Hello from test", "timestamp": "2024-01-01T12:00:00Z"}'

3. 检查Nginx配置

查看Nginx配置文件:

bash 复制代码
# 检查Nginx配置语法
sudo nginx -t

# 查看当前的Nginx配置
cat /etc/nginx/sites-available/mfc-server

# 检查是否已启用站点
ls -la /etc/nginx/sites-enabled/
相关推荐
LSL666_2 小时前
云服务器安装Tomcat
运维·服务器·tomcat
b***65322 小时前
自己编译RustDesk,并将自建ID服务器和key信息写入客户端
运维·服务器
k***45992 小时前
服务器无故nginx异常关闭之kauditd0 kswapd0挖矿病毒 CPU占用200% 内存耗尽
运维·服务器·nginx
p***62992 小时前
【Sql Server】sql server 2019设置远程访问,外网服务器需要设置好安全组入方向规则
运维·服务器·安全
LCG元2 小时前
效率翻倍!10个让你爱不释手的 Linux 命令行"神器"
linux
Pocker_Spades_A2 小时前
在家写的代码,办公室接着改?Jupyter通过cpolar实现远程访问这么玩
ide·python·jupyter
BS_Li2 小时前
【Linux系统编程】Ext系列文件系统
android·linux·ext系列文件系统
q***01772 小时前
Linux 下安装 Golang环境
linux·运维·golang
m5655bj3 小时前
使用 Python 高效复制 Excel 行、列、单元格
开发语言·python·excel