Part 1
- 一 、HTTP 和 Nginx
- 1.1 套接字Socket
- 1.2 URL
- 1.2.1 定义
- 1.2.1 URL和URN的区别
- 1.2.3 URL组成
- 1.3 请求访问完整过程详解
- 二、I/O模型 处理高并发的时候用
- 2.1 I/O模型简介
- 2.2 多路复用I/O型
- 2.3 异步I/O模型
- 2.4 事件模型 select poll epoll
- 三、NGINX概述
- 3.1 简介
- 3.2 NGINX和APACHE的区别?
- 3.3 什么是零拷贝?
- 四、Nginx模块
- 4.1 安装方式
- 4.1.1 方式一 yum安装
- 4.1.2 方式二 编译安装 (推荐使用)
- 1)前置准备
- 2)编译安装nginx
- 3)nginx开机自启(可选)
- 4.2 Nginx命令 常用选项
- 4.2.1 常用选项
- 4.2.2 信号
- 4.3 日志分割(Nginx 优化 )
- 4.4 升级nginx
- 4.4.1 思路
- 4.4.2 平滑升级nginx
- 4.5 退回旧版本(回滚)
一 、HTTP 和 Nginx
1.1 套接字Socket
套接字Socket是进程间通信IPC的一种实现,允许位于不同主机(或同一主机)上不同进程之间进行通信和数据交换。
进程间的传输要有两个标志:IP地址和端口号,合称为套接字地址 socket address
- 客户机套接字地址定义了一个唯一的客户进程
- 服务器套接字地址定义了一个唯一的服务器进程
1.2 URL
1.2.1 定义
统一资源定位符,用于描述某服务器某特定资源位置。
1.2.1 URL和URN的区别
URN定义某事物的身份,仅用于命名,而不指定地址。
URL提供查找该事物的方法。
1.2.3 URL组成
<scheme>://<user>:<password>@<host>:<port>/<path>;<params>?<query>#<frag>
scheme:方案,访问服务器以获取资源时要使用哪种协议
user:用户,某些方案访问资源时需要的用户名
password:密码,用户对应的密码,中间用:分隔
Host:主机,资源宿主服务器的主机名或IP地址
port:端口,资源宿主服务器正在监听的端口号,很多方案有默认端口号
path:路径,服务器资源的本地名,由一个/将其与前面的URL组件分隔
params:参数,指定输入的参数,参数为名/值对,多个参数,用;分隔
query:查询,传递参数给程序,如数据库,用?分隔,多个查询用&分隔
frag:片段,一小片或一部分资源的名字,此组件在客户端使用,用#分隔
协议(Protocol):该URL的协议部分是 "https://",表示使用HTTPS协议进行数据传输。
用户名和密码(Username and Password):URL中的 "john.doe" 是用户名,表示用于身份验证的用户名。这是可选的,并且很少在实践中使用。密码可以通过 ":" 字符的存在被提供,但在该URL中没有明确提供密码。
主机名(Hostname):主机名部分是 "www.example.com",表示资源所在的主机或服务器的地址。
端口号(Port):该URL中明确指定了端口号 "123",表示用于与服务器建立连接的端口。如果未指定端口号,默认使用协议的默认端口(例如,HTTPS的默认端口是443)。
路径(Path):路径部分是 "/forum/questions/",表示所请求资源的路径。在这个示例中,资源位于主机的 "/forum/questions/" 目录下。
查询参数(Query Parameters):查询参数以 "?" 开始,后跟参数的键值对,用 "&" 分隔。在该URL中,查询参数是 "tag=networking&order=newest",表示请求中附带了两个参数:'tag' 的值是 'networking','order' 的值是 'newest'。这些参数可以被服务器用来进行进一步的处理或筛选。
锚点(Anchor):锚点部分以 "#" 开始,用于在文档内定位到特定的片段。在该URL中,锚点是 "topscheme",它指示浏览器在加载文档后将滚动到名为 "topscheme" 的片段。
1.3 请求访问完整过程详解
当用户发起http请求 需要请求index.html网页文件;
客户端请求和服务器端建立连接,建立连接后,客户端发送请求报文;
服务端网卡收到请求报文,将该报文复制到内核空间(操作系统),内核空间分析报文后交给对应的程序;
nginx分析该报文,对比报文和自己的配置文件,按照配置文件完成请求,分析完成后,发现客户需要index.html文件;
由于程序的权限问题,没有资格直接调用磁盘上的文件,程序会再将这个请求,再次转发给内核;
内核得到请求后,去磁盘中寻找目标文件,找到文件后,复制给程序;
程序构建响应报文,构建好后交给内核空间;
内核空间得到响应报文后,再交给网卡,发给客户。
二、I/O模型 处理高并发的时候用
2.1 I/O模型简介
同步/异步(消息反馈机制):关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。
- 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事情是否处理完成
- 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
- 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。
- 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
2.2 多路复用I/O型
多路复用I/O(I/O multiplexing)模型是一种基于事件驱动的 I/O 处理模式。它利用操作系统提供的多路复用机制(如select、poll、epoll等)来同时监听多个 I/O 事件,当某个事件就绪时,通知应用程序进行处理。
通过多路复用I/O模型,可以在一个线程中同时处理多个客户端连接的 I/O 操作,而不需要为每个连接创建一个线程或进程,避免了资源开销和上下文切换的成本。
常见的多路复用I/O模型有:
- select:适用于连接数不太多的情况,轮询监听多个文件描述符上的 I/O 事件。
- poll:与select类似,但没有连接数的限制,并且不会修改传入的描述符集合。
- epoll:适用于连接数非常多的情况,通过事件驱动机制来处理 I/O 事件,可以在大并发情况下具有较高的性能优势。
2.3 异步I/O模型
异步 I/O 模型是一种非阻塞的 I/O 处理模式,通过回调函数或事件通知的方式来处理已完成的 I/O 操作,能够提高系统的并发性和处理效率。
2.4 事件模型 select poll epoll
①Nginx服务使用异步非阻塞模式:请求不需要排队,会反馈任务的完成结果。
②Apache服务使用同步阻塞模式:请求需要排队,且不会主动返回结果。
优缺点
模型 | 描述 | 优点 | 缺点 |
---|---|---|---|
select | 最古老的模型 | 可以同时监视多个文件描述符 | 效率较低,不适用于大规模并发连接 |
poll | 类似于select | 效率相对更高,可以处理大量并发连接 | 随着文件描述符数量的增加,性能下降较明显 |
epoll | Linux特有模型 | 在高并发场景下性能表现更好,使用边缘触发方式,只在状态变化时通知 | 在非Linux系统上不可用,涉及到一些操作系统特定的细节和配置 |
区别
select | poll | epoll | |
---|---|---|---|
操作方式 | 遍历 | 遍历 | 回调 |
底层实现 | 数组 | 链表 | 哈希表 |
IO效率 | 每次调用都进行线性遍历,时间复杂度为0(n) | 同左 | 事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪的fd放到rdlllist里,时间复杂度O(1) |
最大连接数 | 1024(x86)2048(x64) | 无上限 | 无上限 |
fd拷贝 | 每次调用select都需要把fd集合从用户拷贝到内核态 | 每次调用poll,都需要把fd集合从用户态拷贝到内核态 | 调用epoll ctl时拷贝进内核并保存,之后每次epoll wait不拷贝 |
三、NGINX概述
3.1 简介
①作用:支持七层(应用层)和四层(传输层)反向代理、可做web服务器。
②特性:高可靠性、支持热部署、可扩展性好、高并发高性能、单机部署。
⑤进程:一个主进程master生成多个worker子进程,worker子进程负责处理工作。
3.2 NGINX和APACHE的区别?
特点 | Nginx | Apache |
---|---|---|
并发处理 | 高并发处理能力,轻量级且低内存消耗 | 对静态文件处理高效,但在高并发情况下内存消耗较大 |
资源占用 | 占用更少的系统资源和内存 | 占用较多的系统资源和内存 |
事件驱动 | 使用事件驱动模型,可在较少的线程上同时处理多个连接 | 使用多线程模型,会为每个连接创建一个线程 |
配置灵活性 | 配置简单明了,易于阅读和维护 | 配置相对复杂,需要更多的配置项指定 |
扩展性 | 支持动态模块和第三方扩展,可自定义功能 | 支持动态模块和第三方扩展,但相对Nginx更少 |
虚拟主机 | 支持无限个虚拟主机配置,每个虚拟主机独立配置 | 支持无限个虚拟主机配置,但每个虚拟主机使用同一套配置 |
模块支持 | 支持反向代理、负载均衡、HTTP缓存等 | 支持反向代理、负载均衡、SSL等 |
用户群体 | 更适合高并发、网络应用场景,如反向代理、负载均衡 | 更适合传统Web服务器应用,如静态内容和PHP |
核心区别
1)apache 是同步多进程模型,一个连接对应一个进程,而 nginx 是异步的,多个
连接(万级别)可以对应一个进程;
2)需要稳定用apache,需要高性能用nginx。
3.3 什么是零拷贝?
在Nginx中,使用零拷贝技术可以将数据从文件系统直接发送到网络套接字中,而不需要中间的内存拷贝。
这可以减少CPU的使用量,减少内存带宽的消耗,并且可以更快地将数据发送到客户端
四、Nginx模块
4.1 安装方式
4.1.1 方式一 yum安装
#安装依赖包
yum install -y epel-releas
#yum方式安装
yum install -y nginx
4.1.2 方式二 编译安装 (推荐使用)
1)前置准备
#安装依赖包
yum -y install gcc pcre-devel openssl-devel zlib-devel openssl openssl-devel
#新建nginx用户便于管理
useradd -M -s /sbin/nologin nginx
#官网下载包
wget http://nginx.org/download/nginx-1.18.0.tar.gz
2)编译安装nginx
tar xf nginx-1.18.0.tar.gz
mkdir /apps/nginx -p
cd nginx-1.18.0/
./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#加权限
ln -s /apps/nginx/sbin/nginx /usr/sbin/ #直接启动 不需要绝对路径
3)nginx开机自启(可选)
vim /usr/lib/systemd/system/nginx.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
#注意启动文件位置
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
#重新加载配置
systemctl enable --now nginx
#开机自启并立即启动 如果卡主是应为logs下有 nginx.pid 文件 删除即可
chown -R nginx.nginx /apps/nginx
#修改权限
###如果需要修改pid文件可以执行以下操作#################
mkdir /apps/nginx/run/
#创建目录
vim /apps/nginx/conf/nginx.conf
#修改配置文件
pid /apps/nginx/run/nginx.pid;
#找到 pid的位置修改
4.2 Nginx命令 常用选项
#基本格式
nginx [选项] [参数]
4.2.1 常用选项
选项 | 功能 |
---|---|
-c <配置文件> | 指定一个自定义的配置文件路径 |
-g <全局配置> | 在命令行中指定全局配置选项 |
-p <工作目录> | 设置工作目录,用于存放日志文件和临时文件 |
-s <信号> | 向nginx发送信号,常用的有stop (停止nginx进程)和reload (重新加载配置文件) |
-t | 测试配置文件语法是否正确 |
-q | 在测试配置文件时,以静默模式运行,只输出关键信息 |
-V | 显示nginx的版本、编译信息和配置参数 |
-h | 显示帮助信息,包括所有可用的命令行选项 |
-s <文件> | 启动nginx并将master进程的PID写入指定的文件 |
-e <错误日志文件> | 设置错误日志文件的路径 |
-g <配置指令> | 设置全局配置指令。可以在命令行中设置多个全局配置指令,用分号分隔 |
-T | 测试配置文件,并打印出解析后的配置内容 |
-q <文件> | 检查配置文件,并打印出解析后的配置内容,但不启动nginx |
4.2.2 信号
#基本格式
nginx -s 信号
信号 | 描述 |
---|---|
stop | 快速停止nginx进程,可能会中断现有连接。 |
quit | 优雅地停止nginx进程,等待现有连接完成后再停止。 |
reload | 重新加载配置文件,优雅地应用新配置,不中断现有连接。 |
reopen | 重新打开日志文件,用于日志切割或日志重定向。 |
term | 快速停止nginx进程,可能会中断现有连接,与stop 信号类似。 |
usr1 | 重新打开日志文件,用于日志切割或日志重定向,与reopen 信号类似。 |
usr2 | 平滑地升级nginx可执行文件。 |
hup | 重新加载配置文件,优雅地应用新配置,与reload 信号类似。 |
winch | 当nginx以master/worker工作模式运行时,重新生成worker进程以适应新的配置。 |
usr3 | 向worker进程发送自定义信号。 |
4.3 日志分割(Nginx 优化 )
cd /apps/nginx/logs #移动到日志所在目录下,此目录为指定安装目录,默认目录为/var/log/nginx
mv access.log access.log.bak #备份日志文件
touch access.log #建空的日志文件
pid=`cat /apps/nginx/logs/nginx.pid` #查看nginx的pid
kill -s USR1 $pid
或者
nginx -s reopen #重新打开Nginx进程以重新加载配置文件
会发送信号给Nginx主进程,告诉它重新加载配置文件而不停止正在处理的连接(不停止Nginx服务)
4.4 升级nginx
4.4.1 思路
- 将旧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
4.4.2 平滑升级nginx
nginx1.18---->nginx1.20
#关闭防火墙
systemctl stop firewalld
setenforce 0
#启动服务
systemctl start nginx
#下载安装包到src目录
wget https://nginx.org/download/nginx-1.20.2.tar.gz -P \
/usr/local/src/
cd /usr/local/src/;ls
tar xf nginx-1.20.2.tar.gz
cd nginx-1.20.2/;ls
重新编译安装
#检测编译环境 加模块
./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
nginx -V#查看版本
mv /apps/nginx/sbin/nginx /apps/nginx/sbin/nginx.bak
#将低版本的nginx主程序改名
cp /usr/local/src/nginx-1.20.2/objs/nginx /apps/nginx/sbin
#将新版本 拷入进去
/apps/nginx/sbin/nginx -t
#语法检查
kill -USR2 `cat /apps/nginx/logs/nginx.pid`
ps auxf|grep nginx
#会生成新的master进程,需要结束旧的
#创建一个无用的填充文件,用于让测试客户端下载
dd if=/dev/zero of=/apps/nginx/html/m.img bs=1G count=10
cd /apps/nginx/html;ls
切换到客户端下载测试包
#192.168.2.100为服务端IP地址
#从服务端下载m.img,观察进程
wget --limit-rate=1M http://192.168.2.100/m.img
返回服务端
#查看master process pid文件路径
ls /apps/nginx/logs/
cat /apps/nginx/los/nginx.pid #1.20.2版本的
cat /apps/nginx/los/nginx.pid.oldbin #1.18版本的
kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin`
#优雅关闭 旧版本的master process
开启新的客户机,从服务端获取测试包
wget --limit-rate=1M http://192.168.2.100/m.img
然后返回服务端查看是否使用新进程
ss -natp | grep 80
pstree -p |grep nginx
4.5 退回旧版本(回滚)
#唤起旧版本的主进程
kill -HUP `cat /apps/nginx/logs/nginx.pid.oldbin`
#观察进程
ps aux|grep nginx
#结束新版本的master进程
kill -QUIT `cat /apps/nginx/logs/nginx.pid`
ps aux | grep nginx
curl -I 127.1
#通过 curl 发送一个 HEAD 请求到本地服务器并返回响应头信息