每次IO,都要经过两个阶段:
nginx ——》 kernel——》index.html(磁盘)
index.html(磁盘)——》kernel的缓冲区——》nginx的缓冲区
同步/异步:关注的是消息通信机制
阻塞/非阻塞:关注调用者在等待结果返回之前所处的状态
I/O模型:阻塞型、非阻塞型、复用型、信号驱动型、异步
同步阻塞IO模型
即 从磁盘上把文件复制到内核,内核再把数据复制到用户空间的缓冲区中,然后再返回个成功的结果。 在这期间什么都干不了,阻塞状态
同步非阻塞IO模型
IO多路复用
Nginx是免费,开元,高性能的HTTP和反向代理服务器,邮件代理服务器,通用TCP/UDP代理服务器
官网:http://nginx.org
特性
基本功能
web服务相关的功能
正向代理和反向代理
Nginx 是epol,Apache 是 select
Nginx 的高并发得益于其采用了 epoll 模型,与传统的服务器程序架构不同,epoll 是Linux 内核 2.6 以后才出现的,Nginx 采用 epoll 模型,异步非阻塞,而 apache 采用的是select 模型
Nginx 默认以 80 端口监听在服务器上,并且启动一个 master 进程,同时有 master 进程生成多个工作进程,当浏览器发起一个 HTTP 连接请求,每个进程都有可能处理这个连接,
怎么做到的呢?怎么保证同一时刻一个 HTTP 请求被一个工作进程处理呢
首先每个 worker 进程都是从 Master 进程 fork 出来,在 Master 进程里面,建立好需要listen 的 socket(listenfd)之后,会 fork 出多个 worker 进程。
所有 worker 进程的 listenfd 会在新连接到来时变得可读,为保证只有一个进程处理该连接,所有 worker 进程在注册 listenfd 读事件前抢 accept_mutex,抢到互斥锁的那个进程注册 listenfd 读事件,在读事件里调用 accept 接受该连接。
当一个 worker 进程在 accept 这个连接之后,就开始读取请求、解析请求、处理请求,产生数据后,再返回给客户端,最后才断开连接,这样形成一个完整的请求流程。如图
从功能上分为如下三类。
Nginx 由内核和模块组成,其中内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端的请求映射到一个 location block,而 location 是 Nginx配置中的一个指令,用于访问的 URL 匹配,而在这个 location 中所配置的每个指令将会启动不同的模块去完成相应的工作
#cd /etc/yum.repos.d/
#vim nginx.repo
#yum info nginx
#yum install nginx
源码编译安装:
编译安装nginx选项:
__________
Nginx WEB 服务器定期更新,如果需要将低版本升级或者将高版本降级,升级或者降级
方法如下,分为四个步骤,包括软件下载、预编译、编译、配置,具体方法如下:
wget http://www.nginx.org/download/nginx-1.16.0.tar.gz
获取旧版本 nginx 的 configure 选项
/usr/local/nginx/sbin/nginx -V
编译新版本的 Nginx
tar -xvf nginx-1.16.0.tar.gz
cd nginx-1.16.0
./configure --prefix=/usr/local/nginx --user=www --group=www
--with-http_stub_status_module --with-http_ssl_module
make
备份旧版本的 nginx 可执行文件,复制新版本的 nginx 这行文件
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.old
cp objs/nginx /usr/local/nginx/sbin/
测试新版本 nginx 是否正常
/usr/local/nginx/sbin/nginx -t
平滑重启升级 nginx
kill –QUIT `cat /usr/local/nginx/log/nginx.oldbin` ##关闭旧版 nginx
验证 nginx 是否升级成功
/usr/local/nginx/sbin/nginx -V 显示最新编译的版本信息即可。
#平滑启动 nginx
kill -HUP cat /var/run/nginx.pid
或者
nginx -s reload
其中进程文件路径在配置文件 nginx.conf 中可以找到。
平滑启动的意思是在不停止 nginx 的情况下,重启 nginx,重新加载配置文件,启动新的工作线程,完美停止旧的工作线程。
#查看 nginx 进程
ps -ef|grep nginx
#完美停止 nginx
kill -QUIT `cat /var/run/nginx.pid`
#快速停止 nginx
kill -TERM `cat /var/run/nginx.pid`
或者
kill -INT `cat /var/run/nginx.pid`
#完美停止工作进程(主要用于平滑升级)
kill -WINCH `cat /var/run/nginx.pid`
#强制停止 nginx
pkill -9 nginx
#检查对 nginx.conf 文件的修改是否正确
nginx -t -c /etc/nginx/nginx.conf 或者 nginx -t
#停止 nginx 的命令
nginx -s stop 或者 pkill nginx
#查看 nginx 的版本信息
nginx -v
#查看完整的 nginx 的配置信息
nginx -V
配置文件的组成部分:
主配置文件:nginx.conf
子配置文件:include conf.d/*.conf
fastcgi,uwsgi,scgi等协议相关的配置文件
mime.types:支持的mime类型
主配置文件的配置指令:directive value [value2 …];
注意:
(1)指令必须以分号结尾
(2)支持使用配置变量
内建变量:由Nginx模块引入,可直接引用
自定义变量:由用户使用set命令定义。 set variable_name value;
引用变量:$variable_name
http协议的相关配置:
http{
... ...
server{
...
server_name
root
location [OPERATORR] /uri/{
...
}
}
server{
...
}
}
ngx_http_core_module 帮助文档:http://nginx.org/en/docs/ngx_core_module.html
ngx_http_core_module
与套接字相关的配置:
1、server{
...} 在http块
配置一个虚拟主机
server{
listen address[:PORT]|PORT;
server_name SERVER_NAME;
root /PATH/TO/DUCUMENT_ROOT;
}
include /etc/nginx/conf.d/vhosts/*.conf;
server{
listen 8080;
//加上default就是默认,不加就按vhosts目录下的文件顺序找。
//listen 80 default_server; listen IP地址:80 default_server
server_name www.b.com;
root /data/siteb;
}
2、listen PORT|address[:port]|unix:/PATH/TO/SOCKET_FILE
listen address[:port][default_server][ssl][http2|spdy][backlog=number][rcvbuf=size][sndbuf=size]
default_server 设定为默认虚拟主机
ssl 限制仅能够通过ssl连接提供服务
backlog=number 超过并发连接数后,新请求进入后援队列的长度
rcvbuf=size 接收缓冲区大小
sndbuf=size 发送缓冲区大小
注意:
(1)基于port;
listen PORT; 指令监听在不同的端口
(2)基于ip的虚拟主机
listen IP:PORT; IP地址不同
(3)基于hostname
server_name fqdn; 指令指向不同的主机名
3、server_name name...;
虚拟主机的主机名称后可跟多个由空白字符分隔的字符串
支持*通配任意长度的任意字符
server_name *.abc.com www.abc.*
支持~起始的字符做正则表达式模式匹配,性能原因慎用(要计算匹配,最好精确)
server_name ~^www\d+\.abc\.com$
说明:\d 表示[0-9]
匹配优先级机制从高到低:
(1)首先是字符串精确匹配 如:www.abc.com
(2)右侧*通配符 如:*.abc.com
(3)右侧*通配符 如:www.abc.*
(4)正则表达式 如:~^.*\.abc\.com$
(5)default_server
4.tcp_nodelay on|off;
在keepalived模式下的连接是否启用TCP_NODELAY选项
当为off时,延迟发送,合并多个请求后再发送
默认On时,不延迟发送
可用于:http,server,location
5、sendfile on|off
是否启用sendfile功能,在内核中封装报文直接发送
默认off
6、server_tokens on|off|build|string
是否在相应报文的Server首部显示nginx版本
7、root
设置web资源的路径映射;用于指明请求的URL所对应的文档的目录路径,可用于http,server,location,if in location
server{
...
root /data/www/vhosts;
}
示例:http://www.abc.com/images/logo.jpg
-->/data/www/vhosts/images/logo.jpg
访问/images/logo.jpg 相当于访问 /data/www/vhosts/images/logo.jpg
8、location [=|~|~*|^~]uri{
..}
location @name{
..}
放在server块和location块
在一个server中location配置段可存在多个,用于实现从uri到文件系统的路径映射;nginx会根据用户请求的URI来检查定义的所有location,并找出一个最佳匹配,而后应用其配置
示例:
server{
...
server_name www.abc.com;
location /images/{
root /data/imgs/;
}
}
http://www.abc.com/images/logo.jpg
--> /data/imgs/images/logo.jpg
访问images的时候,实际访问的是/data/imgs下的 images
=:对URI做精确匹配;
location = /{
...
}
http://www.abc.com/ 匹配
http://www.abc.com/index.html 不匹配
^~:对URI的最左边部分做匹配检查,不区分字符大小写
~:对URI做正则表达式模式匹配,区分字符大小写
~*:对URI做正则表达式模式匹配,不区分字符大小写
不带符号:匹配起始于此uri的所有uri
匹配优先级从高到低: =,^~,~/~*,不带符号(相当于直接一个杠/)
9.alias
路径别名,文档映射的另一种机制;仅能用于location上下文
示例:
访问 http://www.abc.com/bbs/index.php
location /bbs/{
alias /web/forum/;
} --> /web/forum/index.html 实际访问
location /bbs/{
root /web/forum/;
} --> /web/forum/bbs/index.html 实际访问
注意:location中使用root指令和alias指令的意义不同
(a)root,给定的路径对应于location中的/uri/左侧的/
(b)alias,给定的路径对应location中的/uri/右侧的/
10、index file ...;
指定默认网页文件,注意:ngx_http_index_module模块
11、error_page code .. [=[response]] uri; 在server块
模块:ngx_http_core_module
定义错误页,以指定的响应状态码进行响应
可用位置:http,server,location,if in location
error_page 404 /404.html
error_page 404 = 200 /404.html 访问其实是404,强行把状态改为200
示例:
server{
error_pageg 404 /404.html;
location /404.html{
root /data/sitea/error/;
}
}
#mkdir /data/sirea/error/
vim /data/sitea/error/404.html
12、try_files file ... uri;
try_files file ... = code;
按顺序检查文件是否存在,返回第一个找到的文件或文件夹(结尾加斜线表示为文件夹),如果所有的文件或文件夹都找不到,会进行一个内部重定向到最后一个参数。只有最后一个参数可以引起一个内部重定向,之前的参数只设置内部URI的指向。最后一个参数是回退URI且必须存在,否则会出现内部500错误
location /images/{
//假设找/images/a.jpg,如果没有a.jpg就返回default.gif
try_files $uri /images/default.gif;
}
location /{
try_files $uri $uri/index.html $uri.html = 404;
}
13、keepalive_timeout timeout [header_timeout];
设定保持连接超时时长,0表示禁止长连接,默认为75s
14、keepalive_requests number;
在一次长连接上锁允许请求的资源的最大数量,默认为100
15、keepalive_disable none|broswer...
对哪种浏览器禁用长连接
16、send_timeout time;
向客户端发送响应报文的超时时长,此处是指两次写操作之间的间隔时长,而非整个响应过程的传输时长
17、client_body_buffer_size size;
用于接收每个客户端请求报文的body部分的缓冲区大小;默认为16k;超出此大小时,其将被暂存到磁盘上的由下面client_body_temp_path指令所定义的位置
18、client_body_temp_path path [level1 [level2 [level3]]];
设定存储客户端请求报文的body部分的临时存储路径及子目录结构和数量
目录名为16进制的数字;
client_body_temp_path /var/tmp/client_body 1 2 2
1 1级目录占1位16进制,即2^4=16个目录 0-f
2 2级目录占2位16进制,即2^8=256个目录 00-ff
2 3级目录占2位16进制,即2^8=256个目录 00-ff
19、limit_rate rate;
限制响应给客户端的传输速率,单位是bytes/second
默认值0表示无限制
20、limit_except method ... {
...},仅用于location
限制客户端使用除了指定的请求方法之外的其他方法
method:GET,HEAD,POST,PUT,DELETE
MKCOL,COPY,MOVE,OPTIONS,PROPFIND,
PROPPATCH,LOCK,UNLOCK,PATCH
limit_except GET{
allow 192.168.1.0/24;
deny all;
}除了GET和HEAD之外其他方法仅允许192.168.1.0/24网段主机使用
21、aio on|off|threads|[=pool];
是否启用aio功能,默认不启动
22、directio size|off;
当文件大于等于给定大小时,例如directio 4m,同步(直接)写磁盘,而非写缓存
23、open_file_cache off;
open_file_cache max=N [inactive=time];
nginx可以缓存以下三种信息:
(1)文件元数据:文件的描述符、文件大小和最近一次的修改时间
(2)打开的目录结构
(3)没有找到的或者没有权限访问的文件的相关信息
max=N:可缓存的缓存项上限;达到上限后会使用LRU(最近最少)算法实现管理
inactive=time:缓存项的非活动时长,在此处指定的时长内未被命中的活命中的次数少于open_file_cache_min_uses指令所指定的次数的缓存项即非活动项,将被删除
24、open_file_cache_errors on|off;
是否缓存查找时发生错误的文件一类的信息
默认值为off
25、open_file_cache_min_uses number;
open_file_cache指令的inactive参数指定的时长内,至少被命中此处指定的次数方可被归类为活动项
默认值为1
26、open_file_cache_valid time;
缓存项有效性的检查频率
默认值为60s
1、allow address|CIDR|unix:|all;
2、deny address|CIDR|unix:|all;
http,server,location,limit_except
自上而下检查,一旦匹配,将生效,条件严格的置前
示例:
location /{
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
allow 2001:0db8::/32;
deny all
}
使用basic机制进行用户认证
1、auth_basic string|off;
2、auth_basic_user_file file;
location /admin/{
auth_basic "Admin Area"; # 提示信息
auth_basic_user_file /etc/nginx/conf.d/vhosts/nginxuser; # 其实也可以创建隐藏文件 .nginxuser
}
用户口令文件:
1、明文文本:格式name:password:comment
2、加密文本:由htpasswd命令实现 (通过httpd-tools。 #rpm -ivh httpd-tools)
#htpasswd -cm nginxuser httpuser1 第一次创建要加参数c
#htpasswd -m nginxuser httpuser2
输出信息示例:
Active connections:291
server accepts handled requests
16630948 16630948 31070465
上面三个数字分别对应accepts,handled,requests三个值
Reading:6 Writing:179 Waiting:106
Activeconnections:当前状态,活动状态的连接数
accepts:统计总值,已经接受的客户端请求的总数
handled:统计总值,已经处理完成的客户端请求的总数
requests:统计总值,客户端发来的总的请求数
Reading:当前状态,正在读取客户端青求报文首部的连接的连接数
Writing:当前状态,正在向客户端发关响应报文过程中的连接数
Waiting:当前状态,正在等待客户端发出请求的空闲连接数
1、stub_status;
示例:
location /status{
stub_status;
#allow 172.16.0.0/16;
#deny all;
}
只能在http
#vim /etc/nginx/nginx.conf
1、log_format name string ...;
string可以使用nginx核心模块及其它模块内嵌的变量
2、access_log path [format[buffer=size][gzip[=level]][flush=time][if=condition]];
access_log off;
访问日志文件路径,格式及相关的缓冲的配置
buffer=size
flush=time
配合access_log
access_log可以配置在 http,server,location,if in location,limit_except
日志时间格式:log_format
$time_iso8601
#vim /etc/nginx/nginx.conf 修改[$time_local]为[$time_iso8601]
日志缓存
3、open_log_file_cache max=N[inactiv=time][min_uses=N][valid=time];
open_log_filecacheoff;
缓存各日志文件相关的元数据信息
max:缓存的最大文件描述符数量
min_uses:在inactive指定的时长内访问大于等于此值方可被当作活动项
inactive:非活动时长
valid:验证缓存中各缓存项是否为活动项的时间间隔
用gzip方法压缩响应数据,节约带宽
1、gzip on|off;
启用或禁用gzip压缩
2、gzip comp-level level;
压缩比由低到高:1到9
默认:1
3、gzip_disable regex ...
匹配到客户端浏览器不执行压缩
4、gzip_min_length length;
启用压缩功能的响应报文大小阈值
用gzip方法压缩响应数据,节约带宽
1、gziponloff;
启用或禁用gzip压缩
2、gzipcomp-levellevel;
压缩比由低到高:1到9
默认:1
3、gzip_disableregex.…
匹配到客户端浏览器不执行压缩
4、gzip_min_lengthlength;
启用压缩功能的响应报文大小阈值
5、gzip_http_version1.0|1.1;
设定启用压缩功能时,协议的最小版本
默认:1.1
6、gzip_buffers number size;
支持实现压缩功能时缓冲区数量及每个缓存区的大小
默认:324k或168k
7、gzip_types mime-type ...;
指明仅对哪些类型的资源执行压缩操作;即压缩过滤器
默认包含有text/html,不用显示指定,否则出错
8、gzip_vary on|off;
如果启用压缩,是否在响应报文首部插入“Vary:Accept-Encoding”
9、gzip_proxied off|expired|no-cache|no-store|private|no_last_modified|no_etag|auth|any ...;
nginx充当代理服务器时,对于后端服务器的响应报文,在何种条件下启用压缩功能
off:不启用压缩
expired,no-cache,no-store,private:对后端服务器的响应报文首部Cache-Control值任何一个,启用压缩功能
示例:
gzip on;
gzip_comp_level 6
gzip_min_length 64; 字节
gzip_proxied any;
gzip_types text/xml text/css application/javascript text/plain; 默认html压缩
gzip
帮助文档:http://nginx.org/en/docs/
正常运行必备的配置:
帮助文档:http://nginx.org/en/docs/ngx_core_module.html
1、user
Syntax: user user [group];
Default: user nobody nobody;
Context: main
指定worker进程的运行身份,如组不指定,默认和用户名同名
2、pid /PATH/TO/PID_FILE
指定存储nginx主进程PID的文件路径
3、include file|mask
指明包含进来的其他配置文件片断
4、load_module file
模块加载配置文件:/usr/share/nginx/modules/*.conf
指明要装在的动态模块路径:/usr/lib64/nginx/modules
改了配置文件后生效命令:#nginx -s reload
语法检查:#nginx -t
vim nginx.conf
性能优化相关的配置:
1、worker_processes number | auto
worker进程的数量;通常应该为当前主机的cpu的物理核心数
2、worker_cpu_affinity cpumask ...
worker_cpu_affinity auto [cpumask] 提高缓存命中率
CPU MASK:00000001:0号CPU
00000010:1号CPU
10000000:8号CPU
worker_cpu_affinity 0001 0010 0100 1000;
worker_cpu_affinity 0101 1010;
3、worker_priority number
指定worker进程的nice值,设定worker进程的优先级:[-20,20]
4、worker_rlimit_nofile number
worker进程所能够打开的文件数量上限,如65535
事件驱动相关的配置:
events{
...
}
1、worker_connections number
每个worker进程所能够打开的最大并发连接数数量,如10240
总最大并发数:worker_processes * worker_connections
2、use method
指明并发连接请求的处理方法,默认自动选择最优方法
use epoll;
3、accept_mutex on|off 互斥
处理新的连接请求的方法;on指由各个worker轮流处理新请求,off指每个新请求的到达都会通知(唤醒)所有的worker进程,但只有一个进程可获得连接,造成'惊群',影响性能
调试和定位问题:
1、daemon on|off
是否以守护进程方式运行nginx,默认是守护进程方式。 配置放在全局块,off之后可以到前台运行
2、master_process on|off
是否以master/worker模型运行nginx;默认为on。 off将不启动worker
3、error_log file [level]
错误日志文件及其级别;出于调试需要,可设定为debug;但debug仅在编译时使用了“--with-debug”选项时才有效
方式:file /path/logfile;
stderr:发送到标准错误
syslog:server-address[,parameter=values]:发送到syslog memory:size 内存
level:debug|info|notice|warn|error|crit|alter|emerg
源码编译需要的包:gcc pcre pcre-devel zlib zlib-devel
此处选择MAKE源码编译方式,构建Nginx WEB平台,首先从Nginx官网下载Nginx软件包稳定版本:nginx-1.16.0.tar.gz,下载地址如下:
wget -c http://nginx.org/download/nginx-1.16.0.tar.gz -O /tmp/
Tar解压Nginx软件包(-x extract解压,-z gzip压缩格式,-v verbose详细显示,-f file文件属性);
tar -xzvf nginx-1.16.0.tar.gz
Cd切换至Nginx源代码目录;
cd nginx-1.16.0/
预编译 ./configure
./configure --prefix=/usr/local/nginx/ --user=www --group=www --with-http_stub_status_module
(-user -group 指定www作为用户和组进行进程功控制
–with-http_stub_status_module 状态参数
./configure --help | more -10 查看帮助文档`)
主要是检测Linux系统安装该软件所需的依赖环境、库文件,检测Linux系统是否存在GCC编译器环境(C编译器),指定软件服务部署的路径,自定义软件服务特定的功能、参数、模块,最终会产生Makefile文件。
编译 make
主要是通过make编译工具,读取Makefile文件,调用Linux操作系统下GCC编译环境(C编译器),将软件包中的源代码文件编译生成二进制文件。
Makefile文件用途,告知make编译工具,在编译源代码文件时,从哪个源码文件开始至哪个源码文件结束编译&记录编译时依赖信息。
安装 make install
主要是将第二步make编译产生的二进制文件,拷贝或者安装至Linux操作系统指定的安装目录:–prefix=/usr/local/nginx/。
启动nginx
[root@aliyun conf]# /usr/local/nginx/sbin/nginx
nginx: [emerg] getpwnam("www") failed
因为在预编译的时候指定了www用户
添加www用户,-M是指不创建家目录
useradd -s /sbin/noginx www -M
[root@aliyun conf]# /usr/local/nginx/sbin/nginx
master进程,fork出一个worker进程,worker进程负责对外接收请求
[root@aliyun conf]# firewall-cmd --add-port=8888/tcp --permanent
[root@aliyun conf]# firewall-cmd reload
1)根据如上Nginx WEB平台构建,用户可以通过浏览器访问测试页面,在企业生产环境中,通常Nginx不仅仅只发布一套默认网站,会发布多个网站、提高服务器的利用率,避免资源的浪费。
2)将Nginx WEB服务器发布多套网站的方法,称为虚拟主机(多个网站),Nginx发布虚拟主机的方式主要有以下三种:
同一个8888端口,不同的IP访问IP地址;
同一个IP地址,不同的访问端口;
同一个8888端口,同一个IP地址,不同的访问域名。 √
3)基于Nginx WEB服务器,通过同一个8888端口,同一个IP地址,不同的访问域名,发布两个网站,两个网站对应的域名分别是:wp.kolorbgg.top、love.kolorbgg.top,要求用户通过浏览器实现两个网站页面的访问,操作的步骤和方法如下:
#进入Nginx安装后的目录;
cd /usr/local/nginx/
#查找Nginx主配置文件所在路径;
cd conf/
ls -l nginx.conf
#去除Nginx主配置文件中#和空行 三种方式;
awk '!/#/' nginx.conf|awk '!/^$/' 不看井号和空行,加!
sed -e '/#/d' -e '/^$/d' nginx.conf
grep -aivE "#|^$" nginx.conf
4)根据如上配置文件过滤、删除,nginx.conf主配置文件Server虚拟主机的核心代码:
server {
listen 8888;
server_name wp.kolorbgg.top;
location / {
root html/nextcloud;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 8888;
server_name love.kolorbgg.top;
location / {
root html/love;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
5)创建两个虚拟主机的发布目录&默认引导文件index.html,操作的方法和指令如下:
#创建两套网站发布目录;
mkdir -p /usr/local/nginx/html/love/
mkdir -p /usr/local/nginx/html/nextcloud/
#往nextcloud发布目录中index.html写入测试数据;
cat>/usr/local/nginx/html/nextcloud/index.html <<EOF
nextcloud Test Pages.
EOF
#往love发布目录中index.html写入测试数据;
cat>/usr/local/nginx/html/love/index.html <<EOF
love Test Pages.
EOF
6)在客户端(Windows)主机中,添加hosts记录,将Nginx服务器IP和对应两个域名的记录写入到hosts文件中,通过浏览器就可以直接访问两个域名网站,从而能够定位Nginx WEB服务器所在的IP地址。
修改环境变量,优化启动
[root@aliyun conf]# /usr/local/nginx/sbin/nginx -s reload
[root@aliyun conf]# export PATH=/usr/local/nginx/sbin:$PATH
#echo $PATH