1 Web基础介绍
1.1 系统IO模型
1.1.1 网络请求处理过程
分级保护域:在电脑操作系统中提供了不通的资源访问级别,Ring0表示最高特权,对应内核模式,能够和硬件直接交互(如内存、CPU),Ring3对应用户模式,低级别Ring是不能访问高级别资源。简单而言就是用户的应用程序是不能够直接访问硬件级别底层资源的,而是通过系统调用间接访问硬件资源。
在Linux系统内核中,分为了用户空间和内核空间,其关系如下图
- 内核负责读写网络和文件数据
- 用户程序则通过系统调用获取数据
- 用户程序通过系统调用接口,线程从用户态切换到内核态,内核读写数据后,又切换为用户态
服务器处理网络请求的过程
- 第⼀步:将数据从网卡先加载⾄内核内存空间(缓冲区),此步骤需要等待数据准备完成,时间较⻓
- 第⼆步:将数据从内核缓冲区复制到⽤⼾空间的进程的内存中,时间较短
- 第三步:将处理好的数据复制到内核当中,在由内核把数据给网卡
1.1.2 同步和异步
同步/异步:关注的是事件处理的消息通信机制,即在等待⼀件事情的处理结果时,被调⽤者是否提供完成通知。
- 同步:synchronous,调⽤者等待被调⽤者返回消息后才能继续执⾏,如果被调⽤者不提供消息返回则为同步,同步需要调⽤者主动询问事情是否处理完成。
- 异步:asynchronous,被调⽤者通过状态、通知或回调机制主动通知调⽤者被调⽤者的运⾏状态。
在Linux系统中往往内核是作为被调用者,而进程则是作为调用者,接下来所说的Nginx则是异步的。
1.1.3 阻塞和⾮阻塞
阻塞/⾮阻塞:关注调⽤者在等待结果返回之前所处的状态
- 阻塞:blocking,指IO操作需要彻底完成后才返回到⽤ ⼾空间,调⽤结果返回之前,调⽤者被挂起,⼲不了别的事情。
- ⾮阻塞:nonblocking,指IO操作被调⽤后⽴即返 回给⽤⼾⼀个状态值,⽆需等到IO操作彻底完成,最终的调⽤结果返回之前,调⽤者不会被挂起,可以去做别的事情。
1.2 网络IO模型
1.2.1 Blocking I/O Model(同步阻塞型)
⽤⼾线程在内核进⾏IO操作时被阻塞,⽤⼾线程通过系统调⽤read发起IO读操作, 由⽤⼾空间转到内核空间。内核等到数据包到达后,然后将接收的数据拷⻉到⽤⼾空间,完成read操作⽤⼾需要等待read将数据读取到buffer后,才继续处理接收的数据。整个IO请求的过程中,⽤⼾线程是被阻塞的,这导致⽤⼾在发起IO请求时,不能做任何事情,对CPU的资源利⽤率不够。apache 的preforck使⽤的是这种模式。
1.2.2 nonblocking IO Model(同步非阻塞型)
当用户线程发起IO请求时,数据没有准备好,内核会立刻返回错误给用户进程,之后,⽤⼾线程需要不断地发起IO请求。直到recvfrom
将数据从内核缓冲区拷贝到用户空间,接着处理数据。
当应用程序不断循环调用recvfrom
获取数据的行为被称为轮询,这会带来⼤量的Context Switch(内核对线程或者进程进行切换),浪费了CPU的时间,⼀般很少直接使⽤这种模型,⽽是在其他IO模型中使⽤ ⾮阻塞IO这⼀特性。
1.2.3 IO multiplexing Model(IO多路复⽤型)
这种IO方式也被称为event driven IO,它使用select、poll来等待数据报,因此recvfrom
的IO系统调用上则没有被阻塞。当数据报套接字可读时,由select返回套接字可读,接着调用recvfrom
复制数据报,这样的好处就在于单个的process可以同时处理多个网络连接的IO。
Apache prefork是此模式的主进程+多进程/单线程+select,work是主进程+多进程/多线程+poll模式
1.2.4 signal-driven IO(信号驱动)
首先为信号驱动的 I/O 启用套接字并使用sigaction
系统调用安装信号处理程序。这个系统调用的返回是立即的,程序依然可以继续向下执行,当有IO操作准备就绪时,由内核通知触发⼀个SIGIO信号处理程序执⾏,然后将⽤⼾进程所需要的数据 从内核空间拷⻉到⽤⼾空间。
这种模型的优点是我们在等待数据报到达时不会被阻塞。主循环可以继续执行并等待信号处理程序通知数据已准备好处理或数据报已准备好读取。但信号 I/O 在⼤量 IO 操作时可能会因为信号队列溢出导致没法通知
1.2.5 asynchronous IO(异步⾮阻塞 IO)
调用aio_系列函数将描述符、缓冲区指针、缓冲区大小和文件偏移量传递给内核。该系统调用立即返回。当整个IO操作完成后,数据报到达并从内核缓冲区复制到用户缓冲区后,产生一个信号
Linux提供了AIO库函数实现异步,但是⽤的很少。⽬前有很多开源的异步IO库,例如libevent、libev、libuv。nginx是异步⾮阻塞。
1.2.6 IO对⽐
这五种⽹络 I/O 模型中,越往后,阻塞越少,理论上效率也是最优前四种属于同步 I/O,因为其中真正的 I/O 操作 (recvfrom)将阻塞进程/线程,只有异步 I/O 模型才与 POSIX 定义的异步 I/O 相匹配。
1.2.7 实现⽅式
Nginx⽀持在多种不同的操作系统实现不同的事件驱动模型,但是其在不同的操作系统甚⾄是不同的系统版本上⾯ 的实现⽅式不尽相同,主要有以下实现⽅式:
select
- select库是在linux和windows平台都基本⽀持的 事件驱动模型库,并且在接⼝的定义也基本相同,只是部分参数的 含义略有差异,最⼤并发限制1024,是最早期的事件驱动模型。
poll
- 在Linux 的基本驱动模型,windows不⽀持此驱动模型,是select的升级版,取消了最⼤的并发限制,在编译nginx 的时候可以使⽤--with-poll_module和--without-poll_module这两个指定是否编译select库。
epoll
- epoll是库是Nginx服务器⽀持的最⾼性能的事件驱动库之⼀,是公认的⾮常优秀的事件驱动模型,它和select和 poll有很⼤的区别,epoll是poll的升级版,但是与poll的效率有很⼤的区别. epoll的处理⽅式是创建⼀个待处理的事件列表,然后把这个列表发给内核,返回的时候在去轮训检查这个表,以判断 事件是否发⽣,epoll⽀持⼀个进程打开的最⼤事件描述符的上限是系统可以打开的⽂件的最⼤数,同时epoll库的IO 效率不随描述符数⽬增加⽽线性下降,因为它只会对内核上报的“活跃”的描述符进⾏操作。
rtsig
- 不是⼀个常⽤事件驱动,最⼤队列1024,不是很常⽤
kqueue
- ⽤于⽀持BSD系列平台的⾼校事件驱动模型,主要⽤在FreeBSD 4.1及以上版本、OpenBSD 2.0级以上版本,NetBSD 级以上版本及Mac OS X 平台上,该模型也是poll库的变种,因此和epoll没有本质上的区别,都是通过避免轮训操 作提供效率。
/dev/poll
- ⽤于⽀持unix衍⽣平台的⾼效事件驱动模型,主要在Solaris 平台、HP/UX,该模型是sun公司在开发Solaris系列 平台的时候提出的⽤于完成事件驱动机制的⽅案,它使⽤了虚拟的/dev/poll设备,开发⼈员将要⻅识的⽂件描述符加 ⼊这个设备,然后通过ioctl()调⽤来获取事件通知,因此运⾏在以上系列平台的时候请使⽤/dev/poll事件驱动机 制。
eventport
- 该⽅案也是sun公司在开发Solaris的时候提出的事件驱动库,只是Solaris 10以上的版本,该驱动库看防⽌内核崩 溃等情况的发⽣。
Iocp
- Windows系统上的实现⽅式,对应第5种(异步I/O)模型。
2 Nginx基础
2.1 Nginx简介
Nginx用于静态的web资源服务器html,图⽚,js,css,txt等静态资源 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源 请求 http/https协议的反向代理 imap4/pop3协议的反向代理 tcp/udp协议的请求转发(反向代理)
Nginx:engine X ,2002年开始开发,2004年开源,2019年3⽉11⽇,Nginx公司被F5 Networks以6.7亿美元收 购。
Nginx 则是免费的、开源的、⾼性能的HTTP和反向代理服务器、邮件代理服务器、以及TCP/UDP代理服务器 解决 C10K问题(10K Connections),http://www.ideawu.net/blog/archives/740.html
Nginx官⽹:http://nginx.org
Nginx 商业版为Nginx Plus:https://www.nginx.com/products/nginx/
nginx的其它的⼆次发⾏版: Tengine:由淘宝⽹发起的Web服务器项⽬。它在Nginx的基础上,针对⼤访问量⽹ 站的需求,添加了很多⾼级功能和特性。Tengine的性能和稳定性已经在⼤型的⽹站如淘宝⽹,天猫商城等得到了 很好的检验。它的最终⽬标是打造⼀个⾼效、稳定、安全、易⽤的Web平台,从2011年12⽉开始,Tengine成为⼀ 个开源项⽬,官⽹ http://tengine.taobao.org/ OpenResty:基于 Nginx 与 Lua 语⾔的⾼性能 Web 平台, 章亦 春团队开发,官⽹:http://openresty.org/cn/
2.2 Nginx架构
2.2.1 组织模型
Nginx是多进程组织模型,⽽且是⼀个由Master主进程和Worker⼯作进程组成。
主进程(master process)的功能:
读取Nginx 配置⽂件并验证其有效性和正确性
建⽴、绑定和关闭socket连接
按照配置⽣成、管理和结束⼯作进程(worker)
接受外界指令,⽐如重启、升级及退出服务器等指令
不中断服务情况下重载配置文件
开启日志文件,获取文件描述符
不中断服务,实现平滑升级,升级失败进行回滚处理
编译和处理perl脚本
⼯作进程(woker process)的功能:
接受处理客⼾的请求
将请求以此送⼊各个功能模块进⾏处理
IO调⽤,获取响应数据
与后端服务器通信,接收后端服务器的处理结果
缓存数据,访问缓存索引,查询和调⽤缓存数据
发送请求结果,响应客⼾的请求
接收主程序指令,⽐如重启、升级和退出等
nginx架构如下图
nginx将各功能模块组织成一条链,当有请求到达的时候,请求依次经过这条链上的部分或者全部模块,进行处理。每个模块实现特定的功能。例如,实现对请求解压缩的模块,实现SSI的模块,实现与上游服务器进行通讯的模块,实现与FastCGI服务进行通讯的模块。
nginx的模块根据其功能基本上可以分为以下几种类型:
- event module:搭建了独立于操作系统的事件处理机制的框架,及提供了各具体事件的处理。包括ngx_events_module, ngx_event_core_module和ngx_epoll_module等。nginx具体使用何种事件处理模块,这依赖于具体的操作系统和编译选项。
- phase handler:此类型的模块也被直接称为handler模块。主要负责处理客户端请求并产生待响应内容,比如ngx_http_static_module模块,负责客户端的静态页面请求处理并将对应的磁盘文件准备为响应内容输出。
- output filter:也称为filter模块,主要是负责对输出的内容进行处理,可以对输出进行修改。例如,可以实现对输出的所有html页面增加预定义的footbar一类的工作,或者对输出的图片的URL进行替换之类的工作。
- upstream:upstream模块实现反向代理的功能,将真正的请求转发到后端服务器上,并从后端服务器上读取响应,发回客户端。upstream模块是一种特殊的handler,只不过响应内容不是真正由自己产生的,而是从后端服务器上读取的。
- load-balancer:负载均衡模块,实现特定的算法,在众多的后端服务器中,选择一个服务器出来作为某个请求的转发服务器。
2.2.2 进程间通信
⼯作进程是有主进程(Master)⽣成的,Master使⽤fork()函数,在Nginx服务器启动过程中主进程根据配置⽂件决定启动⼯作 进程的数量,然后建⽴⼀张全局的⼯作表⽤于存放当前未退出的所有的⼯作进程,主进程⽣成⼯作进程后会将新⽣ 成的⼯作进程加⼊到⼯作进程表中,并建⽴⼀个单向的管道并将其传递给⼯作进程,该管道与普通的管道不同,它 是由主进程指向⼯作进程的单项通道,包含了主进程向⼯作进程发出的指令、⼯作进程ID、⼯作进程在⼯作进程表 中的索引和必要的⽂件描述符等信息。 主进程与外界通过信号机制进⾏通信,当接收到需要处理的信号时,它通 过管道向相关的⼯作进程发送正确的指令,每个⼯作进程都有能⼒捕获管道中的可读事件,当管道中有可读事件的 时候,⼯作进程就会从管道中读取并解析指令,然后采取相应的执⾏动作,这样就完成了主进程与⼯作进程的交 互。
2.3 Nginx安装
安装之前需要根据自己的需求选择安装的版本,例如Stable版本或者Mainline;还有安装的方式:二进制包安装或者是源码编译安装,推荐编译安装的方式,因为能够定制一些功能和路径。安装时也可以参考官方文档:https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/
2.3.1 Nginx yum安装
需配置epel源
[root@localhost ~]# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
[root@localhost ~]# yum -y install nginx
[root@localhost ~]# which nginx
/usr/sbin/nginx
[root@localhost ~]# systemctl start nginx
查看nginx命令帮助
[root@localhost ~]# nginx -h
nginx version: nginx/1.20.1
Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]
[-e filename] [-c filename] [-g directives]
Options:
-?,-h : this help
-v : show version and exit
-V : show version and configure options then exit
-t : test configuration and exit
-T : test configuration, dump it and exit
-q : suppress non-error messages during configuration testing
-s signal : send signal to a master process: stop, quit, reopen, reload
-p prefix : set prefix path (default: /usr/share/nginx/)
-e filename : set error log file (default: /var/log/nginx/error.log)
-c filename : set configuration file (default: /etc/nginx/nginx.conf)
-g directives : set global directives out of configuration file
启动脚本
[root@localhost ~]# cat /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
2.3.2 编译安装nginx
准备编译安装的基础环境:
[root@localhost ~]# yum install -y vim lrzsz tree screen psmisc lsof tcpdump wget ntpdate \
gcc gcc-c++ glibc glibc-devel pcre pcre-devel openssl openssl-devel systemd-devel nettools \iotop bc zip unzip zlib-devel bash-completion nfs-utils automake libxml2 \
libxml2-devel libxslt libxslt-devel perl perl-ExtUtils-Embed
gcc 在编译C++源代码的阶段,只能编译 C++ 源⽂件,⽽不能⾃动和 C++ 程序使⽤的库链接(编译过程分为编
译、链接两个阶段,注意不要和可执⾏⽂件这个概念搞混,相对可执⾏⽂件来说有三个重要的概念:编译
(compile)、链接(link)、加载(load)。源程序⽂件被编译成⽬标⽂件,多个⽬标⽂件连同库被链接成⼀个最
终的可执⾏⽂件,可执⾏⽂件被加载到内存中运⾏)。因此,通常使⽤ g++ 命令来完成 C++ 程序的编译和连接,该
程序会⾃动调⽤ gcc 实现编译。
gcc-c++也能编译C源代码,只不过把会把它当成C++源代码,后缀为.c的,gcc把它当作是C程序,⽽g++当作是
c++程序;后缀为.cpp的,两者都会认为是c++程序,注意,虽然c++是c的超集,但是两者对语法的要求是有区别的。
automake是⼀个从Makefile.am⽂件⾃动⽣成Makefile.in的⼯具。为了⽣成Makefile.in,automake还需
⽤到perl,由于automake创建的发布完全遵循GNU标准,所以在创建中不需要perl。libtool是⼀款⽅便⽣成各种程
序库的⼯具。
pcre pcre-devel:在Nginx编译需要 PCRE(Perl Compatible Regular Expression),因为Nginx 的
Rewrite模块和HTTP 核⼼模块会使⽤到PCRE正则表达式语法。
zlip zlib-devel:nginx启⽤压缩功能的时候,需要此模块的⽀持。
openssl openssl-devel:开启SSL的时候需要此模块的⽀持。
安装nginx
源码包下载地址
http://nginx.org/en/download.html
[root@localhost src]# pwd
/usr/local/src
[root@localhost src]# ls
nginx-1.20.1.tar.gz
[root@localhost src]# tar xvf nginx-1.20.1.tar.gz
[root@localhost src]# cd nginx-1.20.1
编译是为了检查系统环境是否符合编译安装的要求,⽐如是否有gcc编译⼯具,是否⽀持编译参数当中的模块,并根据
开启的参数等⽣成Makefile⽂件为下⼀步做准备:
[root@localhost nginx-1.20.1]# ./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.1]# make -j 8
[root@localhost nginx-1.20.1]# make install
[root@localhost nginx-1.20.1]# useradd -r nginx -s /sbin/nologin
创建Nginx自启动脚本
可以参考二进制安装的脚本来配置
[root@centos8 nginx]$cat !*
cat /usr/lib/systemd/system/nginx.service
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/apps/nginx/logs/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /apps/nginx/logs/nginx.pid
ExecStartPre=/apps/nginx/sbin/nginx -t
ExecStart=/apps/nginx/sbin/nginx
ExecReload=/apps/nginx/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
测试是否启动成功
[root@localhost ~]# systemctl daemon-reload
[root@centos8 nginx]# systemctl enable --now nginx
3 Nginx配置
3.1 默认配置
Nginx的配置⽂件的组成部分: 主配置⽂件:nginx.conf,⼦配置⽂件 include conf.d/*.conf
[root@localhost nginx]# grep -v "#" /apps/nginx/conf/nginx.conf | grep -v "^$"
# 全局配置端,对全局⽣效,主要设置nginx的启动⽤⼾/组,启动的⼯作进程数量,⼯作模式,Nginx的PID路径,⽇志路径等。
user nginx nginx;
# 启动⼯作进程数数量
worker_processes 1;
# events设置快,主要影响nginx服务器与⽤⼾的⽹络连接,⽐如是否允许同时接受多个⽹络连接,使⽤哪种事件驱动模型处理请求,每个⼯作进程可以同时⽀持的最⼤连接数,是否开启对多⼯作进程下的⽹络连接进⾏序列化等。
events {
# 设置单个nginx⼯作进程可以接受的最⼤并发,作为web服务器的时候最⼤并发数为worker_connections *
# worker_processes,作为反向代理的时候为(worker_connections*worker_processes)/2
worker_connections 1024;
}
# http块是Nginx服务器配置中的重要部分,缓存、代理和⽇志格式定义等绝⼤多数功能和第三⽅模块都可以在这设置,http块可以包含多个server块,⽽⼀个server块中⼜可以包含多个location块,server块可以配置⽂件引⼊、MIME-Type定义、⽇志⾃定义、是否启⽤sendfile、连接超时时间和单个链接的请求上限等。
http {
include mime.types;
default_type application/octet-stream;
# 作为web服务器的时候打开sendfile加快静态⽂件传输,指定是否使⽤sendfile系统调⽤来传输⽂ # 件,sendfile系统调⽤在两个⽂件描述符之间直接传递数据(完全在内核中操作),从⽽避免了数据在内核缓冲区和⽤⼾ # 缓冲区之间的拷⻉,操作效率很⾼,被称之为零拷⻉,硬盘 >> kernel buffer (快速拷⻉到kernelsocket
# buffer)>>协议栈。
sendfile on;
# ⻓连接超时时间,单位是秒
keepalive_timeout 65;
# 设置⼀个虚拟机主机,可以包含⾃⼰的全局快,同时也可以包含多个location模块。⽐如本虚拟机监听的端⼝、本虚拟 # 机的名称和IP配置,多个server 可以使⽤⼀个端⼝,⽐如都使⽤80端⼝提供web服务
server {
# 配置server监听的端⼝
listen 80;
# 本server的名称,当访问此名称的时候nginx会调⽤当前serevr内部的配置进程匹配。
server_name localhost;
# location其实是server的⼀个指令,为nginx服务器提供⽐较多⽽且灵活的指令,都是在location中提现的,主 # 要是基于nginx接受到的请求字符串,对⽤⼾请求的UIL进⾏匹配,并对特定的指令进⾏处理,包括地址重定向、数 # 据缓存和应答控制等功能都是在这部分实现,另外很多第三⽅模块的配置也是在location模块中配置。
location / {
# 相当于默认⻚⾯的⽬录名称,默认是相对路径,可以使⽤绝对路径配置。
root html;
# 默认的⻚⾯⽂件名称
index index.html index.htm;
}
# 错误⻚⾯的⽂件名称
error_page 500 502 503 504 /50x.html;
# location处理对应的不同错误码的⻚⾯定义到/50x.html,这个跟对应其server中定义的⽬录下。
location = /50x.html {
#定义默认⻚⾯所在的⽬录
root html;
}
}
# 和邮件相关的配置
#mail {
# ...
# } mail 协议相关配置段
# tcp代理配置,1.9版本以上⽀持
#stream {
# ...
# } stream 服务器相关配置段
# 导⼊其他路径的配置⽂件
#include /apps/nginx/conf.d/*.conf
}
3.2 Nginx全局配置
# 启动Nginx⼯作进程的⽤⼾和组
user nginx nginx;
# 启动Nginx⼯作进程的数量
worker_processes [number | auto];
# 错误⽇志记录配置,语法:error_log file [debug | info | notice | warn | error | crit |
alert | emerg]
# error_log logs/error.log;
# error_log logs/error.log notice;
error_log /apps/nginx/logs/error.log error;
# pid⽂件保存路径
pid /apps/nginx/logs/nginx.pid;
# ⼯作进程nice值,-20~19
worker_priority 0;
# 这个数字包括Nginx的所有连接(例如与代理服务器的连接等),⽽不仅仅是与客⼾端的连接,另⼀个考虑因素是实际的并发# 连接数不能超过系统级别的最⼤打开⽂件数的限制.
worker_rlimit_nofile 65536;
# 前台运⾏Nginx服务⽤于测试、docker等环境。
daemon off;
# 是否开启Nginx的master-woker⼯作模式,仅⽤于开发调试场景。
master_process off|on;
# 事件模型配置参数
events {
# 设置单个⼯作进程的最⼤并发连接数
worker_connections 65536;
# 使⽤epoll事件驱动,Nginx⽀持众多的事件驱动,⽐如select、poll、epoll,只能设置在events模块中设置。
use epoll;
# 优化同⼀时刻只有⼀个请求⽽避免多个睡眠进程被唤醒的设置,on为防⽌被同时唤醒默认为off,全部唤醒的过程也成 # 为"惊群",因此nginx刚安装完以后要进⾏适当的优化。
accept_mutex on;
# Nginx服务器的每个⼯作进程可以同时接受多个新的⽹络连接,但是需要在配置⽂件中配置,此指令默认为关闭,即默认 # 为⼀个⼯作进程只能⼀次接受⼀个新的⽹络连接,打开后⼏个同时接受多个。
multi_accept on;
}
3.3 http详细配置
http {
# 导⼊⽀持的⽂件类型
include 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 logs/access.log main;
# ⾃定义优化参数
# 实现⽂件零拷⻉
sendfile on;
# 在开启了sendfile的情况下,合并请求后统⼀发送给客⼾端。
#tcp_nopush on;
# 在开启了keepalived模式下的连接是否启⽤TCP_NODELAY选项,当为off时,延迟0.2s发送,默认On时,不延迟发
# 送,⽴即发送⽤⼾相应报⽂。
#tcp_nodelay off;
#keepalive_timeout 0;
# 设置会话保持时间
keepalive_timeout 65 65;
# 开启⽂件压缩
#gzip on;
server {
# 设置监听地址和端⼝
listen 80;
# 设置server name,可以以空格隔开写多个并⽀持正则表达式,如*.magedu.com www.magedu.*
# www.(site\d+)\.magedu\.com$ default_server
server_name localhost;
# 设置编码格式,默认是俄语格式,可以改为utf-8
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html; #定义错误⻚⾯
location = /50x.html {
root html;
}
# 拒绝web形式访问指定⽂件,如很多的⽹站都是通过.htaccess⽂件来改变⾃⼰
# 的重定向等功能。
#location ~ /\.ht {
# deny all;
#}
location ~ /passwd.html {
deny all;
}
}
3.4 root与alias
root:指定web的家目录,在定义location的时候,文件的绝对路径等于 root+location,如:
server {
listen 80;
server_name www.magedu.net;
location / {
root /data/nginx/html/pc;
}
location /about {
#必须要在html目录中创建一个about目录才可以访问,否则报错。
root /data/nginx/html/pc;
index index.html;
}
}
[root@s2 ~]# mkdir /data/nginx/html/pc/about
[root@s2 ~]# echo about > /data/nginx/html/pc/about/index.html
重启Nginx并访问测试
alias:定义路径别名,会把访问的路径重新定义到其指定的路径,如:
server {
listen 80;
server_name www.magedu.net;
location / {
root /data/nginx/html/pc;
}
# 使用alias的时候uri后面如果加了斜杠则下面的路径配置必须加斜杠,否则403
location /about {
# 当访问about的时候,会显示alias定义的/data/nginx/html/pc里面的内容。
alias /data/nginx/html/pc;
index index.html;
}
}
重启Nginx并访问测试
3.5 location的详细使用
在没有使用正则表达式的时候,nginx会先在server中的多个location选取匹配度最高的一个uri,uri是用户请求的 字符串,即域名后面的web文件路径,然后使用该location模块中的正则url和字符串,如果匹配成功就结束搜索, 并使用此location处理此请求。
语法规则: location [=|~|~*|^~] /uri/ { … }
= # 用于标准uri前,需要请求字串与uri精确匹配,如果匹配成功就停止向下匹配并立即处理请求。
~ # 用于标准uri前,表示包含正则表达式并且区分大小写,并且匹配
!~ # 用于标准uri前,表示包含正则表达式并且区分大小写,并且不匹配
~* # 用于标准uri前,表示包含正则表达式并且不区分大写,并且匹配
!~* # 用于标准uri前,表示包含正则表达式并且不区分大小写,并且不匹配
^~ # 用于标准uri前,表示包含正则表达式并且匹配以什么开头
$ # 用于标准uri前,表示包含正则表达式并且匹配以什么结尾
\ # 用于标准uri前,表示包含正则表达式并且转义字符。可以转. * ?等
* # 用于标准uri前,表示包含正则表达式并且代表任意长度的任意字符
范例:
location = / {
[ configuration A ]
}
location / {
[ configuration B ]
}
location /documents/ {
[ configuration C ]
}
location ^~ /images/ {
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}
“ /
”请求将匹配配置A,“ /index.html
”请求将匹配配置B,“ /documents/document.html
”请求将匹配配置C,“ /images/1.gif
”请求将匹配配置D,“ /documents/1.jpg
”请求将匹配配置E。
location优先级:
-
(location 路径名) > (location =) > (location ^~ 路径) > (location ,* 正 则顺序) > (location 部分起始路径) > (/)
-
= /
则将其指定为location
指令的参数可加快处理速度,因为在第一次比较后会停止对匹配项的搜索。 -
https://docs.nginx.com/nginx/admin-guide/web-server/web-server/#location_priority
3.6 Nginx 四层访问控制
访问控制基于模块ngx_http_access_module实现,可以通过匹配客⼾端源IP地址进⾏限制。
location /about {
alias /data/nginx/html/pc;
index index.html;
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
# 先允许⼩部分,再拒绝⼤部分
deny all;
}
3.7 ⾃定义错误⻚⾯
listen 80;
server_name www.edu.com;
error_page 500 502 503 504 404 /error.html;
location = /error.html {
/data/nginx/html/PC;
}
重启nginx并访问不存在的⻚⾯进⾏测试
3.8 ⾃定义访问⽇志路径
[root@s2 ~]# mkdir /data/nginx/logs
listen 80;
server_name www.magedu.net;
# 默认⽬录下⾯创建error.html⻚⾯
error_page 500 502 503 504 404 /error.html;
access_log /data/nginx/logs/access.log;
error_log /data/nginx/logs/error.log;
location = /error.html {
root html;
}
重启nginx并访问不存在的⻚⾯进⾏测试并验证是在指定⽬录⽣成新的⽇志⽂件
3.9 文件操作优化
aio on | off | threads[=pool];
directio size | off;
# 是否缓存打开过的⽂件信息
open_file_cache off;
open_file_cache max=N [inactive=time];
# nginx可以缓存以下三种信息:
# (1) ⽂件元数据:⽂件的描述符、⽂件⼤⼩和最近⼀次的修改时间
# (2) 打开的⽬录结构
# (3) 没有找到的或者没有权限访问的⽂件的相关信息
# max=N:可缓存的缓存项上限数量;达到上限后会使⽤LRU(Least recently used,最近最少使⽤)算法实现管理
# inactive=time:缓存项的⾮活动时⻓,在此处指定的时⻓内未被命中的或命中的次数少于open_file_cache_min_uses 指令所指定的次数的缓存项即为⾮活动项,将被删除
open_file_cache_errors on | off;
# 是否缓存查找时发⽣错误的⽂件⼀类的信息
# 默认值为off
open_file_cache_min_uses number;
# open_file_cache指令的inactive参数指定的时⻓内,⾄少被命中此处指定的次数⽅可被归类为活动项默认值为1
open_file_cache_valid time;
# 缓存项有效性的检查验证频率,默认值为60s
# 隐藏Nginx server版本。
server_tokens off;
open_file_cache
配置范例
# 最⼤缓存10000个⽂件,⾮活动数据超时时⻓60s
open_file_cache max=10000 inactive=60s;
# 每间隔60s检查⼀下缓存数据有效性
open_file_cache_valid 60s;
# 60秒内⾄少被命中访问5次才被标记为活动数据
open_file_cache_min_uses 5;
# 缓存错误信息
open_file_cache_errors on;
4 Nginx高级配置
4.1 状态页
基于nginx模块ngx_http_auth_basic_module实现,在编译安装nginx的时候需要添加编译参数--with http_stub_status_module,否则配置完成之后监测会是提⽰语法错误。
配置⽰例:
location /nginx_status {
stub_status;
allow 192.168.0.0/16;
allow 127.0.0.1;
deny all;
}
输出信息⽰例:
Active connections: 2
server accepts handled requests
71 71 89
Reading: 0 Writing: 1 Waiting: 1
Active connections: 当前处于活动状态的客⼾端连接数,包括连接等待空闲连接数。
accepts:统计总值,Nginx⾃启动后已经接受的客⼾端请求的总数。
handled:统计总值,Nginx⾃启动后已经处理完成的客⼾端请求的总数,通常等于accepts,除⾮有worker_connections 限制等被拒绝的连接。
requests:统计总值,Nginx⾃启动后客⼾端发来的总的请求数。
Reading:当前状态,正在读取客⼾端请求报⽂⾸部的连接的连接数。
Writing:当前状态,正在向客⼾端发送响应报⽂过程中的连接数。
Waiting:当前状态,正在等待客⼾端发出请求的空闲连接数,开启 keep-alive的情况下,这个值等于 active - (reading+writing)
4.2 Nginx ⾃定义访问⽇志
访问⽇志是记录客⼾端即⽤⼾的具体请求内容信息,全局配置模块中的error_log是记录nginx服务器运⾏时的⽇志 保存路径和记录⽇志的level,因此有着本质的区别,⽽且Nginx的错误⽇志⼀般只有⼀个,但是访问⽇志可以在不 同server中定义多个,定义⼀个⽇志需要使⽤access_log指定⽇志的保存路径,使⽤log_format指定⽇志的格式, 格式中定义要保存的具体⽇志内容。
4.2.1 ⾃定义默认格式⽇志
如果是要保留⽇志的源格式,只是添加相应的⽇志内容,则配置如下:
log_format nginx_format1 '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';
access_log logs/access.log nginx_format1;
# 重启nginx并访问测试⽇志格式
==> /apps/nginx/logs/access.log <==
192.168.0.1 - - [22/Feb/2019:08:44:14 +0800] "GET /favicon.ico HTTP/1.1" 404 162 "-"
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/2
0100101 Firefox/65.0" "-"www.magedu.net:80
4.2.2 ⾃定义json格式⽇志
Nginx 的默认访问⽇志记录内容相对⽐较单⼀,默认的格式也不⽅便后期做⽇志统计分析,⽣产环境中通常将 nginx⽇志转换为json⽇志,然后配合使⽤ELK做⽇志收集-统计-分析。
log_format access_json '{"@timestamp":"$time_iso8601",'
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'
'"referer":"$http_referer",'
'"tcp_xff":"$proxy_protocol_addr",'
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
access_log /apps/nginx/logs/access_json.log access_json;
4.3 https 功能
4.3.1 ssl 配置参数
nginx 的https 功能基于模块ngx_http_ssl_module实现,因此如果是编译安装的nginx要使⽤参数 ngx_http_ssl_module开启ssl功能,但是作为nginx的核⼼功能,yum安装的nginx默认就是开启的,编译安装的 nginx需要指定编译参数--with-http_ssl_module开启,官⽅⽂档: https://nginx.org/en/docs/http/ngx_http_ssl_ module.html,配置参数如下:
# 为指定的虚拟主机配置是否启⽤ssl功能,此功能在1.15.0废弃,使⽤listen [ssl]替代。
ssl on | off;
# 当前虚拟主机使⽤使⽤的公钥⽂件,⼀般是crt⽂件
ssl_certificate /path/to/file;
# 当前虚拟主机使⽤的私钥⽂件,⼀般是key⽂件
ssl_certificate_key /path/to/file;
# ⽀持ssl协议版本,早期为ssl,现在是TSL,默认为后三个
ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
# 配置ssl缓存
ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
off: 关闭缓存
none: 通知客⼾端⽀持ssl session cache,但实际不⽀持
builtin[:size]:使⽤OpenSSL内建缓存,为每worker进程私有
[shared:name:size]:在各worker之间使⽤⼀个共享的缓存,需要定义⼀个缓存名称和缓存空间⼤⼩,⼀兆可以存储 4000个会话信息,多个虚拟主机可以使⽤相同的缓存名称。
# 客⼾端连接可以复⽤ssl session cache中缓存的有效时⻓,默认5m
ssl_session_timeout time;
范例:
listen 80;
listen 443 ssl;
ssl_certificate /apps/nginx/certs/www.magedu.net.crt;
ssl_certificate_key /apps/nginx/certs/www.magedu.net.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
4.3.2 实现多域名HTTPS
Nginx⽀持基于单个IP实现多域名的功能,并且还⽀持单IP多域名的基础之上实现HTTPS,其实是基于Nginx的 SNI(Server Name Indication)功能实现,SNI是为了解决⼀个Nginx服务器内使⽤⼀个IP绑定多个域名和证书的 功能,其具体功能是客⼾端在连接到服务器建⽴SSL链接之前先发送要访问站点的域名(Hostname),这样服务 器再根据这个域名返回给客⼾端⼀个合适的证书。
# ⾃签名CA证书
[root@nginx nginx]# mkdir certs
[root@nginx nginx]# cd certs/
# 生成CA私钥同是进行自签名
[root@nginx ~]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -days 3650 -out ca.crt
[root@nginx certs]# openssl x509 -in ca.crt -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
f6:08:df:9e:15:7e:67:82
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=hunan, L=changsha, O=Default Company Ltd
# 为其他人制作颁发证书
# 首先生成key和csr文件
[root@nginx certs]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout edu.key -out edu.crs
Generating a 4096 bit RSA private key
..............................................................................................................................................................................................................................................................................................................................................++
writing new private key to 'edu.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:hunan
Locality Name (eg, city) [Default City]:changsha
Organization Name (eg, company) [Default Company Ltd]:ykt
Organizational Unit Name (eg, section) []:jishu
Common Name (eg, your name or your server's hostname) []:01
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@nginx certs]# ls
ca.crt ca.key edu.crs edu.key
# 颁发证书
[root@nginx certs]# openssl x509 -req -days 3650 -in edu.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out edu.crt
Signature ok
subject=/C=CN/ST=hunan/L=changsha/O=ykt/OU=jishu/CN=01
Getting CA Private Key
# 验证证书内容
[root@nginx certs]# openssl x509 -in edu.crt -noout -text
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
8e:d0:11:e1:3d:01:69:b2
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=hunan, L=changsha, O=Default Company Ltd
Validity
Not Before: Nov 21 13:20:32 2021 GMT
Not After : Nov 19 13:20:32 2031 GMT
Subject: C=CN, ST=hunan, L=changsha, O=ykt, OU=jishu, CN=01
# Nginx配置
[root@nginx certs]# vim /apps/nginx/conf.d/location.conf
server {
listen 443 ssl;
server_name www.edu.com;
ssl_certificate /apps/nginx/certs/edu.crt;
ssl_certificate_key /apps/nginx/certs/edu.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
root html;
index index.html index.htm;
}
location /test {
root /data/nginx/html/PC;
index index.html;
}
location /python {
root /data/nginx/mobile/html;
index index.html index.htm;
}
}
# 测试能否访问
5 Nginx Rewrite相关功能
Nginx服务器利⽤ngx_http_rewrite_module 模块解析和处理rewrite请求,此功能依靠 PCRE(perl compatible regularexpression),因此编译之前要安装PCRE库,rewrite是nginx服务器的重要功能之⼀,⽤于实现URL的重 写,URL的重写是⾮常有⽤的功能,⽐如它可以在我们改变⽹站结构之后,不需要客⼾端修改原来的书签,也⽆需 其他⽹站修改我们的链接,就可以设置为访问,另外还可以在⼀定程度上提⾼⽹站的安全性。
5.1 rewrite指令
通过正则表达式的匹配来改变URI,可以同时存在⼀个或多个指令,按照顺序依次对URI进⾏匹配,rewrite主要是 针对⽤⼾请求的URL或者是URI做具体处理,
格式:
rewrite regex replacement [flag];
5.1.1 rewrite flag介绍
利⽤nginx的rewrite的指令,可以实现url的重新跳转,rewrtie有四种不同的flag,分别是redirect(临时重定向)、 permanent(永久重定向)、break和last。其中前两种是跳转型的flag,后两种是代理型,跳转型是指有客⼾端浏览 器重新对新地址进⾏请求,代理型是在WEB服务器内部实现跳转的。
last
- 重写完成后停⽌对当前URI在当前location中后续的其它重写操作,⽽后对新的URL启动新⼀轮重写检查,不建议在 location中使⽤
break
- 重写完成后停⽌对当前URL在当前location中后续的其它重写操作,⽽后直接将匹配结果返还给客⼾端即结束循环并 返回数据给客⼾端,建议在location中使⽤
redirect
- 临时重定向,重写完成后以临时重定向⽅式直接返回重写后⽣成的新URL给客⼾端,由客⼾端重新发起请求;使⽤相对 路径,或者http://或https://开头,状态码:302
permanent
- 重写完成后以永久重定向⽅式直接返回重写后⽣成的新URL给客⼾端,由客⼾端重新发起请求,状态码:301,临时重定向不会缓存域名解析记录(A记录),但是永久重定向会缓存。
5.1.2 rewrite案例
临时重定向和永久重定向
location / {
root /data/nginx/html/pc;
index index.html;
rewrite / http://www.taobao.com permanent;
#rewrite / http://www.taobao.com redirect;
}
# 重启Nginx并访问域名www.magedu.net进⾏测试
⾃动跳转https
server {
listen 443 ssl;
listen 80;
ssl_certificate /apps/nginx/certs/www.magedu.net.crt;
ssl_certificate_key /apps/nginx/certs/www.magedu.net.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
server_name www.magedu.net;
location / {
root /data/nginx/html/pc;
index index.html;
# 未加条件判断,会导致死循环
if ($scheme = http ){
rewrite / https://www.magedu.net permanent;
}
}
}
5.2 实现防盗链
location ^~ /images {
root /data/nginx;
index index.html;
# 定义有效的referer
valid_referers none blocked server_names *.magedu.com www.magedu.*
api.online.test/v1/hostlist ~\.google\. ~\.baidu\.;
# 假如是使⽤其他的⽆效的referer访问
if ($invalid_referer) {
# 返回状态码403
return 403;
}
}
6 Nginx 反向代理功能
反向代理:反向代理也叫reverse proxy,指的是代理外⽹⽤⼾的请求到内部的指定web服务器,并将数据返回给⽤ ⼾的⼀种⽅式,这是⽤的⽐较多的⼀种⽅式。
Nginx除了可以在企业提供⾼性能的web服务之外,另外还可以将本⾝不具备的请求通过某种预定义的协议转发⾄ 其它服务器处理,不同的协议就是Nginx服务器与其他服务器进⾏通信的⼀种规范,主要在不同的场景使⽤以下模 块实现不同的功能:
ngx_http_proxy_module: 将客⼾端的请求以http协议转发⾄指定服务器进⾏处理。
ngx_stream_proxy_module:将客⼾端的请求以tcp协议转发⾄指定服务器处理。
ngx_http_fastcgi_module:将客⼾端对php的请求以fastcgi协议转发⾄指定服务器助理。
ngx_http_uwsgi_module:将客⼾端对Python的请求以uwsgi协议转发⾄指定服务器处理。
6.1 http反向代理
6.1.1 反向代理配置参数
# ⽤来设置将客⼾端请求转发给的后端服务器的主机,可以是主机名、IP地址:端⼝的⽅式,也可以代理到预先设置的
# 主机群组,需要模块gx_http_upstream_module⽀持。
proxy_pass;
location /web {
index index.html;
# 不带斜线将访问的/web,等于访问后端服务器 http://192.168.7.103:80/web/index.html,即后端服务
# 器配置的站点根⽬录要有web⽬录才可以被访问,这是⼀个追加/web到后端服务器
# http://servername:port/WEB/INDEX.HTML的操作
proxy_pass http://192.168.7.103:80;
# 带斜线,等于访问后端服务器的http://192.168.7.103:80/index.html 内容返回给客⼾端
proxy_pass http://192.168.7.103:80/;
}
# ⽤于nginx作为反向代理的时候,在返回给客⼾端http响应的时候,隐藏后端服务版本相应头部的信息,可以设置在
# http/server或location块,
proxy_hide_header field;
location /web {
index index.html;
proxy_pass http://192.168.7.103:80/;
proxy_hide_header ETag;
}
# 默认nginx在响应报⽂中不传递后端服务器的⾸部字段Date, Server, X-Pad, X-Accel等参数,如果要传递的
# 话则要使⽤ proxy_pass_header field声明将后端服务器返回的值传递给客⼾端。
proxy_pass_header field;
# 是否向后端服务器发送HTTP包体部分,可以设置在http/server或location块,默认即为开启
proxy_pass_request_body on | off;
# 是否将客⼾端的请求头部转发给后端服务器,可以设置在http/server或location块,默认即为开启
proxy_pass_request_headers on | off;
# 可以更改或添加客⼾端的请求头部信息内容并转发⾄后端服务器,⽐如在后端服务器想要获取客⼾端的真实IP的时
# 候,就要更改每⼀个报⽂的头部,如下:
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header;
# 添加HOST到报⽂头部,如果客⼾端为NAT上⽹那么其值为客⼾端的共⽤的公⽹IP地址,常⽤于在⽇之中记录客⼾端的
# 真实IP地址。
proxy_set_header X-Forwarded-For $remote_addr;
# 配置nginx服务器与后端服务器尝试建⽴连接的超时时间,默认为60秒,⽤法如下:
proxy_connect_timeout time;
# 60s为⾃定义nginx与后端服务器建⽴连接的超时时间
proxy_connect_timeout 60s;
# 配置nginx服务器向后端服务器或服务器组发起read请求后,等待的超时时间,默认60s
proxy_read_time time;
# 配置nginx项后端服务器或服务器组发起write请求后,等待的超时时间,默认60s
proxy_send_time time;
# ⽤于设置nginx提供代理服务的HTTP协议的版本,默认http 1.0
proxy_http_version 1.0;
# 当客⼾端⽹络中断请求时,nginx服务器中断其对后端服务器的请求。即如果此项设置为on开启,则服务器会忽略客
# ⼾端中断并⼀直等着代理服务执⾏返回,如果设置为off,则客⼾端中断后Nginx也会中断客⼾端请求并⽴即记录499⽇
# 志,默认为off。
proxy_ignore_client_abort off;
# 当配置了 proxy_hide_header和proxy_set_header的时候,⽤于设置nginx保存HTTP报⽂头的hash表的上限。
proxy_headers_hash_bucket_size 128;
# 设置proxy_headers_hash_bucket_size的最⼤可⽤空间
proxy_headers_hash_max_size 512;
# server_name hash表申请空间⼤⼩
server_namse_hash_bucket_size 512;
# 设置服务器名称hash表的上限⼤⼩
server_names_hash_max_szie 512;
6.2 使用FastCGI实现反向代理
FastCGI
我们知道Nginx是无法直接运行Java、PHP这种文件的,它需要将这种类型的请求转发给第三方的应用程序,而CGI正是一种对接应用程序和网络服务器的接口协议。CGI提供了一个接口使外部程序(如PHP程序)与Web服务器(Nginx、Apache)之间能够进行交互。
当CGI程序运行在独立的进程中,并对每个Web请求创建一个进程,在结束时销毁。在进程不断创建和关闭过程中会产生很大开销,为了解决这一缺点,产生了FastCGI。
FastCGI每次处理完请求 之后不会关闭掉进程,而是保留这个进程,使这个进程可以处理多个请求。这样的话每个请求都不用再重新创建一 个进程了,大大提升了处理效率。
PHP-FPM
PHP-FPM(FastCGI Process Manager:FastCGI进程管理器)是一个实现了Fastcgi的管理程序, 并且提供进程管理的功能,进程包括master进程和worker进程,master进程只有一个,负责监听端口,接受来自 web server的请求。worker进程一般会有多个,每个进程中会嵌入一个PHP解析器,进行PHP代码的处理。
6.2.1 FastCGI配置指令
Nginx基于模块ngx_http_fastcgi_module实现通过fastcgi协议将指定的客⼾端请求转发⾄php-fpm处理
# 转发请求到后端服务器,address为后端的fastcgi server的地址,可⽤位置:location, if in location
fastcgi_pass address;
# 设置传递给FastCGI服务器的参数值,可以是⽂本,变量或组合,可⽤于将Nginx的内置变量赋值给⾃定义key。这些参数值若未设置则默认会从conf/fastcgi文件中设置继承
fastcgi_param parameter value [if_not_empty];
6.2.2 FastCGI⽰例(同一服务器)
php环境准备
# 安装启动PHP
[root@nginx nginx]# yum -y install php-fpm
[root@nginx nginx]# systemctl start php-fpm
# PHP配置
[root@nginx nginx]# vim /etc/php-fpm.d/www.conf
# 这里只是简单测试,所以只简单修改用户和组即可
user = nginx
group = nginx
# 重启PHP服务
[root@nginx nginx]# systemctl restart php-fpm
准备PHP测试页面
[root@nginx nginx]# mkdir /data/nginx/php
[root@nginx nginx]# cat /data/nginx/php/index.php
<?php
phpinfo()
?>
配置Nginx转发
Nginx安装完成之后默认⽣成了与fastcgi的相关配置⽂件,⼀般保存在nginx的安装路径的conf⽬录当中,⽐ 如/apps/nginx/conf/fastcgi.conf、/apps/nginx/conf/fastcgi_params。
location ~ \.php$ {
root /data/nginx/php;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# 如果SCRIPT_FILENAME是绝对路径则可以省略root /data/nginx/php;
#fastcgi_param SCRIPT_FILENAME /data/nginx/php$fastcgi_script_name;
include fastcgi_params;
}
# 重新加载配置文件
[root@nginx nginx]# sbin/nginx -s reload
测试能否访问
7 LNMP实现word--press
Nginx(1.20.1): https://nginx.org/en/download.html
Mysql(5.7.10):https://downloads.mysql.com/archives/community/
Worldpress(5.8.2):https://cn.wordpress.org/download/#download-install
PHP(7.4.26):https://www.php.net/downloads
部署规划:
192.168.10.207:Nginx php-fpm 运行web服务
192.168.10.208: 运行Mysql数据库
7.1 部署数据库
7.1.1 二进制安装数据库
下载二进制包
[root@localhost src]# ls
mysql-5.7.10-linux-glibc2.5-x86_64.tar.gz
# 创建用户和组
[root@mysql src]# groupadd -r -g 306 mysql
[root@mysql src]# useradd -r -g 306 -u 306 -d /data/mysql -s /bin/false mysql
[root@mysql src]# getent passwd mysql
mysql:x:306:306::/data/mysql:/bin/false
# 准备二进制文件
[root@mysql src]# tar xf mysql-5.7.10-linux-glibc2.5-x86_64.tar.gz
[root@mysql src]# ln -sv mysql-5.7.10-linux-glibc2.5-x86_64 mysql
‘mysql’ -> ‘mysql-5.7.10-linux-glibc2.5-x86_64’
[root@mysql src]# cp !* /etc/init.d/mysqld
cp mysql/support-files/mysql.server /etc/init.d/mysqld
[root@mysql src]# cat /etc/my.cnf
[mysqld]
datadir=/data/mysql
skip_name_resolve=1
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
includedir /etc/my.cnf.d
[root@mysql src]# chown -R root.root /usr/local/src/mysql/
[root@mysql src]# mkdir /data
[root@mysql src]# /usr/local/src/mysql/bin/mysqld --initialize --user=mysql
[root@mysql src]# ls /data/mysql/
auto.cnf ib_buffer_pool ibdata1 ib_logfile0 ib_logfile1 mysql mysql.log performance_schema sys
# mysqld文件默认启动路径在/usr/local中,需修改
[root@mysql src]# vim /etc/init.d/mysqld
[root@mysql src]# /etc/init.d/mysqld start
# 修改初始的临时密码,在mysqllog中查看系统随机生成的临时密码,若使用mysqld --initialize-insecure不会root 生成密码
# 创建数据库
[root@mysql ~]# mysql -uroot -p'database'
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.10 MySQL Community Server (GPL)
Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> CREATE DATABASE wordpress;
Query OK, 1 row affected (0.00 sec)
mysql> grant all privileges on wordpress.* to "wordpress"@"192.168.10.%" identified by "123321";
Query OK, 0 rows affected, 1 warning (0.00 sec)
7.1.2 测试能否从nginx主机访问
[root@nginx src]# mysql -uwordpress -h192.168.10.208 -p
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MySQL connection id is 6
Server version: 5.7.10 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
7.2 部署PHP
7.2.1 编译安装PHP
[root@nginx src]# ls
nginx-1.20.1 nginx-1.20.1.tar.gz php-7.4.26 php-7.4.26.tar.gz
# 安装依赖包
[root@nginx src]# yum -y install wget vim pcre pcre-devel openssl openssl-devel libicu-devel gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel glib2 glib2-devel ncurses ncurses-devel curl curl-devel krb5-devel libidn libidn-devel openldap openldap-devel nss_ldap jemalloc-devel cmake boost-devel bison automake libevent libevent-devel gd gddevel libtool* libmcrypt libmcrypt-devel mcrypt mhash libxslt libxslt-devel readline readline-devel gmp gmp-devel libcurl libcurl-devel openjpeg-devel
# 编译PHP
[root@nginx src]# cd php-7.4.26/
[root@nginx php-7.4.26]# ./configure --prefix=/apps/php --enable-fpm --with-fpm-user=www --with-fpm-group=www --with-pear --with-curl --with-iconv --with-mhash --with-zlib --with-xmlrpc --with-xsl --with-openssl --with-mysqli --with-pdo-mysql --disable-debug --enable-sockets --enable-soap --enable-inline-optimization --enable-xml --enable-ftp --enable-exif --enable-bcmath --enable-calendar --enable-shmop --enable-dba --enable-sysvsem --enable-sysvshm --enable-sysvmsg
[root@nginx php-7.4.26]# make -j 8
[root@nginx php-7.4.26]# make install
7.2.2 配置PHP
[root@nginx php-7.4.26]# cd /apps/php/etc/php-fpm.d
[root@nginx php-fpm.d]# cp www.conf.default www.conf
[root@nginx php-fpm.d]# cp /usr/local/src/php-7.4.26/php.ini-development /apps/php/php.ini
[root@nginx php-fpm.d]# useradd www -s /sbin/nologin -u 1001
[root@nginx php-fpm.d]# grep -v ";" www.conf | grep -v "^$"
[www]
user = www
group = www
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 50
pm.start_servers = 30
pm.min_spare_servers = 30
pm.max_spare_servers = 35
pm.status_path = /status
ping.path = /ping
ping.response = pong
access.log = log/$pool.access.log
slowlog = log/$pool.log.slow
[root@nginx php-fpm.d]# mkdir /apps/php/log/
[root@nginx php-fpm.d]# cd /apps/php/etc/
[root@nginx etc]# cp php-fpm.conf.default php-fpm.conf
7.2.3 启动PHP
# 验证PHP配置语法
[root@nginx etc]# /apps/php/sbin/php-fpm -t
[27-Nov-2021 12:07:15] NOTICE: configuration file /apps/php/etc/php-fpm.conf test is successful
# 启动PHP
[root@nginx etc]# /apps/php/sbin/php-fpm -c /apps/php/php.ini
[root@nginx etc]# ps -aux | grep php-fpm
root 25540 0.2 0.0 217952 6428 ? Ss 12:07 0:00 php-fpm: master process (/apps/php/etc/php-fpm.conf)
www 25541 0.0 0.0 217952 5844 ? S 12:07 0:00 php-fpm: pool www
[root@nginx etc]# netstat -tanlp | grep php-fpm
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN 25540/php-fpm: mast
7.3 Nginx部署
Nginx 源码安装此处不再重复,这里主要对Nginx进行相关配置
[root@nginx etc]# grep -v "^#" /apps/nginx/conf.d/location.conf
server {
listen 80;
server_name www.edu.com;
error_page 500 502 503 504 404 /error.html;
location / {
root /data/nginx/wordpress;
index index.php index.html index.htm;
}
location ~ \.php$ {
root /data/nginx/wordpress;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fastcgi_param SCRIPT_FILENAME /data/nginx/php$fastcgi_script_name;
include fastcgi_params;
}
}
7.4 部署wordpress
[root@nginx nginx]# cd /data/nginx/wordpress/
[root@nginx wordpress]# tar -xf wordpress-5.8.2-zh_CN.tar.gz
[root@nginx wordpress]# ls
wordpress wordpress-5.8.2-zh_CN.tar.gz
[root@nginx wordpress]# mv wordpress/* .
[root@nginx wordpress]# cp wp-config-sample.php wp-config.php
[root@nginx wordpress]# vim wp-config.php
[root@nginx wordpress]# chown www.www /data/nginx/wordpress/ /apps/nginx/ -R
[root@nginx wordpress]# /apps/nginx/sbin/nginx -s reload
测试访问页面
http://www.edu.com/wp-admin/install.php
文档参考链接:
从操作系统层面了解Linux网络IO模型:https://developpaper.com/understanding-the-network-io-model-under-linux-from-the-operating-system-level/
IO多路复用:https://notes.shichao.io/unp/ch6/
IO模型:https://rickhw.github.io/2019/02/27/ComputerScience/IO-Models/
Nginx原理:http://ningg.top/nginx-series-principle/
Nginx开发从入门到精通:http://tengine.taobao.org/book/index.html
Nginx架构:https://www.aosabook.org/en/nginx.html
MIME参考⽂档:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Basics_of_HTTP/MIME_Types