一、Apache 经典的 Web 服务端
1.1 Apache prefork 模型
预派生模式,有一个主控制进程,然后生成多个子进程,使用select模型,最大并发1024
每个子进程有一个独立的线程响应用户请求
相对比较占用内存,但是比较稳定,可以设置最大和最小进程数
是最古老的一种模式,也是最稳定的模式,适用于访问量不是很大的场景
优点:稳定
缺点:每个用户请求需要对应开启一个进程,占用资源较多,并发性差,不适用于高并发场景
1.2 Apache worker 模型
一种多进程和多线程混合的模型
有一个控制进程,启动多个子进程
每个子进程里面包含固定的线程
使用线程程来处理请求
当线程不够使用的时候会再启动一个新的子进程,然后在进程里面再启动线程处理请求
由于其使用了线程处理请求,因此可以承受更高的并发
优点:相比prefork 占用的内存较少,可以同时处理更多的请求
缺点:使用keepalive的长连接方式,某个线程会一直被占据,即使没有传输数据,也需要一直等待到超 时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用(该问题在 prefork模式下,同样会发生)
1.3 Apache event模型
Apache中最新的模式,2012年发布的apache 2.4.X系列正式支持event 模型,属于事件驱动模型(epoll)
每个进程响应多个请求,在现在版本里的已经是稳定可用的模式
它和worker模式很像,最大的区别在于,它解决了keepalive场景下长期被占用的线程的资源浪费问题 (某些线程因为被keepalive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)
event MPM中,会有一个专门的线程来管理这些keepalive类型的线程
当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场 景下的请求处理能力
优点:单线程响应多请求,占据更少的内存,高并发下表现更优秀,会有一个专门的线程来管理keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放
缺点:没有线程安全控制
二、Nginx 架构和安装
2.1 Nginx 功能介绍
静态的web资源服务器html,图片,js,css,txt等静态资源
http/https协议的反向代理
结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
tcp/udp协议的请求转发(反向代理)
imap4/pop3协议的反向代理
2.2 Web 服务相关的功能
虚拟主机(server)
支持 keep-alive 和管道连接(利用一个连接做多次请求)
访问日志(支持基于日志缓冲提高其性能)
url rewirte
路径别名
基于IP及用户的访问控制
支持速率限制及并发数限制
重新配置和在线升级而无须中断客户的工作进程
2.3 Nginx 基础特性
模块化设计,较好的扩展性 高可靠性
支持热部署:不停机更新配置文件,升级版本,更换日志文件
低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
event-driven,aio,mmap,sendfile
2.4 Nginx 模块介绍
nginx 有多种模块
核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件 驱动机制 、进程管理等核心功能
标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置等等
可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持 Stream服务模块: 实现反向代理功能,包括TCP协议代理
第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支 持等
2.5Nginx 安装
官方源码包
[root@nginx ~]# tar zxf nginx-1.24.0.tar.gz
安装模块
[root@nginx nginx-1.24.0]# dnf install gcc pcre-devel zlib-devel openssl-devel -y
加载相应模块
[root@nginx nginx-1.24.0]# ./configure --prefix=/usr/local/nginx \
--user=nginx \ # 指定nginx运行用户
--group=nginx \ # 指定nginx运行组
--with-http_ssl_module \ # 支持https://
--with-http_v2_module \ # 支持http版本2
--with-http_realip_module \ # 支持ip透传
--with-http_stub_status_module \ # 支持状态页面
--with-http_gzip_static_module \ # 支持压缩
--with-pcre \ # 支持正则
--with-stream \ # 支持tcp反向代理
--with-stream_ssl_module \ # 支持tcp的ssl加密
--with-stream_realip_module # 支持tcp的透传ip
[root@nginx nginx-1.24.0]# make && make install
查看
root@nginx nginx-1.24.0]# cd /usr/local/nginx/
[root@nginx nginx]# ls
conf html logs sbin
[root@nginx sbin]# useradd -s /sbin/nologin -M nginx
[root@nginx sbin]# id nginx
uid=1001(nginx) gid=1001(nginx) groups=1001(nginx)
[root@nginx sbin]# ./nginx
[root@nginx sbin]# ps aux | grep nginx
root 42047 0.0 0.0 9868 940 ? Ss 00:38 0:00 nginx: master process ./nginx
nginx 42048 0.0 0.2 13740 4852 ? S 00:38 0:00 nginx: worker process
root 42054 0.0 0.1 221668 2216 pts/1 S+ 00:39 0:00 grep --color=auto nginx
[root@nginx sbin]# netstat -antlupe | grep nginx
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 0 79628 42047/nginx: master
三、平滑升级和回滚
3.1平滑升级
解压缩
[root@nginx ~]# tar zxf echo-nginx-module-0.63.tar.gz
[root@nginx ~]# tar zxf nginx-1.26.1.tar.gz
编译目录
[root@nginx nginx-1.26.1]# ./configure --prefix=/usr/local/nginx \
--user=nginx --group=nginx \
--add-module=/root/echo-nginx-module-0.63 \
--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 \
--add-module=/root/srcache-nginx-module-0.33 \
--add-module=/root/memc-nginx-module-0.20
用新版本覆盖旧版本
[root@nginx sbin]# \cp -f /root/nginx-1.26.1/objs/nginx /usr/local/nginx/sbin/nginx
回收旧版本
[root@nginx sbin]# kill -USR2 9155
[root@nginx sbin]# kill -WINCH 9155
3.2 平滑回滚
[root@nginx sbin]# ps aux | grep nginx
avahi 882 0.0 0.1 15528 6224 ? Ss 11:36 0:00 avahi-daemon: running [nginx.local]
root 9155 0.0 0.0 9860 2568 ? Ss 12:22 0:00 nginx: master process nginx
root 9195 0.0 0.1 9896 5924 ? S 12:10 0:00 nginx: master process nginx
nginx 9196 0.0 0.1 13792 5300 ? S 12:14 0:00 nginx: worker process
root 9219 0.0 0.0 221796 2372 pts/1 S+ 12:34 0:00 grep --color=auto nginx
[root@nginx sbin]# kill -HUP 9155
[root@nginx sbin]# ps aux | grep nginx
avahi 882 0.0 0.1 15528 6224 ? Ss 11:30 0:00 avahi
root 9155 0.0 0.0 9860 2568 ? Ss 12:16 0:00 nginx
root 9195 0.0 0.1 9896 5924 ? S 12:25 0:00 nginx
nginx 9196 0.0 0.1 13792 5300 ? S 12:25 0:00 nginx
nginx 9225 0.0 0.1 13756 4868 ? S 12:50 0:00 nginx
root 9227 0.0 0.0 221796 2376 pts/1 S+ 12:58 0:00 grep
[root@nginx sbin]# kill -WINCH 9195
四、 I/O 模型
4.1 I/O 模型相关概念
同步/异步:关注的是消息通信机制,即调用者在等待一件事情的处理结果时,被调用者是否提供完成状 态的通知。
同步:synchronous,被调用者并不提供事件的处理结果相关的通知消息,需要调用者主动询问事 情是否处理完成
异步:asynchronous,被调用者通过状态、通知或回调机制主动通知调用者被调用者的运行状态
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
阻塞:blocking,指IO操作需要彻底完成后才返回到用户空间,调用结果返回之前,调用者被挂 起,干不了别的事情。
非阻塞:nonblocking,指IO操作被调用后立即返回给用户一个状态值,而无需等到IO操作彻底完 成,在最终的调用结果返回之前,调用者不会被挂起,可以去做别的事情。
4.2 网络 I/O 模型
阻塞型、非阻塞型、复用型、信号驱动型、异步
4.2.1阻塞型 I/O 模型(blocking IO)
阻塞IO模型是最简单的I/O模型,用户线程在内核进行IO操作时被阻塞
用户线程通过系统调用read发起I/O读操作,由用户空间转到内核空间。内核等到数据包到达后,然 后将接收的数据拷贝到用户空间,完成read操作
用户需要等待read将数据读取到buffer后,才继续处理接收的数据。整个I/O请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够。
优点:程序简单,在阻塞等待数据期间进程/线程挂起,基本不会占用 CPU 资源
缺点:每个连接需要独立的进程/线程单独处理,当并发请求量大时为了维护程序,内存、线程切换开销 较apache 的preforck使用的是这种模式。
同步阻塞:程序向内核发送I/O请求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回,则进 程将一直等待并不再接受新的请求,并由进程轮询查看I/O是否完成,完成后进程将I/O结果返回给 Client,在IO没有返回期间进程不能接受其他客户的请求,而且是有进程自己去查看I/O是否完成,这种 方式简单,但是比较慢,用的比较少
4.2.2 非阻塞型 I/O 模型 (nonblocking IO)
用户线程发起IO请求时立即返回。但并未读取到任何数据,用户线程需要不断地发起IO请求,直到数据 到达后,才真正读取到数据,继续执行。即 “轮询”机制存在两个问题:如果有大量文件描述符都要等, 那么就得一个一个的read。这会带来大量的Context Switch(read是系统调用,每调用一次就得在用户 态和核心态切换一次)。轮询的时间不好把握。这里是要猜多久之后数据才能到。等待时间设的太长, 程序响应延迟就过大;设的太短,就会造成过于频繁的重试,干耗CPU而已,是比较浪费CPU的方式,一 般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
非阻塞:程序向内核发送请I/O求后一直等待内核响应,如果内核处理请求的IO操作不能立即返回IO结果,进程将不再等待,而且继续处理其他请求,但是仍然需要进程隔一段时间就要查看内核I/O是否完成。
查看上图可知,在设置连接为非阻塞时,当应用进程系统调用 recvfrom 没有数据返回时,内核会立即返 回一个EWOULDBLOCK错误,而不会一直阻塞到数据准备好。如上图在第四次调用时有一个数据报准 备好了,所以这时数据会被复制到 应用进程缓冲区 ,于是 recvfrom 成功返回数据。
当一个应用进程这样循环调用 recvfrom 时,称之为轮询 polling 。这么做往往会耗费大量CPU时间,实 际使用很少。
4.2.3 多路复用 I/O 型(I/O multiplexing)
I/O multiplexing 主要包括:select,poll,epoll三种系统调用,select/poll/epoll的好处就在于单个 process就可以同时处理多个网络连接的IO。
它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数 据到达了,就通知用户进程。
它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数 据到达了,就通知用户进程。
Apache prefork是此模式的select,worker是poll模式。
IO多路复用(IO Multiplexing) :是一种机制,程序注册一组socket文件描述符给操作系统,表示“我要 监视这些fd是否有IO事件发生,有了就告诉程序处理”IO多路复用一般和NIO一起使用的。NIO和IO多路 复用是相对独立的。NIO仅仅是指IO API总是能立刻返回,不会被Blocking;而IO多路复用仅仅是操作系统 提供的一种便利的通知机制。操作系统并不会强制这俩必须得一起用,可以只用IO多路复用 + BIO,这时 还是当前线程被卡住。IO多路复用和NIO是要配合一起使用才有
实际意义
IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,就通知该进程多个连接共用一 个等待机制,本模型会阻塞进程,但是进程是阻塞在select或者poll这两个系统调用上,而不是阻塞在真 正的IO操作上用户首先将需要进行IO操作添加到select中,同时等待select系统调用返回。当数据到达 时,IO被激活,select函数返回。用户线程正式发起read请求,读取数据并继续执行从流程上来看,使用 select函数进行IO请求和同步阻塞模型没有太大的区别,甚至还多了添加监视IO,以及调用select函数的 额外操作,效率更差。并且阻塞了两次,但是第一次阻塞在select上时,select可以监控多个IO上是否已 有IO操作准备就绪,即可达到在同一个线程内同时处理多个IO请求的目的。而不像阻塞IO那种,一次只 能监控一个IO虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select 函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只是注册自己需要的IO请求,然 后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率IO多路复用是最常使用的IO 模型,但是其异步程度还不够“彻底”,因它使用了会阻塞线程的select系统调用。因此IO多路复用只能称 为异步阻塞IO模型,而非真正的异步IO
优点:可以基于一个阻塞对象,同时在多个描述符上等待就绪,而不是使用多个线程(每个文件描述 符一个线程),这样可以大大节省系统资源
缺点:当连接数较少时效率相比多线程+阻塞 I/O 模型效率较低,可能延迟更大,因为单个连接处理 需要 2 次系统调用,占用时间会有增加
4.2.4 信号驱动式 I/O 模型 (signal-driven IO)
信号驱动I/O的意思就是进程现在不用傻等着,也不用去轮询。而是让内核在数据就绪时,发送信号通知 进程。
调用的步骤是,通过系统调用 sigaction ,并注册一个信号处理的回调函数,该调用会立即返回,然后主 程序可以继续向下执行,当有I/O操作准备就绪,即内核数据就绪时,内核会为该进程产生一个 SIGIO信 号,并回调注册的信号回调函数,这样就可以在信号回调函数中系统调用 recvfrom 获取数据,将用户进 程所需要的数据从内核空间拷贝到用户空间
此模型的优势在于等待数据报到达期间进程不被阻塞。用户主程序可以继续执行,只要等待来自信号处 理函数的通知。
在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞
当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。优点:线程并没有在等待数据时被阻塞,内核直接返回调用接收信号,不影响进程继续处理其他请求因此 可以提高资源的利用率
缺点:信号 I/O 在大量 IO 操作时可能会因为信号队列溢出导致没法通知
异步阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核收到进程请求后
进行的IO如果不能立即返回,就由内核等待结果,直到IO完成后内核再通知进程。
4.2.5 异步 I/O 模型 (asynchronous IO)
异步I/O 与 信号驱动I/O最大区别在于,信号驱动是内核通知用户进程何时开始一个I/O操作,而异步I/O 是由内核通知用户进程I/O操作何时完成,两者有本质区别,相当于不用去饭店场吃饭,直接点个外卖,把 等待上菜的时间也给省了
相对于同步I/O,异步I/O不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备 好,都会直接返回给用户进程,然后用户态进程可以去做别的事情。等到socket数据准备好了,内核直 接复制数据给进程,然后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。
信号驱动IO当内核通知触发信号处理程序时,信号处理程序还需要阻塞在从内核空间缓冲区拷贝数据到 用户空间缓冲区这个阶段,而异步IO直接是在第二个阶段完成后,内核直接通知用户线程可以进行后续 操作了
优点:异步 I/O 能够充分利用 DMA 特性,让 I/O 操作与计算重叠
缺点:要实现真正的异步 I/O,操作系统需要做大量的工作。目前 Windows 下通过 IOCP 实现了真正的 异步 I/O,在 Linux 系统下,Linux 2.6才引入,目前 AIO 并不完善,因此在 Linux 下实现高并发网络编 程时以 IO 复用模型模式+多线程任务的架构基本可以满足需求
Linux提供了AIO库函数实现异步,但是用的很少。目前有很多开源的异步IO库,例如libevent、libev、 libuv。
异步非阻塞:程序进程向内核发送IO调用后,不用等待内核响应,可以继续接受其他请求,内核调用的 IO如果不能立即返回,内核会继续处理其他事物,直到IO完成后将结果通知给内核,内核在将IO完成的 结果返回给进程,期间进程可以接受新的请求,内核也可以处理新的事物,因此相互不影响,可以实现 较大的同时并实现较高的IO复用,因此异步非阻塞使用最多的一种通信方式。
五、Nginx核心配置
全局配置
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
user nginx;
worker_processes auto;
worker_cpu_affinity 0001 0010;
重启服务
[root@nginx ~]# nginx -s reload
查看
[root@nginx ~]# ps aux | grep nginx
root 55887 0.0 0.0 10024 3476 ? Ss 23:07 0:00 nginx: master process /usr/local/nginx/sbin/nginx
nginx 55943 0.0 0.1 14364 5008 ? S 23:27 0:00 nginx: worker process
nginx 55944 0.0 0.1 14364 5008 ? S 23:27 0:00 nginx: worker process
root 55946 0.0 0.0 221664 2304 pts/0 S+ 23:27 0:00 grep --color=auto nginx
在末尾添加以下内容
[root@nginx ~]# vim /etc/security/limits.conf
nginx - nofile 100000
修改连接数
[root@nginx ~]# vim /usr/local/nginx/conf/nginx.conf
events {
worker_connections 100000;
}
root和alias
新建一个网页
[root@nginx nginx]# mkdir -p /usr/local/nginx/conf.d
编写配置文件
[root@nginx nginx]# vim /usr/local/nginx/conf.d/vhost.conf
server{
listen 80;
server_name www.example.org;
root /data/web/html;
index index.html;
}
创建文件夹,并打印
[root@nginx nginx]# mkdir -p /data/web/html
[root@nginx nginx]# echo www.example.org > /data/web/html/index.html
重新载入
[root@nginx nginx]# nginx -s reload
alias
编写配置文件
server{
listen 80;
server_name www.example.org;
root /data/web/html;
index index.html;
location /test1/ {
root /data/web;
}
location /test2 {
alias /data/web/test1;
}
}
测试
Nginx账户认证
创建认证文件
[root@nginx ~]# htpasswd -cm /usr/local/nginx/.htpasswd admin
New password:
Re-type new password:
Adding password for user admin
[root@nginx ~]# htpasswd -m /usr/local/nginx/.htpasswd lee
New password:
Re-type new password:
Adding password for user lee
创建并编写配置文件
[root@nginx ~]# mkdir -p /data/web
[root@nginx ~]# mkdir /data/web/lee
[root@nginx ~]# echo lee > /data/web/lee/index.html
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server{
listen 80;
server_name www.example.org;
root /data/web/html;
index index.html;
location /lee {
root /data/web;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
}
重启服务并查看网页
[root@nginx ~]# nginx -s reload
Nginx自定义错误页面
创建文件夹
[root@nginx ~]# mkdir -p /data/web/errorpage
[root@nginx ~]# echo errorpage > /data/web/errorpage/404.html
编写配置文件
[root@nginx ~]# vim /usr/local/nginx/conf.d/vhost.conf
server{
listen 80;
server_name www.example.org;
root /data/web/html;
index index.html;
error_page 404 /40x.html;
location /lee {
root /data/web;
auth_basic "login password";
auth_basic_user_file "/usr/local/nginx/.htpasswd";
}
location = /40x.html {
root /data/web/errorpage;
}
}
六、Nginx 高级配置
Nginx状态页
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
上面三个数字分别对应accepts,handled,requests三个值
Reading: 6 Writing: 179 Waiting: 106
Active connections: #当前处于活动状态的客户端连接数
#包括连接等待空闲连接数=reading+writing+waiting
accepts: #统计总值,Nginx自启动后已经接受的客户端请求连接的总数。
handled: #统计总值,Nginx自启动后已经处理完成的客户端请求连接总数,通常等于accepts,除非有因worker_connections限制等被拒绝的连接
requests: #统计总值,Nginx自启动后客户端发来的总的请求数
Reading: #当前状态,正在读取客户端请求报文首部的连接的连接数,数值越大,说明排队现象严重,性能不足
Writing: #当前状态,正在向客户端发送响应报文过程中的连接数,数值越大,说明访问量很大
Waiting: #当前状态,正在等待客户端发出请求的空闲连接数
开启 keep-alive的情况下,这个值等于active –(reading+writing)
[root@nginx ~]# cd /usr/local/nginx/conf.d/
[root@nginx conf.d]# vim status.conf
server {
listen 80;
server_name status.example.org;
root /data/web/html;
index index.html;
location /status {
stub_status;
}
}
Nginx 压缩功能
Nginx支持对指定类型的文件进行压缩然后再传输给客户端,而且压缩还可以设置压缩比例,压缩后的文件大小将比源文件显著变小,样有助于降低出口带宽的利用率,降低企业的IT支出,不过会占用相应的CPU资源。
Nginx对文件的压缩功能是依赖于模块 ngx_http_gzip_module,默认是内置模块
[root@nginx conf.d]# vim /usr/local/nginx/conf/nginx.conf
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;
[root@nginx conf.d]# nginx -t
重启服务
[root@nginx conf.d]# nginx -s reload
[root@nginx conf.d]# echo hello example xixi > /data/web/html/small.html
[root@nginx conf.d]# cat /var/log/example.org/access.log > /data/web/html/big.html
测试
[root@nginx conf.d]# curl --head --compressed 172.25.254.100/small.html
[root@nginx conf.d]# curl --head --compressed 172.25.254.100/big.html
Rewrite相关功能
Nginx服务器利用 ngx_http_rewrite_module 模块解析和处理rewrite请求
此功能依靠 PCRE(perl compatible regular expression),因此编译之前要安装PCRE库
rewrite是nginx服务器的重要功能之一,用于实现URL的重写,URL的重写是非常有用的功能
比如它可以在我们改变网站结构之后,不需要客户端修改原来的书签,也无需其他网站修改我们的链接,就可以设置为访问
另外还可以在一定程度上提高网站的安全性。
配置文件
[root@nginx conf.d]# vim vhost.conf
server {
listen 80;
server_name var.example.org;
root /data/web/html;
index index.html;
location / {
root /data/web/var;
index index.html;
rewrite / http://www.example.com permanent;
}
}
创建文件夹
[root@nginx conf.d]# mkdir /data/web/var -p
测试
[root@nginx nginx]# curl var.example.org
全站加密
创建目录
[root@nginx ~]# cd /usr/local/nginx/
[root@nginx nginx]# mkdir certs
加密
[root@nginx ~]# openssl req -newkey rsa:2048 -nodes -sha256 -keyout/usr/local/nginx/certs/example.org.key -x509 -days 365 -out /usr/local/nginx/certs/example.org.crt
编写配置文件
[root@nginx certs]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
listen 443 ssl;
server_name www.example.org;
root /data/web/html;
index index.html;
ssl_certificate /usr/local/nginx/certs/example.org.crt;
ssl_certificate_key /usr/local/nginx/certs/example.org.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
location / {
if ( $scheme = http ){
rewrite / https://$host redirect;
}
if ( !-e $request_filename ){
rewrite /(.*) https://$host/index.html redirect;
}
}
}
防盗链
none: #请求报文首部没有referer首部,比如用户直接在浏览器输入域名访问web网站,就没有referer信息。
blocked: #请求报文有referer首部,但无有效值,比如为空。
server_names: #referer首部中包含本主机名及即nginx 监听的server_name。
arbitrary_string: #自定义指定字符串,但可使用*作通配符。
regular expression: #被指定的正则表达式模式匹配到的字符串,要使用~开头
[root@nginx ~]# cd /data/web/html/images
配置文件
[root@webserver1 html]# vim index.html
<html>
<head>
<meta http-equiv=Content-Type content="text/html;charset=utf-8">
<title>盗链</title>
</head>
<body>
<img src="http://www.example.org/images/logo.png" >
<h1 style="color:red">欢迎大家</h1>
<p><a href=http://www.example.org>狂点老李</a>出门见喜</p>
</body>
</html>
然后重启httpd服务
[root@webserver1 html]# systemctl restart httpd
Nginx反向代理
编辑配置文件,添加以下内容
[root@nginxconf.d]# vim /usr/local/nginx/conf/nginx.conf
proxy_cache_path /usr/local/nginx/proxy_cache levels=1:2:2 keys_zone=proxycache:20m inactive=120 max_size=1g;
[root@nginx conf.d]# vim /usr/local/nginx/conf.d/vhost.conf
server {
listen 80;
server_name www.example.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;
$scheme$proxy_host$request_uri
proxy_cache_valid 200 302 301 10m;
proxy_cache_valid any 1m;
}
}
然后重启服务
[root@nginx conf.d]# nginx -s reload
七、实现FastCGI
为什么会有FastCGI?
CGI协议虽然解决了语言解析器和 Web Server 之间通讯的问题,但是它的效率很低,因为 Web Server每收到一个请求都会创建一个CGI进程,PHP解析器都会解析php.ini文件,初始化环境,请求结束的时候再关闭进程,对于每一个创建的CGI进程都会执行这些操作,所以效率很低,而FastCGI是用来提高CGI性能的,FastCGI每次处理完请求之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一个进程了,大大提升了处理效率。
什么是PHP-FPM?
PHP-FPM(FastCGI Process Manager:
FastCGI进程管理器)是一个实现了Fastcgi的程序,并且提供进程管理的功能。
进程包括master进程和worker进程。master进程只有一个,负责监听端口,接受来自web server的请求
worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
FastCGI配置指令
Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客户端请求转发至php-fpm处理,其配置指令如下:
fastcgi_pass address:port;#转发请求到后端服务器,address为后端的fastcgi server的地址,可用位置:location, if in location
#fastcgi默认的主页资源,示例:fastcgi_index index.php;
fastcgi_index name;
#设置传递给FastCGI服务器的参数值,可以是文本,变量或组合,可用于将Nginx的内置变量赋值给自定义key
fastcgi_param parameter value [if_not_empty];
fastcgi_param REMOTE_ADDR $remote_addr; #客户端源IP
fastcgi_param REMOTE_PORT $remote_port; #客户端源端口
fastcgi_param SERVER_ADDR $server_addr; #请求的服务器IP地址
fastcgi_param SERVER_PORT $server_port; #请求的服务器端口
fastcgi_param SERVER_NAME $server_name; #请求的server name
Nginx默认配置示例:
location ~ \.php$ {
root /scripts;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; #默认脚本路径
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params; #此文件默认系统已提供,存放的相对路径为prefix/conf
}
源码编译php
解决依赖问题
[root@nginx ~]# yum install -y bzip2 systemd-devel libxml2-devel sqlite-devel libpng-devel libcurl-devel oniguruma-devel
解压源码并安装
[root@nginx nginx-1.26.2]# ./configure \
--prefix=/usr/local/php \ #安装路径
--with-config-file-path=/usr/local/php/etc \ #指定配置路径
--enable-fpm \ #用cgi方式启动程序
--with-fpm-user=nginx \ #指定运行用户身份
--with-fpm-group=nginx \
--with-curl \ #打开curl浏览器支持
--with-iconv \ #启用iconv函数,转换字符编码
--with-mhash \ #mhash加密方式扩展库
--with-zlib \ #支持zlib库,用于压缩http压缩传输
--with-openssl \ #支持ssl加密
--enable-mysqlnd \ #mysql数据库
--with-mysqli \
--with-pdo-mysql \
--disable-debug \ #关闭debug功能
--enable-sockets \ #支持套接字访问
--enable-soap \ #支持soap扩展协议
--enable-xml \ #支持xml
--enable-ftp \ #支持ftp
--enable-gd \ #支持gd库
--enable-exif \ #支持图片元数据
--enable-mbstring \ #支持多字节字符串
--enable-bcmath \ #打开图片大小调整,用到zabbix监控的时候用到了这个模块
--with-fpm-systemd #支持systemctl 管理cgi
php相关配置
[root@nginx ~]# cd /usr/local/php/etc
[root@nginx ~]# cd /usr/local/php/etc/
[root@nginx etc]# cp php-fpm.conf.default php-fpm.conf
[root@nginx etc]# vim php-fpm.conf
pid = run/php-fpm.pid
[root@nginx etc]# cd php-fpm.d/
[root@nginxphp-fpm.d]# cp www.conf.default www.conf
生成主配置文件
[root@nginx php-fpm.d]# cd /root/php-8.3.9/
[root@nginx php-8.3.9]# cp php.ini-production /usr/local/php/etc/php.ini
[root@nginx ~]# vim /usr/local/php/etc/php.ini
[Date]
; Defines the default timezone used by the date functions
; https://php.net/date.timezone
date.timezone = Asia/Shanghai
生成启动文件,注释以下内容
root@nginx ~]# cd /root/php-8.3.9/
[root@nginx php-8.3.9]# cp sapi/fpm/php-fpm.service /lib/systemd/system/
# Mounts the /usr, /boot, and /etc directories read-only for processes invoked by
this unit.
#ProtectSystem=full
准备php测试页面
[root@nginx ~]# mkdir -p /data/web/php
[root@nginx ~]# cat /data/web/php/index.php
phpinfo();
?>
Nginx配置转发
[root@nginx ~]# vim /apps/nginx/conf.d/php.conf
server {
listen 80;
server_name php.timinglee.org;
root /data/php;
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}
}
访问验证php测试页面