第七周作业
1.总结I/O模型
1. 阻塞 I/O(Blocking I/O)
核心特点
应用程序发起 I/O 操作(如 read/write)后,进程会被挂起,直到内核完成数据准备或传输,才恢复执行。
- 阻塞点:数据从内核空间拷贝到用户空间的过程(或等待数据到达内核缓冲区)。
优缺点
- 优点:编程简单(无需处理复杂的非阻塞或事件循环)。
- 缺点:进程在等待期间无法执行其他任务,并发能力差(单线程仅能处理一个 I/O)。
适用场景
短连接、低并发场景(如简单的命令行工具 cat、telnet)。
2. 非阻塞 I/O(Non-blocking I/O)
核心特点
通过设置文件描述符为非阻塞模式(如 fcntl(fd, F_SETFL, O_NONBLOCK)),应用程序发起 I/O 操作后,内核立即返回(不会阻塞进程),但需主动轮询检查数据是否就绪。
优缺点
- 优点:进程不会被长时间阻塞,可执行其他任务。
- 缺点:轮询会浪费 CPU 资源(忙等待),尤其在数据未就绪时频繁空转。
适用场景
需要快速响应且 I/O 操作耗时极短的场景(如实时状态查询),但实际中很少单独使用。
3. I/O 多路复用(I/O Multiplexing)
核心特点
通过一个或多个系统调用(select/poll/epoll),同时监控多个文件描述符的状态(可读/可写/异常),当任意一个或多个描述符就绪时,内核通知应用程序处理。
关键实现
select:内核遍历所有被监控的描述符,时间复杂度O(n),受限于FD_SETSIZE(默认 1024)。poll:基于链表存储描述符,无数量限制,但仍需遍历检查(O(n))。epoll(Linux 特有):基于事件驱动,使用红黑树管理描述符,回调机制通知就绪事件,时间复杂度O(1)(仅处理就绪的描述符),支持水平触发(LT,默认)和边缘触发(ET,更高效)。
优缺点
- 优点:单线程/进程可同时处理大量 I/O 连接(高并发),避免了阻塞和轮询的浪费。
- 缺点:编程复杂度较高(需处理事件循环);
select/poll性能在高并发下下降明显(epoll更优)。
适用场景
高并发网络服务(如 Web 服务器 Nginx、Redis)、需要同时处理多个连接的场景。
4. 信号驱动 I/O(Signal-Driven I/O)
核心特点
应用程序通过 sigaction 注册信号处理函数(如 SIGIO),当内核完成数据准备(数据到达内核缓冲区)时,主动向进程发送信号,通知其进行 I/O 操作。
优缺点
- 优点:无需轮询,内核主动通知,减少 CPU 空转。
- 缺点:信号处理存在并发问题(如信号中断系统调用),编程复杂度高;实际应用中较少使用(被
epoll等替代)。
适用场景
极少需要主动触发且对延迟敏感的场景(如实时信号处理)。
5. 异步 I/O(Asynchronous I/O, AIO)
核心特点
应用程序发起 I/O 操作后,完全不参与数据传输过程,内核在完成数据读写(从磁盘/网络到用户空间)后,通过回调函数或信号通知应用程序。整个过程应用程序可执行其他任务。
关键区别
与 I/O 多路复用的本质差异:
-
I/O 多路复用:应用程序需主动查询就绪的描述符(同步等待内核通知)。
-
异步 I/O:内核完成数据拷贝后通知应用程序(真正异步,应用无需主动干预)。
模型 阻塞性 同步性 核心机制 典型场景 代表接口/技术 阻塞 I/O 阻塞 同步 进程睡眠等待内核完成 短连接、低并发服务 read/write(默认)非阻塞 I/O 非阻塞 同步 轮询检查内核状态 实时状态查询 fcntl(O_NONBLOCK)+ 轮询I/O 多路复用 阻塞(单线程) 同步 内核监控多描述符就绪 高并发网络服务 select/poll/epoll信号驱动 I/O 非阻塞 同步 内核发送信号通知就绪 极少使用 sigaction(SIGIO)异步 I/O 非阻塞 异步 内核完成后通知应用 高吞吐量磁盘 I/O libaio/POSIX AIO
2.完成nginx编译安装脚本
1. 安装编译依赖
sudo apt update
sudo apt install -y build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev libgd-dev libxml2 libxml2-dev uuid-dev
2. 下载 Nginx 源码
cd /data/soft/nginx
wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0
3. 配置编译选项
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_realip_module \
--with-http_addition_module \
--with-http_sub_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_mp4_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_random_index_module \
--with-http_secure_link_module \
--with-http_stub_status_module \
--with-http_auth_request_module \
--with-http_xslt_module=dynamic \
--with-http_image_filter_module=dynamic \
--with-http_geoip_module=dynamic \
--with-threads \
--with-stream \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--with-stream_realip_module \
--with-stream_geoip_module=dynamic \
--with-http_slice_module \
--with-mail \
--with-mail_ssl_module \
--with-compat \
--with-file-aio \
--with-http_v2_module
4. 编译和安装
make -j $(nproc)
sudo make install
5. 创建 Nginx 用户
sudo useradd -r -s /bin/false nginx
6. 创建缓存目录
sudo mkdir -p /var/cache/nginx/client_temp
sudo chown -R nginx:nginx /var/cache/nginx
7. 创建 systemd 服务文件
sudo vim /etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
8. 启动 Nginx 服务
sudo systemctl daemon-reload
sudo systemctl enable nginx
sudo systemctl start nginx
9. 验证安装
sudo systemctl status nginx
curl http://localhost
3.完成nginx平滑升级,总结步骤
1. 备份现有配置与数据
sudo cp -r /etc/nginx /etc/nginx_backup
sudo cp -r /var/www/html /var/www/html_backup
2. 查看当前 Nginx 版本与编译参数
nginx -V
3. 下载新版本 Nginx 源码
cd /tmp
wget https://nginx.org/download/nginx-1.26.0.tar.gz # 替换为最新版本
tar -zxvf nginx-1.26.0.tar.gz
cd nginx-1.26.0
4. 配置编译选项(保持与旧版本一致)
./configure $(nginx -V 2>&1 | grep 'configure arguments:' | sed 's/configure arguments: //')
- 关键点:复用旧版本的所有编译参数(如
--with-http_ssl_module)。
5. 编译新版本(不安装)
make -j $(nproc) # 不执行make install!
6. 验证新版本二进制文件
sudo cp objs/nginx /usr/sbin/nginx.new
sudo nginx.new -t # 测试配置文件兼容性
7. 执行平滑升级
# 1. 发送USR2信号给旧进程
sudo kill -USR2 $(cat /var/run/nginx.pid)
# 2. 确认新旧进程共存
ps -ef | grep nginx # 应有两个master进程
# 3. 验证新版本运行正常后,发送WINCH信号给旧进程
sudo kill -WINCH $(cat /var/run/nginx.pid.oldbin)
8. 完成升级(确认无误后)
# 1. 关闭旧进程
sudo kill -QUIT $(cat /var/run/nginx.pid.oldbin)
# 2. 验证版本
nginx -v
9. 更新 systemd 服务文件(可选)
若旧版本未使用 systemd 管理,需创建服务文件:
sudo systemctl edit nginx # 添加或修改配置
4.总结nginx核心配置,并实现nginx多虚拟主机
一、Nginx 核心配置文件结构
Nginx 主配置文件通常位于/etc/nginx/nginx.conf,核心模块包括:
1. 全局块
user www-data;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
- 关键指令:
user(工作进程用户)、worker_processes(工作进程数)。
2. events 块
events {
worker_connections 1024;
multi_accept on;
}
- 关键指令:
worker_connections(每个进程最大连接数)。
3. http 块(核心)
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
# 虚拟主机配置(多个server块)
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
- 关键指令:
sendfile(高效文件传输)、keepalive_timeout(长连接超时)。
二、多虚拟主机配置实现
虚拟主机配置通过server块实现,可基于IP、端口、域名区分。
1. 基于域名的虚拟主机(最常用)
步骤 1:创建网站目录
sudo mkdir -p /var/www/hua1.com/html
sudo mkdir -p /var/www/hua2.com/html
sudo chown -R www-data:www-data /var/www
步骤 2:配置虚拟主机文件
sudo vim /etc/nginx/sites-available/hua1.com
nginx
server {
listen 80;
server_name hua1.com www.hua1.com; # 域名
root /var/www/hua1.com/html; # 网站根目录
index index.html index.htm;
location / {
try_files $uri $uri/ =404;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /var/www/html;
}
}
步骤 3:复制配置并修改为第二个网站
sudo cp /etc/nginx/sites-available/hua1.com /etc/nginx/sites-available/hua2.com
sudo vim /etc/nginx/sites-available/hua2.com
步骤 4:激活配置
sudo ln -s /etc/nginx/sites-available/hua1.com /etc/nginx/sites-enabled/
sudo ln -s /etc/nginx/sites-available/hua2.com /etc/nginx/sites-enabled/
步骤 5:测试并重启 Nginx
sudo nginx -t
sudo systemctl restart nginx
2. 基于端口的虚拟主机
server {
listen 8080; # 非标准端口
server_name localhost;
root /var/www/port8080/html;
# 其他配置同上
}
3. 基于 IP 的虚拟主机(需多 IP)
server {
listen 10.0.0.13:80; # 特定IP
server_name hua1.com;
# 其他配置同上
}
server {
listen 10.0.0.16:80; # 另一个IP
server_name hua2.com;
# 其他配置同上
}
三、验证配置
-
检查语法:
sudo nginx -t -
测试域名解析:
curl http://site1.com curl http://site2.com
5.根据课程演示,完成nginx日志格式定制
1. 编辑 Nginx 主配置文件
sudo vim /etc/nginx/nginx.conf
2. 在http块中定义自定义日志格式
在http块内添加log_format指令,例如:
http {
# 原有配置...
# 自定义日志格式(示例:包含IP、时间、请求、状态码、响应时间等)
log_format custom '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$request_time $upstream_response_time';
# 访问日志位置
access_log /var/log/nginx/access.log custom;
# 其他配置...
}
3. 为特定虚拟主机定制日志
若需要为某个网站单独设置日志格式,可在server块中覆盖主配置:
server {
listen 80;
server_name example.com;
# 单独的日志格式和路径
access_log /var/log/nginx/example_access.log custom;
# 其他配置...
}
4. JSON 格式日志(高级)
适合与 ELK Stack 等日志分析系统集成:
log_format json_log '{ "timestamp": "$time_iso8601", '
'"client_ip": "$remote_addr", '
'"method": "$request_method", '
'"uri": "$request_uri", '
'"status": $status, '
'"bytes": $body_bytes_sent, '
'"referer": "$http_referer", '
'"agent": "$http_user_agent", '
'"request_time": "$request_time" }';
access_log /var/log/nginx/json_access.log json_log;
5. 测试配置并重启 Nginx
# 测试配置语法
sudo nginx -t
# 重启Nginx
sudo systemctl restart nginx
6. 验证日志格式
查看日志文件确认格式是否正确:
tail -f /var/log/nginx/access.log
7. 日志分割(避免日志过大)
使用logrotate自动分割日志:
sudo vim /etc/logrotate.d/nginx
添加以下内容:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 0640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
6.完成基于Nginx和Python的动态站点安装配置
1. 安装依赖环境
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装Nginx
sudo apt install nginx -y
# 安装Python3和虚拟环境
sudo apt install python3 python3-pip python3-venv -y
2. 创建 Python 应用(以 Flask 为例)
# 创建项目目录
mkdir -p /var/www/myapp && cd /var/www/myapp
# 创建虚拟环境并激活
python3 -m venv venv
source venv/bin/activate
# 安装Flask
pip install flask gunicorn
# 创建示例应用
cat > app.py << EOF
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, World! This is a Flask app behind Nginx."
@app.route('/api/data')
def data():
return {"message": "Dynamic data from Python backend"}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
EOF
3. 配置 Gunicorn 作为 WSGI 服务器
# 测试Gunicorn是否能正确启动应用
gunicorn --bind 0.0.0.0:5000 app:app
# 按Ctrl+C停止测试
# 创建systemd服务文件
sudo nano /etc/systemd/system/myapp.service
添加以下内容:
[Unit]
Description=Gunicorn instance to serve myapp
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
Environment="PATH=/var/www/myapp/venv/bin"
ExecStart=/var/www/myapp/venv/bin/gunicorn --workers 3 --bind unix:myapp.sock -m 007 app:app
[Install]
WantedBy=multi-user.target
4. 启动并启用 Gunicorn 服务
# 重载systemd管理器配置
sudo systemctl daemon-reload
# 启动服务
sudo systemctl start myapp
# 设置开机自启
sudo systemctl enable myapp
# 检查服务状态
sudo systemctl status myapp
5. 配置 Nginx 反向代理
# 创建Nginx配置文件
sudo nano /etc/nginx/sites-available/myapp
# 添加以下内容
server {
listen 80;
server_name your_domain_or_ip; # 替换为你的域名或IP
location / {
include proxy_params;
proxy_pass http://unix:/var/www/myapp/myapp.sock;
}
}
# 创建软链接启用配置
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
# 测试配置并重启Nginx
sudo nginx -t
sudo systemctl restart nginx
6. 验证部署
# 检查Nginx服务状态
sudo systemctl status nginx
# 访问网站
curl http://your_domain_or_ip
curl http://your_domain_or_ip/api/data
7. 关键配置说明
- Gunicorn 参数:
--workers 3:启动 3 个工作进程--bind unix:myapp.sock:使用 Unix 套接字通信(更安全高效)
- Nginx 反向代理:
proxy_pass:转发请求到 Gunicorn 套接字proxy_params:包含常用代理参数(位于/etc/nginx/proxy_params)
8. 安全强化
-
配置防火墙:
sudo ufw allow 'Nginx Full' sudo ufw enable -
启用 HTTPS(使用 Certbot):
sudo apt install certbot python3-certbot-nginx -y sudo certbot --nginx -d your_domain
9. 日志配置
在 Nginx 配置中添加自定义日志:
server {
# 其他配置...
access_log /var/log/nginx/myapp_access.log;
error_log /var/log/nginx/myapp_error.log;
}
10. 应用更新流程
# 1. 停止服务
sudo systemctl stop myapp
# 2. 更新代码
cd /var/www/myapp
git pull # 如果使用版本控制
# 3. 重启服务
sudo systemctl start myapp

浙公网安备 33010602011771号