IO模型和NGINX安装升级
IO模型
IO概念
I/O在计算机中指Input/Output, IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主要指标之一。
Linux的IO类型
磁盘I/O
磁盘I/O是进程向内核发起系统调用,请求磁盘上的某个资源比如是html 文件或者图片,然后内核通过相应的驱动程序将目标文件加载到内核的内存空间,加载完成之后把数据从内核内存再复制给进程内存,如果是比较大的数据也需要等待时间
网络I/O
一切皆文件,本质为对socket文件的读写,网络通信就是网络协议栈到用户空间进程的IO就是网络IO
工作过程
1.客户端发起请求 先发送到网卡
2.网卡收到的报文复制到内核空间
3.内核空间再复制到用户空间的应用程序空间
4.nginx 分析得到一个磁盘页面文件
5.再将需求反馈给内核空间,应为应用程序没有权限从磁盘上直接读取文件,需要依靠内核
6.内核去磁盘上找到所需要的文件,加载到内核空间
7.加载后再复制到用户空间
8.用户空间构建响应报文,交给内核空间,内核空间再复制给网卡,返回给用户
整个过程会来回切换 用户空间,内核空间 那么我们可以再次基础上做优化处理
程序设计理念
同步/异步(消息反馈机制):关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。
- 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事情是否处理完成
- 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
- 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。
- 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
nginx介绍
Nginx的版本分为开发版、稳定版和过期版,nginx以功能丰富著称,它即可以作为http服务器,也可以作为反向代理服务器或者邮件服务器,也可以作为反向代理服务器或者邮件服务器,能够快速的响应静态网页的请求,支持FastCGI/SSL/Virtual Host/URL Rwrite/Gzip/HTTP Basic Auth/http或者TCP的负载均衡(1.9版本以上且开启stream模块)等功能,并且支持第三方的功能扩展。
nginx功能
- 静态的web资源服务器html,图片,js,css,txt等静态资源
- http/https协议的反向代理 7层
- 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
- tcp/udp协议的请求转发(反向代理) 4层
nginx 进程结构
-
多进程方式:服务器每接收到一个客户端请求就有服务器的主进程生成一个子进程响应客户端,直到用户关闭连接,这样的优势是处理速度快,子进程之间相互独立,但是如果访问过大会导致服务器资源耗尽而无法提供请求。
-
多线程方式:与多进程方式类似,但是每收到一个客户端请求会有服务进程派生出一个线程来个客户方进行交互,一个线程的开销远远小于一个进程,因此多线程方式在很大程度减轻了web服务器对系统资源的要求,但是多线程也有自己的缺点,即当多个线程位于同一个进程内工作的时候,可以相互访问同样的内存地址空间,所以他们相互影响,一旦主进程挂掉则所有子线程都不能工作了,IIS服务器使用了多线程的方式,需要间隔一段时间就重启一次才能稳定。
nginx 模块
核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件驱动机制 、进程管理等核心功能
标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置 等等
可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如:Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持
Stream服务模块: 实现反向代理功能,包括TCP协议代理
第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等
nginx安装与使用
yum安装nginx
http://nginx.org/en/linux_packages.html #官网
yum install -y epel-release #安装epel源
yum install nginx -y #安装nginx
编译安装nginx
yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel
#安装依赖包
useradd -M -s /sbin/nologin nginx
#新建nginx用户便于管理
cd /opt/
wget http://nginx.org/download/nginx-1.18.0.tar.gz#官网下载安装包
tar xf nginx-1.18.0.tar.gz #解压软件包
cd nginx-1.18.0/
mkdir /apps/nginx -p
./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module
make -j2&&make install # 编译安装
chown -R nginx.nginx /apps/nginx
#修改权限
/apps/nginx/sbin/nginx#绝对路径启动
ln -s /apps/nginx/sbin/nginx /usr/sbin/ #创建软连接后直接 nginx启动
conf:保存nginx所有的配置文件
html目录中保存了nginx服务器的web文件
logs:用来保存nginx服务器的访问日志错误日志等日志
sbin:保存nginx二进制启动脚本
将ngnix添加系统服务
vim /usr/lib/systemd/system/nginx.service #建立.service文件
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid #注意文件位置,如果不对 启动不了
ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf #注意启动文件位置
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
[Install]systemc
WantedBy=multi-user.target
通过脚本运行启动
vim /etc/init.d/nginx
#!/bin/bash
#chkconfig: - 99 20
#description:Nginx Service Control Script
COM="/usr/local/nginx/sbin/nginx"
PID="/usr/local/nginx/logs/nginx.pid"
case "$1" in
start)
$COM
;;
stop)
kill -s QUIT $(cat $PID)
;;
restart)
$0 stop
$0 start
;;
reload)
kill -s HUP $(cat $PID)
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
esac
exit 0
chmod +x /etc/init.d/nginx
chkconfig --add nginx #添加为系统服务
chkconfig --list nginx
service nginx start
service nginx stop #哪个开启用那个关闭
systemctl stop nginx
systemctl start nginx
修改pid文件位置
mkdir /apps/nginx/run/ #创建目录
vim /apps/nginx/conf/nginx.conf #修改配置文件
pid /apps/nginx/run/nginx.pid; #找到 pid的位置修改
systemctl daemon-reload #重新加载配置
nginx信号使用
nginx -h/? #帮助
nginx -v #显示版本号
nginx -V #显示编译详细信息情况 模块等信息
nginx -s stop #立即关闭nginx
nginx -s quit #不影响业务的状态下退出
nginx -s reload #重新加载
nginx -s reopen #分割日志
nginx -g 'user zhangsan;' #以张三身份运行,默认是以nginx身份
nginx -g 'daemon off;' #前台运行命令
nginx -t #检查语法格式
nginx -T #打印配置文件
nginx -c 文件 #指明加载配置文件
分割日志
[root@node2 nginx]cd /var/log/nginx/
#切换到
[root@node2 nginx]mv access.log access.log.bak
[root@node2 nginx]touch access.log
#此时日志不会写入到新文件
[root@node2 nginx]ps aux |grep nginx
[root@node2 nginx]kill -s USR1 117994
[root@node2 nginx]nginx -s reopen
平滑升级
- 将旧Nginx文件换成新Nginx文件(注意备份)
- 向master进程发送USR2信号
- master进程修改pid文件名,加后缀.oldbin
- master进程用新Nginx文件启动新master进程,系统中将有新旧两个Nginx主进程共同提供Web服务
- 向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止,并删除Nginx.pid.oldbin文件
- 向旧master进程发送QUIT信号,关闭老master
- 如果发现升级有问题,可以回滚向老master发送HUP,向新master发送QUIT
[root@localhost ~]ps aux |grep nginx #先查看是否开启nginx
[root@localhost ~]vim /apps/nginx/conf/nginx.conf
#开启 两核
#user nobody;
worker_processes 2; #worker_processes 1 原来是1核
[root@localhost ~]ln -s /apps/nginx/sbin/nginx /usr/bin/
[root@localhost ~]nginx -s reload #重新加载配置文件
[root@localhost ~]wget https://nginx.org/download/nginx-1.20.2.tar.gz -P /usr/local/src/ #下载安装包到src目录
[root@localhost ~]cd /usr/local/src
[root@localhost src]tar xf nginx-1.20.2.tar.gz #解压
[root@localhost src]cd nginx-1.20.2/
[root@localhost nginx-1.20.2]nginx -V #查看详细信息
[root@localhost nginx-1.20.2]./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module #重新编译
[root@localhost nginx-1.20.2]make #不要make install
[root@localhost objs]cd objs #此文件夹中有新版本的nginx 运行程序
[root@localhost objs]./nginx -v #查看版本
nginx version: nginx/1.20.2
[root@localhost objs]mv /apps/nginx/sbin/nginx /apps/nginx/sbin/nginx.bak #将低版本的nginx主程序改名
[root@localhost objs]cp /usr/local/src/nginx-1.20.2/objs/nginx /apps/nginx/sbin/ #将新版本 拷入进去
[root@localhost objs]/apps/nginx/sbin/nginx -t #检查语法问题
[root@localhost nginx]kill -USR2 `cat /apps/nginx/logs/nginx.pid` #发送信号
[root@localhost nginx]dd if=/dev/zero of=/apps/nginx/html/m.img bs=1G count=10 #校验
[root@localhost nginx]wget --limit-rate=1M http://192.168.65.110/m.img #开启新机器下载
[root@localhost nginx]ss -ntap|grep 80 #查看进程管理下载
LISTEN 0 128 *:80 *:* users:(("nginx",pid=8850,fd=6),("nginx",pid=8849,fd=6),("nginx",pid=8848,fd=6),("nginx",pid=5489,fd=6),("nginx",pid=5488,fd=6),("nginx",pid=5146,fd=6))
ESTAB 0 0 192.168.65.110:22 192.168.65.1:59680 users:(("sshd",pid=1785,fd=3))
ESTAB 0 461224 192.168.65.110:80 192.168.65.103:38450 users:(("nginx",pid=5488,fd=3))
[root@localhost nginx]ls /apps/nginx/logs/ #有新老两个进程
access.log error.log nginx.pid nginx.pid.oldbin
[root@localhost nginx]cat /apps/nginx/logs/nginx.pid.oldbin
5146
[root@localhost nginx]kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin` #关闭老进程
[root@localhost nginx]#pstree -p |grep nginx #查看老进程
|-nginx(5146)---nginx(8848)-+-nginx(8849)
| `-nginx(8850)