目录
一、Web服务
1.1 web服务访问流程
1.2 Web服务
1.2.1 Web服务器分类
Web服务分为Apache和Nginx
1.2.2 Apache经典的Web服务器
1.2.2.1 Apache介绍
- Apache HTTP Server(简称Apache)是Apache软件基金会的一个开放源码的网页服务器,可以在大多数计算机操作系统中运行。
- Apache是世界使用排名第一的Web服务器软件,它可以运行在几乎所有广泛使用的计算机平台上。
- 由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一,也叫网页服务器软件 。
- 它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。
1.2.2.2 Apache三种工作模式
Apache一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块)模式。分别是Prefork、Worker、Event
1.Prefork MPM
Prefork MPM实现了一个非线程的、预派生的web服务器。它在Apache启动之初,就先预派生一些子进程,然后等待连接;可以减少频繁创建和销毁进程的开销,每个子进程只有一个线程,在一个时间点内,只能处理一个请求。这是一个成熟稳定,可以兼容新老模块,也不需要担心线程安全问题,但是一个进程相对占用资源,消耗大量内存,不擅长处理高并发的场景。
优点:稳定
缺点: 每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
2.Worker MPM
和prefork模式相比,worker使用了多进程和多线程的混合模式,worker模式也同样会先预派生一些子进程,然后每个子进程创建一些线程,同时包括一个监听线程,每个请求过来会被分配到一个线程来服务。线程比起进程会更轻量,因为线程是通过共享父进程的内存空间,因此,内存的占用会减少一些,在高并发的场景下会比prefork有更多可用的线程,表现会更优秀一些;另外,如果一个线程出现了问题也会导致同一进程下的线程出现问题,如果是多个线程出现问题,也只是影响Apache的一部分,而不是全部。由于用到多进程多线程,需要考虑到线程的安全了,在使用keep-alive长连接的时候,某个线程会一直被占用,即使中间没有请求,需要等待到超时才会被释放(该问题在prefork模式下也存在)。
优点:相比prefork占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长链接方式,某个线程会一直占据,即使没有传输数据,也需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在prefork模式下,同样会发生)
3.event MPM
这是Apache最新的工作模式,它和worker模式很像,不同的是在于它解决了keep-alive长连接的时候占用线程资源被浪费的问题,在event工作模式中,会有一些专门的线程用来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务器的线程,执行完毕后,又允许它释放。这增强了在高并发场景下的请求处理。
优点: 单线程响应请求多,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keepalive类型的线程,当真是请求的时候,将请求传递给服务线程,执行完毕后,有允许它释放
缺点:没有线程安全控制
1.2.3 Nginx——高性能web服务
1.什么是nginx?
NGINX 是一个开源的 Web 服务器和反向代理服务器,它使用 Nginx 作为 Web 服务器和反向代理服务器的原因是它拥有高性能、可扩展性和可靠性。它可以处理大量的并发连接,并且可以缓存 HTTP 请求以提高性能。
2.工作原理
NGINX是由俄罗斯一名程序员开发,于2020年12月15日正式发布公开版本,其工作原理是将 HTTP 请求转发到服务器,然后将响应返回给用户。它可以通过配置来支持缓存、SSL 终止、负载均衡等功能。NGINX 可以运行在多种操作系统上,如 Linux、Windows 等。
3.Nginx功能
- 负载均衡:NGINX 可以通过轮询、加权轮询、最小连接数等方法对传入的请求进行负载均衡。
- 缓存:NGINX 可以缓存 HTTP 请求以提高性能,可以使用 Etag、If-None-Match 等指令来缓存请求。
- SSL 终止:NGINX 可以终止 HTTPS 请求并将其转换为 HTTP 请求,以便可以将其传递给 Web 服务器。
- 反向代理:NGINX 可以充当 Web 服务器和客户端之间的代理,将请求转发到服务器,并将响应返回给客户端。
- 路由:NGINX 可以根据 URL 将请求转发到不同的服务器,也可以根据请求的参数、状态码等来路由请求。
1.2.4 apache和nginx对比
Nginx
- 轻量级,采用 C 进行编写,同样的 web 服务,会占用更少的内存及资源
- 抗并发,nginx 以 epoll and kqueue 作为开发模型,处理请求是异步非阻塞的,负载能力比 apache 高很多,而 apache 则是阻塞型的。在高并发下 nginx 能保持低资源低消耗高性能 ,而 apache 在 PHP 处理慢或者前端压力很大的情况下,很容易出现进程数飙升,从而拒绝服务的现象。
- nginx 处理静态文件好,静态处理性能比 apache 高三倍以上
- nginx 的设计高度模块化,编写模块相对简单
- nginx 配置简洁,正则配置让很多事情变得简单,而且改完配置能使用 -t 测试配置有没有问题,apache 配置复杂 ,重启的时候发现配置出错了,会很崩溃
- nginx 作为负载均衡服务器,支持 7 层负载均衡
- nginx 本身就是一个反向代理服务器,而且可以作为非常优秀的邮件代理服务器
- 启动特别容易, 并且几乎可以做到 7*24 不间断运行,即使运行数个月也不需要重新启动,还能够不间断服务的情况下进行软件版本的升级
- 社区活跃,各种高性能模块出品迅速
Apache
- apache 的 rewrite 比 nginx 强大,在 rewrite 频繁的情况下,用 apache
- apache 发展到现在,模块超多,基本想到的都可以找到
- apache 更为成熟,少 bug ,nginx 的 bug 相对较多
- apache 超稳定
- apache 对 PHP 支持比较简单,nginx 需要配合其他后端用
- apache 在处理动态请求有优势,nginx 在这方面是鸡肋,一般动态请求要 apache 去做,nginx 适合静态和反向。
- apache 仍然是目前的主流,拥有丰富的特性,成熟的技术和开发社区
1.2.5 正向代理与反向代理
正向代理
正向代理(forward proxy):是一个位于客户端和目标服务器之间的服务器(代理服务器),为了从目标服务器取得内容,客户端向代理服务器发送一个请求并指定目标,然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。
正向代理,其实是"代理服务器"代理了"客户端",去和"目标服务器"进行交互。
反向代理
反向代理(reverse proxy):是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
反向代理,其实是"代理服务器"代理了"目标服务器",去和"客户端"进行交互。
例如,有时候,用户想要访问某国外网站,该网站无法在国内直接访问,但是我们可以访问到一个代理服务器,这个代理服务器可以访问到这个国外网站。这样呢,用户对该国外网站的访问就需要通过代理服务器来转发请求,并且该代理服务器也会将请求的响应再返回给用户。这个上网的过程就是用到了正向代理。
二、IO模型
2.1 服务端I/O
- 磁盘I/O
- 网络I/O : 一切皆文件,本质为对socket文件的读写
2.1.1 磁盘I/O
2.1.2 网络I/O
- 获取请求数据,客户端与服务器建立连接发出请求,服务器接受请求
- 构建响应,当服务器接收完请求,并在用户空间处理客户端的请求,直到构建响应完成
- 返回数据,服务器将已构建好的响应再通过内核空间的网络 I/O 发还给客户端
2.2 I/O模型
2.2.1 I/O模型相关概念
同步 / 异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状态的通知。
- 同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事 情是否处理完成
- 异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
- 阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂起,干不了别的事情。
- 非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完 成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
2.2.2 网络I/O模型
2.2.2.1 阻塞型I/O

- 优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源
- 缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销较apache 的preforck使用的是这种模式。
- 同步阻塞:程序向内核发送I/O请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进程将一直等待并不再接受新的请求,并由进程轮询查看I/O是否完成,完成后进程将I/O结果返回给Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看I/O是否完成,这种方式简单,但是比较慢,用的比较少。
2.2.2.2 非阻塞I/O模型
2.2.2.3 多路复用I/O

优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程 ( 每个文件描述符一个线程) ,这样可以大大节省系统资源缺点:当连接数较少时效率相比多线程 + 阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理需要 2 次系统调用,占用时间会有增加
IO多路复用适用如下场合:
当客户端处理多个描述符时(一般是交互式输入和网络套接口),必须使用 I/O 复用当一个客户端同时处理多个套接字时,此情况可能的但很少出现当一个服务器既要处理监听套接字,又要处理已连接套接字,一般也要用到 I/O 复用当一个服务器即要处理 TCP ,又要处理 UDP ,一般要使用 I/O 复用当一个服务器要处理多个服务或多个协议,一般要使用 I/O 复用
2.2.2.4 信号驱动式I/O模型
优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此可以提高资源的利用率缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知
2.2.2.5 异步I/O模型
优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠缺点:要实现真正的异步 I/O ,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的异步 I/O ,在 Linux 系统下, Linux 2.6 才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编程时以 IO 复用模型模式 + 多线程任务的架构基本可以满足需求
三、nginx安装
3.1 安装
1.下载软件包
官方源码包下载地址
wget https://nginx.org/download/nginx-1.26.1.tar.gz
获取到安装包
[root@nginx-node1 ~]# wget https://nginx.org/en/download.html/nginx-1.24.0.tar.gz
解压安装包
[root@nginx-node1 ~]# tar -xzvf nginx-1.24.0.tar.gz
安装源码编译与nginx依赖的库
[root@nginx-node1 ~]# dnf install -y gcc pcre-devel zlib-devel openssl-devel
配置/检测
[root@nginx-node1 ~]# cd nginx-1.24.0
[root@nginx-node1 nginx-1.24.0]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module
# 生成了Makefile和objs
[root@nginx-node1 nginx-1.24.0]# ls
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
编译
[root@nginx-node1 nginx-1.24.0]# make
安装
生成相关的软件存放目录和配置文件
[root@nginx-node1 nginx-1.24.0]# make install
# 在make install之前,没有该文件
[root@nginx-node1 nginx-1.24.0]# ls /usr/local/nginx/
conf html logs sbin
将启动文件,复制到工作目录下的启动文件夹下
[root@nginx-node1 objs]# \cp -f nginx /usr/local/nginx/sbin/
[root@nginx-node1 objs]# ls /usr/local/nginx/sbin/
nginx
创建用户
[root@nginx-node1 ~]# useradd -s /sbin/nologin -M nginx
[root@nginx-node1 ~]# id nginx
uid=1001(nginx) gid=1001(nginx) groups=1001(nginx)
启动nginx
[root@nginx-node1 ~]# cd /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# ./nginx
[root@nginx-node1 sbin]# ps aux | grep nginx
root 40234 0.0 0.0 9836 928 ? Ss 23:38 0:00 nginx: master process nginx
nginx 40235 0.0 0.1 13696 4792 ? S 23:38 0:00 nginx: worker process
root 40237 0.0 0.0 221668 2424 pts/2 S+ 23:38 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# nginx -s stop
[root@nginx-node1 sbin]# ps aux | grep nginx
root 40248 0.0 0.0 221668 2320 pts/2 S+ 23:52 0:00 grep --color=auto nginx
设置环境变量,可以直接使用nginx
[root@nginx-node1 ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@nginx-node1 ~]# source ~/.bash_profile
3.2 nginx开机自启
[root@nginx-node1 ~]# vim /lib/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=syslog.target network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
[Install]
WantedBy=multi-user.target
[root@nginx-node1 ~]# systemctl daemon-reload
# 就可以使用systemctl命令了
[root@nginx-node1 ~]# systemctl restart nginx
3.3 平滑升级
1.下载源码包
[root@nginx-node1 ~]# wget https://nginx.org/download/nginx-1.26.1.tar.gz
2.解压
[root@nginx-node1 ~]# tar -xzvf nginx-1.26.1.tar.gz
[root@nginx-node1 ~]# tar -xzvf echo-nginx-module-0.63.tar.gz
3.配置/检测
[root@nginx-node1 ~]# cd nginx-1.26.1
# 添加了echo-nginx-module-0.63模块
[root@nginx-node1 nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module --add-module=/root/echo-nginx-module-0.63
4.编译
[root@nginx-node1 nginx-1.26.1]# make
# 不需要再make install,刚刚已经安装过了
5.将老的nginx替换成新的nginx
[root@nginx-node1 nginx-1.26.1]# cd /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# cp nginx nginx.old
[root@nginx-node1 sbin]# cd /root/nginx-1.26.1/objs/
# -f 强制覆盖
[root@nginx-node1 objs]# \cp -f nginx /usr/local/nginx/sbin/
6.
[root@nginx-node1 sbin]# ps aux | grep nginx
root 47359 0.0 0.0 9864 932 ? Ss 16:30 0:00 nginx: master process nginx
nginx 47360 0.0 0.1 13736 4820 ? S 16:30 0:00 nginx: worker process
root 47362 0.0 0.0 221668 2260 pts/1 S+ 16:30 0:00 grep --color=auto nginx
[root@nginx-node1 ~]# curl -I 172.25.254.100
HTTP/1.1 200 OK
Server: nginx/1.24.0
Date: Fri, 16 Aug 2024 16:19:37 GMT
Content-Type: text/html
Content-Length: 615
Last-Modified: Fri, 16 Aug 2024 15:19:47 GMT
Connection: keep-alive
ETag: "66bf6e13-267"
Accept-Ranges: bytes
启用新的进程
[root@nginx-node1 sbin]# kill -USR2 47359
[root@nginx-node1 sbin]# ps aux | grep nginx
root 47359 0.0 0.0 9864 2648 ? Ss 16:30 0:00 nginx: master process nginx
nginx 47360 0.0 0.1 13736 4820 ? S 16:30 0:00 nginx: worker process
root 47363 0.0 0.1 9864 6112 ? S 16:30 0:00 nginx: master process nginx
nginx 47364 0.0 0.1 13724 4812 ? S 16:30 0:00 nginx: worker process
root 47366 0.0 0.0 221668 2272 pts/1 S+ 16:30 0:00 grep --color=auto nginx
停止老进程
[root@nginx-node1 sbin]# kill -WINCH 47359
[root@nginx-node1 sbin]# ps aux | grep nginx
root 47359 0.0 0.0 9864 2648 ? Ss 16:30 0:00 nginx: master process nginx
root 47363 0.0 0.1 9864 6480 ? S 16:30 0:00 nginx: master process nginx
nginx 47372 0.0 0.1 13756 4840 ? S 16:37 0:00 nginx: worker process
root 47382 0.0 0.0 221668 2272 pts/1 S+ 16:46 0:00 grep --color=auto nginx
如果版本升级后,没有任何问题,需要关闭老的master进程的话,就可以使用
[root@nginx-node1 sbin]# kill -9 47359
查看版本号
[root@nginx-node1 sbin]# nginx -v
nginx version: nginx/1.26.1
3.4 回滚
[root@nginx-node1 sbin]# kill -HUP 47359
[root@nginx-node1 sbin]# ps aux | grep nginx
root 47359 0.0 0.0 9864 2648 ? Ss 16:30 0:00 nginx: master process nginx
root 47363 0.0 0.1 9864 6480 ? S 16:30 0:00 nginx: master process nginx
nginx 47372 0.0 0.1 13756 5308 ? S 16:37 0:00 nginx: worker process
nginx 47400 0.0 0.1 13736 4824 ? S 16:58 0:00 nginx: worker process
root 47402 0.0 0.0 221668 2264 pts/1 S+ 16:58 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# kill -WINCH 47363
[root@nginx-node1 sbin]# ps aux | grep nginx
root 47359 0.0 0.0 9864 2648 ? Ss 16:30 0:00 nginx: master process nginx
root 47363 0.0 0.1 9864 6480 ? S 16:30 0:00 nginx: master process nginx
nginx 47400 0.0 0.1 13736 4824 ? S 16:58 0:00 nginx: worker process
root 47417 0.0 0.0 221668 2424 pts/1 S+ 17:02 0:00 grep --color=auto nginx
[root@nginx-node1 sbin]# mv nginx nginx.new
[root@nginx-node1 sbin]# mv nginx.old nginx
[root@nginx-node1 sbin]# ls
nginx nginx.new
[root@nginx-node1 sbin]# nginx -v
nginx version: nginx/1.24.0
3.6 nginx全局配置
[root@nginx-node1 ~]# nginx -s stop
[root@nginx-node1 ~]# ps aux | grep nginx
root 47780 0.0 0.0 221668 2324 pts/1 S+ 18:12 0:00 grep --color=auto nginx
[root@nginx-node1 ~]# nginx -g "worker_processes 5;"
[root@nginx-node1 ~]# ps aux | grep nginx
root 47783 0.0 0.0 9836 924 ? Ss 18:12 0:00 nginx: master process nginx -g worker_processes 5;
nginx 47784 4.5 1.2 54680 45720 ? S 18:12 0:00 nginx: worker process
nginx 47785 2.5 1.2 54680 45780 ? S 18:12 0:00 nginx: worker process
nginx 47786 0.0 1.2 54680 45692 ? S 18:12 0:00 nginx: worker process
nginx 47787 20.0 1.2 54680 45776 ? S 18:12 0:00 nginx: worker process
nginx 47788 21.0 1.2 54680 45800 ? S 18:12 0:00 nginx: worker process
root 47790 0.0 0.0 221668 2272 pts/1 S+ 18:13 0:00 grep --color=auto nginx
nginx高并发测试
Linux并发测试工具
[root@nginx-node1 ~]# yum install -y http-tools
#例如
ab -n 请求次数 -c 并发数 访问地址ab -n 1000 -c 100 https://www.baidu.com/ 表请求1000次中有100并发
[root@nginx-node1 ~]# vim /etc/security/limits.conf
nginx - nofile 100000
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
events {
worker_connections 100000;
use epoll;
}
[root@nginx-node1 ~]# sudo -u nginx ulimit -a
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 14546
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 100000
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 14546
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
[root@nginx-node1 ~]# ab -c 10000 -n 10000 http://172.25.254.100/index.html
3.7 创建PC web站点
[root@nginx-node1 ~]# mkdir /usr/local/nginx/conf.d
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
include "/usr/local/nginx/conf.d/*.conf";
}
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
root /data/web/html;
index index.html;
}
[root@nginx-node1 ~]# mkdir -p /data/web/html
[root@nginx-node1 ~]# echo www.lm.org > /data/web/html/index.html
[root@nginx-node1 ~]# nginx -s reload
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100 www.lm.org
[root@nginx-node1 ~]# curl www.lm.org
www.lm.org
3.8 location用法
= #用于标准 uri 前,需要请求字串与 uri 精确匹配,大小敏感 , 如果匹配成功就停止向下匹配并立即处理请求^~ #用于标准 uri 前,表示包含正则表达式 , 并且匹配以指定的正则表达式开头#对 uri 的最左边部分做匹配检查,不区分字符大小写~ #用于标准 uri 前,表示包含正则表达式 , 并且区分大小写~* #用于标准 uri 前,表示包含正则表达式 , 并且不区分大写不带符号 # 匹配起始于此 uri 的所有的 uri\ #用于标准 uri 前,表示包含正则表达式并且转义字符。可以将 . * ? 等转义为普通符号对目录匹配优先级:(~* = ~)> 不带符号 > ^~ > =对文件匹配优先级:= > (~* = ~) > 不带符号 > ^~
3.9 用户认证
[root@nginx-node1 ~]# htpasswd -cm /usr/local/nginx/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
[root@nginx-node1 ~]# htpasswd -m /usr/local/nginx/.htpasswd lm
New password:
Re-type new password:
Adding password for user lm
[root@nginx-node1 ~]# cat /usr/local/nginx/.htpasswd
admin:$apr1$yujc3BhF$8olV5TU375/3yXNV4Jfbf0
lm:$apr1$DB.oxbHz$NdHo3q5q7Gtiw4FwxKUXw1
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
root /data/web/html;
index index.html;
location /lm {
root /data/web;
auth_basic "login password!";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
}
[root@nginx-node1 ~]# systemctl restart nginx
3.10 自定义错误页面
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
root /data/web/html;
index index.html;
error_page 404 /40x.html;
location /lm {
root /data/web;
auth_basic "login password!";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
}
[root@nginx-node1 ~]# mkdir -p /data/web/errorpage
[root@nginx-node1 ~]# echo error page > /data/web/errorpage/40x.html
[root@nginx-node1 ~]# systemctl restart nginx.service
测试
3.11 自定义错误日志
[root@nginx-node1 ~]# mkdir -p /var/log/lm.org
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
root /data/web/html;
index index.html;
error_page 404 /40x.html;
# 自定义错误日志
error_log /var/log/lm.org/error.log;
access_log /var/log/lm.org/access.log;
location /lm {
root /data/web;
auth_basic "login password!";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
# 自动生成文件
[root@nginx-node1 ~]# cat /var/log/lm.org/error.log
[root@nginx-node1 ~]# cat /var/log/lm.org/access.log
3.12 文件检测
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
root /data/web/html;
index index.html;
error_page 404 /40x.html;
error_log /var/log/lm.org/error.log;
access_log /var/log/lm.org/access.log;
# 检测文件
try_files $uri $uri.html $uri/index.html /erro/default.html;
location /lm {
root /data/web;
auth_basic "login password!";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
}
[root@nginx-node1 ~]# mkdir -p /data/web/html/error
[root@nginx-node1 ~]# echo error default > /data/web/html/error/default.html
3.13 长链接控制
下载长链接测试工具
[root@nginx-node1 ~]# yum install -y telnet
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
# 在一次长连接上所允许请求的资源的最大数量
keepalive_requests 2;
keepalive_timeout 65 60;
# 开启长连接后,返回客户端的会话保持时间为60s,单次长连接累计请求达到指定次数请求或65秒就会被断
开,第二个数字60为发送给客户端应答报文头部中显示的超时时间设置为60s:如不设置客户端将不显示超时时
间
}
[root@nginx-node1 ~]# telnet www.lm.org 80
Trying 172.25.254.100...
Connected to www.lm.org.
Escape character is '^]'.
GET / HTTP/1.1
HOST:www.lm.org
# 回车
3.14 下载服务器
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
root /data/web/html;
index index.html;
error_page 404 /40x.html;
error_log /var/log/lm.org/error.log;
access_log /var/log/lm.org/access.log;
try_files $uri $uri.html $uri/index.html /error/default.html;
location /lm {
root /data/web;
auth_basic "login password !";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
location /download {
root /data/web;
# 自动文件索引功能
autoindex on;
# 打开本地时间
autoindex_localtime on;
# 改变存储的的那欸
autoindex_exact_size off;
# 限制下载速度
limit_rate 1024k;
}
}
四、高级设置
4.1 状态页
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/status.conf
server {
listen 80;
server_name status.lm.org;
root /data/web/html;
index index.html;
location /status {
stub_status;
allow 172.25.254.1;
deny all;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
4.2 压缩
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
http {
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_http_version 1.1;
gzip_vary on;
gzip_types text/plain application/javascript application/x-javascript text/css
application/xml text/javascript application/x-httpd-php image/gif image/png;
include "/usr/local/nginx/conf.d/*.conf";
server {.....}
}
[root@nginx-node1 ~]# systemctl restart ngixn
[root@nginx-node1 ~]# du -sh /usr/local/nginx/logs/access.log
4.1M /usr/local/nginx/logs/access.log
[root@nginx-node1 ~]# cat /usr/local/nginx/logs/error.log > /data/web/html/small.html
[root@nginx-node1 ~]# cat /usr/local/nginx/logs/access.log > /data/web/html/big.html
4.3 nginx变量
4.3.1 内置变量
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vars.conf
server {
listen 80;
server_name var.lm.org;
root /data/web/html;
index index.html;
location /var {
echo $remote_addr;
echo $args;
echo $is_args;
echo $document_root;
echo $document_uri;
echo $host;
echo $remote_port;
echo $remote_user;
echo $request_method;
echo $request_filename;
echo $request_uri;
echo $scheme;
echo $server_protocol;
echo $server_addr;
echo $server_name;
echo $server_port;
echo $http_user_agent;
echo $http_cookie;
echo $cookie_key2;
}
}
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100 var.lm.org
[root@nginx-node1 ~]# systemctl restart nginx
# -b设置cookie值,-u指定用户
[root@nginx-node1 ~]# curl -b "key1=lm,key2=lm1" -u lm:redhat var.lm.org/var?name=lm&&id=6666
172.25.254.100
name=lm
?
/data/web/html
/var
var.lm.org
44136
lm
GET
/data/web/html/var
/var?name=lm
http
HTTP/1.1
172.25.254.100
var.lm.org
80
curl/7.76.1
key1=lm,key2=lm1
lm1
4.3.2 自定义变量
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/set-var.conf
server {
listen 80;
server_name set.lm.org;
root /data/web/html;
index index.html;
location /var {
default_type text/html;
set $lm lm;
echo $lm;
}
}
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100 set.lm.org
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# curl set.lm.org/var
lm
五、
if
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/if.conf
server {
listen 80;
server_name if.lm.org;
root /data/web/html;
index index.html;
location /test2 {
if ( !-e $request_filename ) {
echo "$request_filename is noe exist";
}
}
}
[root@nginx-node1 ~]# vim /etc/hosts
172.25.254.100 if.lm.org
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# curl if.lm.org/test2/
/data/web/html/test2/ is noe exist
五、rewrite
5.1 if、break、return
server {
listen 80;
server_name if.lm.org;
root /data/web/html;
index index.html;
location /test2 {
# 当前请求的资源文件的磁盘路径不存在
if ( !-e $request_filename ) {
echo "$request_filename is not exist";
}
}
location /break {
default_type text/html;
set $name lm;
echo $name;
if ( $http_user_agent = "curl/7.76.1" ) {
break;
}
set $id 666;
echo $id;
}
location /return {
default_type text/html;
if ( !-e $request_filename ) {
return 301 https://www.baidu.com;
}
echo "$request_filename is exist";
}
}
5.2 rewrite
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/if.conf
server {
listen 80;
server_name if.lm.org;
root /data/web/html;
index index.html;
location / {
root /data/web/var;
index index.html;
# 永久重定向301
rewrite / http://www.lm.com permanent;
# 临时重定向302
#rewrite / http://www.lm.com redirect;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
永久
临时
5.3 break和last
[root@nginx-node1 ~]# mkdir /data/web/html/{test1,test2,break,last} -p
[root@nginx-node1 ~]# echo test1 > /data/web/html/test1/index.html
[root@nginx-node1 ~]# echo test2 > /data/web/html/test2/index.html
[root@nginx-node1 ~]# echo last > /data/web/html/last/index.html
[root@nginx-node1 ~]# echo break > /data/web/html/break/index.html
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.lm.org;
root /data/web/html;
index index.html;
location /break {
rewrite ^/break/(.*) /test1/$1;
rewrite ^/test1/(.*) /test2/$1;
}
location /last {
rewrite ^/last/(.*) /test1/$1;
rewrite ^/test1/(.*) /test2/$1;
}
location /test1 {
default_type text/html;
return 666 "ahahahahahahahah";
}
location /test2 {
root /data/web/html;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/var.conf
server {
listen 80;
server_name var.lm.org;
root /data/web/html;
index index.html;
location /break {
rewrite ^/break/(.*) /test1/$1 break;
rewrite ^/test1/(.*) /test2/$1;
}
location /last {
rewrite ^/last/(.*) /test1/$1 last;
rewrite ^/test1/(.*) /test2/$1;
}
location /test1 {
default_type text/html;
return 666 "ahahahahahahahah";
}
location /test2 {
root /data/web/html;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
5.4 全站加密
[root@nginx-node1 ~]# cd /usr/local/nginx/
[root@nginx-node1 nginx]# ls
client_body_temp conf.d html proxy_temp scgi_temp
conf fastcgi_temp logs sbin uwsgi_temp
[root@nginx-node1 nginx]# mkdir certs
[root@nginx-node1 nginx]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout /usr/local/nginx/certs/lm.org.key -x509 -days 365 -out /usr/local/nginx/certs/lm.org.crt
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
listen 443 ssl;
server_name www.lm.org;
root /data/web/html;
index index.html;
ssl_certificate /usr/local/nginx/certs/lm.org.crt;
ssl_certificate_key /usr/local/nginx/certs/lm.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location / {
# 当使用http时,强制访问https
if ( $scheme = http ){
rewrite /(.*) https://$host/$1 redirect;
}
# 判断文件是否存在
if ( !-e $request_filename ) {
rewrite /(.*) https://$host/index.html redirect;
}
}
}
[root@nginx-node1 ~]# systemctl restart nginx;
5.5 防盗链
盗链
server {
listen 80;
listen 443 ssl;
server_name www.lm.org;
root /data/web/html;
index index.html;
ssl_certificate /usr/local/nginx/certs/lm.org.crt;
ssl_certificate_key /usr/local/nginx/certs/lm.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location /images {
root /data/web/html;
}
}
防盗
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
listen 443 ssl;
server_name www.lm.org;
root /data/web/html;
index index.html;
ssl_certificate /usr/local/nginx/certs/lm.org.crt;
ssl_certificate_key /usr/local/nginx/certs/lm.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# 全站防盗链
#location / {
# valid_referers none blocked server_names *.lm.org ~/.baidu/. ;
# if ( $invalid_referer ) {
# return 404;
# }
#}
location /images {
valid_referers none blocked server_names *.lm.org ~/.baidu/. ;
if ( $invalid_referer ) {
rewrite ^/ http://www.lm.org/t2.JPG;
}
}
}
[root@nginx-node1 ~]# systemctl restart nginx
六、反向代理
6.1 反向代理
6.1.1动静分离
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
location ~ \.php$ {
proxy_pass http://172.25.254.10:80;
}
location /static {
proxy_pass http://172.25.254.20:8080;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
[root@web10 ~]# yum install -y httpd
[root@web10 ~]# dnf install -y php
[root@web10 ~]# systemctl start httpd
[root@web10 ~]# vim /var/www/html/index.php
<?php
phpinfo();
?>
[root@web10 ~]# systemctl restart httpd
[root@web20 ~]# yum install -y httpd
[root@web20 ~]# systemctl start httpd
[root@web20 ~]# mkdir -p /var/www/html/static
[root@web20 ~]# echo 172.25.254.20 > /var/www/html/index.html
[root@web20 ~]# echo static 172.25.254.20 > /var/www/html/static/index.html
[root@web20 ~]# vim /etc/httpd/conf/httpd.conf
[root@web20 ~]# systemctl restart httpd
测试
6.1.2 缓存
压测:
[root@nginx-node1 ~]# ab -n1000 -c100 http://www.lm.org/static/index.html
缓存
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120s max_size=1g;
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.lm.org;
location ~ \.php$ {
proxy_pass http://172.25.254.10:80;
}
location /static {
proxy_pass http://172.25.254.20:8080;
proxy_cache proxycache;
proxy_cache_key $request_uri;
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 1m;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
压测:
[root@nginx-node1 ~]# ab -n1000 -c100 http://www.lm.org/static/index.html
6.2 实现Nginx四层负载
6.2.1 http反向代理
6.2.1.1 基础
[root@nginx-node1 ~]# vim /usr/local/nginx/conf.d/vhost.conf
upstream webcluster {
server 172.25.254.10:80 fail_timeout=15s max_fails=3;
server 172.25.254.20:8080 fail_timeout=15s max_fails=3;
server 172.25.254.100:80 backup;
}
server {
listen 80;
server_name www.lm.org;
location / {
proxy_pass http://webcluster;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
测试
原因:nat模式
6.2.1.2 uri哈希
6.2.1.3 cookie值哈希
6.2.2 四层负载均衡
6.2.2.1 upd负载均衡:DNS
web10与web20配置DNS服务
[root@web10 ~]# yum install -y bind
[root@web10 named]# cp named.localhost lm.org.zone -p
20主机
[root@web20 ~]# yum install -y bind
nginx主机
[root@nginx-node1 ~]# vim /usr/local/nginx/conf/nginx.conf
[root@nginx-node1 ~]# mkdir -p /usr/local/nginx/tcpconf.d
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# vim /usr/local/nginx/tcpconf.d/dns.conf
stream {
upstream dns {
server 172.25.254.10:53 fail_timeout=15s max_fails=3;
server 172.25.254.20:53 fail_timeout=15s max_fails=3;
}
server {
listen 53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}
}
[root@nginx-node1 ~]# systemctl restart nginx
6.2.2.2 tcp负载均衡:MySQL
[root@web10 ~]# yum install -y mariadb-server
[root@web20 ~]# yum install -y mariadb-server
nginx主机
[root@nginx-node1 ~]# vim /usr/local/nginx/tcpconf.d/dns.conf
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# systemctl restart nginx
[root@nginx-node1 ~]# yum install -y mariadb
6.3 FastCGI
6.3.1 CGI的由来
最早的 Web 服务器只能简单地响应浏览器发来的 HTTP 请求,并将存储在服务器上的 HTML 文件返回给浏 览器,也就是静态html 文件,但是后期随着网站功能增多网站开发也越来越复杂,以至于出现动态技 术,比如像php(1995 年 ) 、 java(1995) 、 python(1991) 语言开发的网站,但是 nginx/apache 服务器并不能直接运行 php 、 java 这样的文件, apache 实现的方式是打补丁,但是 nginx 缺通过与第三方基于协议实现,即通过某种特定协议将客户端请求转发给第三方服务处理,第三方服务器会新建新的进程处理用户的请求,处理完成后返回数据给Nginx 并回收进程,最后 nginx 在返回给客户端,那这个约定就是通用网关接口(common gateway interface ,简称 CGI) , CGI (协议) 是 web 服务器和外部应用程序之间的接口标准,是cgi 程序和 web 服务器之间传递信息的标准化接口。
6.3.2 为什么会有FastCGI?
CGI 协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低,因为 Web Server每收到一个请求都会创建一个CGI 进程, PHP 解析器都会解析 php.ini 文件,初始化环境,请求结束的时候再关闭进程,对于每一个创建的CGI 进程都会执行这些操作,所以效率很低,而 FastCGI 是用来提高 CGI 性 能的,FastCGI 每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请 求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。
6.3.3 什么是PHP-FPM?
PHP-FPM(FastCGI Process Manager :
- FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
- 进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server
- 的请求
- worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
6.3.4 Nginx源码安装
1.下载源码包
[root@nginx-node1 ~]# wget https://nginx.org/download/nginx-1.26.1.tar.gz
2.解压源码包
[root@nginx-node1 ~]# tar xzvf nginx-1.26.1.tar.gz
3.获取模块
解压命令
[root@nginx-node1 ~]# tar xvzf echo-nginx-module-0.63.tar.gz
[root@nginx-node1 ~]# tar xvf memc-nginx-module-0.20.tar.gz
[root@nginx-node1 ~]# tar xvf srcache-nginx-module-0.33.tar.gz
4.下载nginx需要的依赖
[root@nginx-node1 ~]# dnf install gcc pcre-devel zlib-devel openssl-devel -y
3.检测/配置
[root@nginx-node1 ~]# cd nginx-1.26.1/
[root@nginx-node1 nginx-1.26.1]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_gzip_static_module --with-http_stub_status_module --with-pcre --with-stream --with-stream_ssl_module --add-module=/root/echo-nginx-module-0.63 --add-module=/root/srcache-nginx-module-0.33 --add-module=/root/memc-nginx-module-0.20
4.编译和安装
[root@nginx-node1 nginx-1.26.1]# make && make install
5.启动
[root@nginx-node1 ~]# cd /usr/local/nginx/sbin/
[root@nginx-node1 sbin]# ls
nginx
[root@nginx-node1 sbin]# ./nginx
6.写入环境变量
[root@nginx-node1 ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/nginx/sbin
[root@nginx-node1 ~]# source ~/.bash_profile
[root@nginx-node1 ~]# nginx
7.创建用户
[root@nginx-node1 ~]# useradd -s /sbin/nologin -M nginx
6.3.5 PHP源码安装
1.获取onigurma
[root@nginx-node1 ~]# wget https://mirrors.aliyun.com/rockylinux/9.4/devel/x86_64/kickstart/Packages/o/oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm
[root@nginx-node1 ~]# yum install -y oniguruma-devel-6.9.6-1.el9.5.x86_64.rpm
2.下载其他依赖
[root@nginx-node1 ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel
3.解压需要的模块
4.解压PHP源码包
5.检测/配置
[root@nginx-node1 ~]# cd php-8.3.9/
[root@nginx-node1 php-8.3.9]# ./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx --with-curl --with-iconv --with-mhash --with-zlib --with-openssl --enable-mysqlnd --with-mysqli --with-pdo-mysql --disable-debug --enable-sockets --enable-soap --enable-xml --enable-ftp --enable-gd --enable-exif --enable-mbstring --enable-bcmath --with-fpm-systemd
6.编译和配置
[root@nginx-node1 php-8.3.9]# make && make install
7.php相关配置优化
(1)
(2)生成子配置文件
(3)
(4)生成启动文件
(5)设置环境变量
6.3.6 nginx反向代理负载均衡
测试:
6.3.7 PHP动态扩展模块(PHP的缓存模块)
目的:解决PHP性能差问题
1.安装memcache模块
[root@nginx-node1 ~]# tar xvf memcache-8.2
[root@nginx-node1 ~]# cd memcache-8.2/
[root@nginx-node1 memcache-8.2]# yum install -y autoconf
[root@nginx-node1 memcache-8.2]# phpize
Configuring for:
PHP Api Version: 20230831
Zend Module Api No: 20230831
Zend Extension Api No: 420230831
[root@nginx-node1 memcache-8.2]# ./configure && make && make install
2.复制测试文件到nginx发布目录
3.配置php加载memcache模块
[root@nginx-node1 ~]# vim /usr/local/php/etc/php.ini
[root@nginx-node1 ~]# systemctl reload php-fpm
4.部署memcached
测试
[root@nginx-node1 ~]# ab -n500 -c10 http://www.lm.org/example.php
6.3.8 php高速缓存
七、nignx二次开发
7.1 openresty
OpenResty(又称:ngx_openresty) 是一个基于 NGINX 的可伸缩的 Web 平台,由中国人章亦春发起,提供了很多高质量的第三方模块。
OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,更主要的是在性能方面,OpenResty可以 快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。
360,UPYUN,阿里云,新浪,腾讯网,去哪儿网,酷狗音乐等都是 OpenResty 的深度用户。
7.2 编译安装openresty
[root@nginx-node1 ~]# wget https://openresty.org/download/openresty-1.17.8.2.tar.gz
[root@nginx-node1 ~]# tar xzvf openresty-1.25.3.1.tar.gz
[root@nginx-node1 ~]# dnf install -y gcc pcre-devel openssl-devel perl
[root@nginx-node1 ~]# useradd -s /sbin/nologin -M nginx
# 检测/配置
[root@nginx-node1 ~]# cd openresty-1.25.3.1/
[root@nginx-node1 openresty-1.25.3.1]# ./configure --user=nginx --group=nginx --prefix=/usr/local/openresty --with-http_ssl_module --with-http_v2_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module --with-stream --without-pcre2 --with-stream_ssl_preread_module --with-http_realip_module
[root@nginx-node1 openresty-1.25.3.1]# gmake && gmake install
添加环境变量
[root@nginx-node1 bin]# vim ~/.bash_profile
[root@nginx-node1 bin]# source ~/.bash_profile
测试