Nginx
nginx 作为近年来最火的中间件之一,很有必要学习 nginx 优势
- 采用 IO 多路复用
epoll模型,epoll驱动的就是在操作系统下的系统内核来进行工作,实现 IO 复用的处理方式
- 多进程多线程处理,但一个线程只能处理一个 IO 流
- 多路 IO 复用,采用的是一个线程并实现 IO 流非阻塞模式
while true {
for i in stream[]; {
// 查看有无数据,无数据就进行循环
if i has data
read until unavailable
}
}所以当没有数据时,就会白白浪费 cpu,此时我们可以使用内核模型来进行循环,一般使用的是 epoll 模型, epoll 模型相当于是一个代理,获取有数据的循环再进行遍历
epoll 优势 - 解决 SELECT 模型对于文件句柄 FD 打开限制 - 采用 callback 函数回调机制优化模型效率 2. 利用了 cpu 亲和 affinity 来提高 cpu 的并发处理能力减少不必要的性能损耗。cpu 亲和就是把 cpu 核心和 Nginx 工作进程绑定方式,把每个 worker 进程固定在一个 cpu 上执行,减少切换 cpu 的 cache miss,获得更好地性能 3. sendfile ,在没有 nginx 时,用户发送一个请求获取文件的时候,会经过内核空间和用户空间,最终到达 socket 并传递给用户,而 sendfile 只会进过内核空间传递给用户
安装
这里查看
安装目录
/etc/logrotate.d/nginxNginx 日志轮转,用于logrotate服务的日志切割,也就是可以按天进行输出/etc/nginx | /etc/nginx/nginx.conf | /etc/nginx/conf.d | /etc/nginx/conf.d/default.confNginx 主要配置文件/etc/nginx/sites-enabled中拥有 sites-available 文件夹下 default 的软链接。sites-available 与 sites-enabled 使我们能够进行模块化配置,当我们希望增加新网站时,我们可以在 sites-available 中创建新配置文件/etc/nginx/sites-available用于存放网站的配置文件,意为可用的网站列表,用于在需要时链接到sites-enabled中作为需要启用的网站。文件夹下的 default 为网站配置文件的参考,由于在 nginx 更新时,default 会一同被更新以展示配置文件的变化,所以在配置网站时,不应该直接修改此文件,需要复制为新文件,再进行修改。/etc/nginx/fastcgi_params | /etc/nginx/uwsgi_params | /etc/nginx/scgi_params为cgi配置和fastcgi配置/etc/nginx/koi-utf | /etc/nginx/koi-win | /etc/nginx/win-utf编码转换映射转换文件/etc/nginx/mime.types设置 http 协议的Content-Type与扩展名对应关系/usr/lib/systemd/system/nginx-debug.service | /usr/lib/systemd/system/nginx.service | /etc/sysconfig/nginx | /etc/sysconfig/nginx-debug用于配制出系统守护进程管理器管理方式/usr/lib64/nginx/modules | /etc/nginx/modulesNginx 模块目录/usr/sbin/nginx | /usr/sbin/nginx-debugNginx 命令/usr/share/doc/nginx-1.12.0 | /usr/share/doc/nginx-1.12.0/COPYRIGHT | /usr/share/man/man8/nginx.8.gzNginx 的手册和帮助文件/var/cache/nginxNginx 的缓存目录/var/log/nginxNginx 的日志目录
命令
nginx -t -c:查看配置是否正确nginx -s reload -c:重新加载配置
配置语法
默认配置语法
-
user:设置 nginx 服务的系统使用用户 -
worker_processes:工作进程数,一般和 cpu 核心一致 -
error_log:nginx 的错误日志 -
pid:nginx服务启动时候pid -
events:事件模块worker_connections:每个进程允许最大连接数use:设置 nginx 使用的内核模型
-
http: 包含所有 http 的服务-
server:配置虚拟或是独立的站点listen:监听的端口server_name:监听的 hostlocation:控制每一层路径的访问- 可以接一个路径,然后有一个模块
error_page: 可以接状态码,之后再接页面
-
`
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
// 如果在 root 路径下没有找到 index.html 回去找 index.htm
index index.html index.htm;
}
error_page 500 502 /50x.html;
location = /50x.html {
// 在这个路径下寻找对应的 html 文件
root /usr/share/nginx/html;
}
}include:包含所有的Content-Typedefault_type:默认的Content-Typelog_format:日志类型keepalive_timeout <时间长度>:客户端和服务端超时的时间gzip:打开gzip
虚拟主机
当我们希望一个 Nginx 来运行多套单独服务时,可以配置多个虚拟主机。有三种方式
- 基于主机的多 IP 的方式
- 多网卡多 IP 的方式,网卡 1 -> IP1 网卡 2 -> IP2,对主机配置要求高
- 单网卡多 IP 的方式,网卡 1 -> IP1 -> IP2,对网卡设置别名。通过
ip a add <Ip>/<掩码> dev <设备名>的方式来增加 IP 地址,在增加之前使用ping <IP>的方式来判断这个域名是否存在服务,如果有服务就不能增加
- 基于端口的配置方式
- 端口其实和上面类似,只不过不用设置多 IP,
listen监听的是不同端口号即可。需要处理的是端口冲突,需要先用命令查看,然后避开对应的端口
- 基于多个 host 名称方式,常见的方式,也就是多域名方式。它只需要一个 IP 和一个端
虚拟主机的配置放在 nginx 的配置文件
/etc/nginx/nginx.conf中includes属性中包括的路径中,之后通过listen属性配置到具体的 IP 地址 首先需要修改本地的 host 文件,增加 IP 对应的 host 地址,但需要配置的 host 地址对应同一个 IP 地址,同时需要配置server_name
`
server {
listen 80;
server_name 2.imooc.com;
}
日志
日志类型包括 error.log 和 access_log
error.log:主要用于处理 http 请求的状态,以及 nginx 服务的状态,会按照不同的级别记录到error.log中error_log <log 位置> <error 级别(比如 warn)>:在服务配置中增加字段
access_log:依赖于log_format的配置,每一个信息都是对应一个变量,log_format就是将所有变量组装到一起access_log <log 位置> <log_format 的 name>:在服务配置中增加字段Nginx 变量:可在log_format中进行组合format输出日志信息- HTTP 请求变量
arg_<变量名>:输出信息http_<HEADER>:request中的headsent_http_<HEADER>:response中的head
- 内置变量:比较多,进入官网了解
- 自定义变量
- HTTP 请求变量
模块
使用 nginx -V ,以 --with 开头的就是开启的模块
- Nginx 官方模块,官方支持的模块
--with-http_stub-status_module:Nginx 的客户端状态,此时可以使用浏览器访问<地址>/mystatus查看 nginx 当前活跃的连接数Syntax:stub_statusDefault: --Context:server,location
location /mystatus {
stub_status;
}--with-http_random_index_module:目录中选择一个随机主页,也就是随机选择一个主页,给用户不同的感觉。但不会选择路径下的隐藏文件Syntax:random_index on | offDefault:random_index offContext:location
location / {
random_index on;
}-
--with-http_sub_module:HTTP 内容替换-
Syntax:sub_filter <要替换的内容> <替换的内容> -
Default:-- -
Context:http,server,location或是,每次请求校验服务器内容是是否更新,如果更新返回的是新的 -
Syntax:sub_filter_last_modified on | off -
Default:sub_filter_last_modified off -
Context:http,server,location或是,匹配所有 html 代码里的第一个,还是匹配所有指定的字符串 -
Syntax:sub_filter_once on | off -
Default:sub_filter_once on -
Context:http,server,location
-
- 第三方模块
请求限制
HTTP 协议的连接与请求
-
HTTP1.0:TCP 不能复用
-
HTTP1.1:顺序性 TCP 复用
-
HTTP2.0:多路复用 TCP 复用
-
-limit_conn_module:连接限制 调用空间进行限制,key就是对什么进行限制,比如IP,name就是这个zone的名字,size就是大小-
Syntax:limit_conn_zone key zone=name:size -
Default:-- -
Context:http以及,zone表示申请的zone名,number就是同一时间只能允许多少个 -
Syntax:limit_conn zone number -
Default:-- -
Context:http,server, location
-
-
-limit_req_module:请求限制 也是调用空间进行限制,name就是zone名,size就是空间大小,rate就是对速率进行限制,通常以秒为单位Syntax:limit_req_zone key zone=name:size rate=rate;Default:--Context:http
# $binary_remote_addr 表示的是客户端的地址
limit_req_zone $binary_remote_addr zone=req_zone:1m rate=1r/s以及, burst 表示是超过指定速率以后,遗留的三个请求放到下一秒请求,其他的会直接返回
Syntax:limit_req zone=name burst=number] [nodelay]Default:--Context:http,server, location
访问控制
-
http_access_module:基于 IP 的访问控制,但是它只是对代理层进行限制,而对真正的客户端没有进行限制。-
http_x_forwarded_for:常用的 http 变量,会显示代理以及发起连接的客户端 IP,可以一定程度的解决限制真正客户端问题 -http_x_forwarded_for = Client IP, Proxy(1) IP, Proxy(2) IP- 局限性 - 它是通过头HTTP_X_FORWARD_FOR来进行控制的,可能有厂商不使用这个头,或是传递一个别的值 - 结合geo模块 - 通过 HTTP 自定义变量传递,可以在 HTTP 头定义一个我们规定的变量,在联系上一级时把自己的remote_addr信息携带到上一级上,从而得到客户端信息addressIP 地址,CIDR网段,unix就是 linux 或是 unix 使用socket的方式的访问,all就是允许所有的 -
Syntax:allow address | CIDR | unix: | all -
Default:-- -
Context:http,server, location, limit_except或是,也就是不允许访问的 -
Syntax:deny address | CIDR | unix: | all -
Default:-- -
Context:http,server, location, limit_except
-
-
http_auth_basic_module:基于用户的信任登录-
Syntax:auth_basic string | off -
Default:auth_basic off` -
Context:http,server, limit_except以及,file就是用来存储用户名和密码信息的文件,需要按照 nginx 规定的格式。可以使用htpasswd来生成密码文件,htpasswd -c <生成文件名> <用户名> -
Syntax:auth_basic_user_file file -
`Default:--
-
Context:http, location,server, limit_except局限性
-
用户信息依赖文件方式
-
操作管理机械,效率低下 解决方案
-
nginx 结合
LUA实现高效验证 -
nginx 和
LDAP打通,利用nginx-auth-ldap模块
-
静态资源 web 服务
静态资源类型,静态资源就是那些不需要动态生成的资源
-
浏览器渲染:
HTML、CSS、JS -
图片:
JPEG、GIF、PNG -
视频:
FLV、MPEG -
文件:
TXT等任意下载文件 静态资源服务场景CDN,其实就是把资源存储中心的资源分发给不同地区,各存一份。之后在不同地区的用户,通过智能 DNS 技术,动态定位到北京的代理上进行请求,就不需要请求资源中心,也就是传输时延的最小化 -
文件读取
Syntax:sendfile on | offDefault:sendfile offContext:http, server, location, if in location
-
tcp_nopush在sendfile开启的情况下,提高网络包的传输效率。把包进行整合,之后一次性发送出去。处理大文件会跟有利Syntax:tcp_nopush on | offDefault:tcp_nopush offContext:http, server, location
-
tcp_nodelay不会对包进行整合,在keepalive连接下,提高网络包的传输实时性Syntax:tcp_nodelay on | offDefault:tcp_nodelay onContext:http, server, location
-
压缩,减少不必要的网络资源消耗
-
Syntax:gzip on | off -
Default:gzip off -
Context:http, server, location, if in location压缩比 -
Syntax:gzip_comp_level level -
Default:gzip_comp_level off -
Context:http, server, location协议版本 -
Syntax:gzip_http_version 1.0 | 1.1 -
Default:gzip_http_version 1.1 -
Context:http, server, locationhttp_gzip_static_module:默认的模块,可以预读gzip功能,当读取静态文件比如html文件时,会先去找.gz结尾的文件http_gunzip_module:当不支持gzip时,应用支持gunzip的压缩方式,现实很少用到
-
-
缓存:
expires用于添加Cache-Control、Expires头Syntax:expires [modified] time;或expores epoch | max | off;Default:expores offContext:http, server, location, if in location
-
跨域
Syntax:add_header name value [always]Default: --Context:http, server, location, if in location
-
防盗链:防止资源被盗用,希望是一些合法用户来访问网站,防止爬取。首要方式:区别那些请求是非正常的用户请求 基于
http_refer防盗链配置模块,同时http_refer也是一个变量。它会记录上次请求的域名Syntax:valid_referrers none | blocked | server_names | string...;如果none表示只允许不带refer的请求blocked表示不带协议信息的请求是不被允许的Default: --Context:server, location
valid_referrers none blocked 116.62.103.228
if ($invalid_referer) {
return 403
}代理服务
按应用场景模式来分类有两种,正向代理和反向代理
- 正向代理: 即通过代理访问其他代理
- 反向代理: 针对性地访问某个站点的时候,为服务端提供服务 常见的反向代理模式和 Nginx 代理模块 |反向代理模式|Nginx 配置模块| | ---------------------- | |http、websocket、https| ngx_http_proxy_module| |fastcgi| ngx_http_fastcgi_module| |uwsgi| ngx_http_uwsgi_module| |grpc| ngx_http_v2_module|
- 常见的代理语法
Syntax:proxy_pass URLDefault: --Context:location, if in location, limit_except
- 缓冲区,后端可能发送的只是小部分头信息,这里可以在数据全部存在时,才会返回数据,但会占用内存资源
Syntax:proxy_buffering on | off;Default:proxy_buffering on;Context:http, server, location
- 跳转重定向
Syntax:proxy_redirect default; | proxy_direct off; | proxy_redirect redirect replacement;Default:proxy_buffering default;Context:http, server, location
- 头信息,把头信息从代理带到后端
Syntax:proxy_set_header field value;Default:proxy_set_header Host $proxy_host; | proxy_set_header Connection close;Context:http, server, location
- 超时,连接超时
Syntax:proxy_connect_timeout time;Default:proxy_connect_timeout 60s;Context:http, server, location
缓存
缓存分为服务端缓存,代理(Nginx)缓存,客户端缓存 代理缓存就是在请求的时候直接从代理中获取缓存
-
proxy_cache配置语法,定义path,path就是存放缓存文件的地址-
Syntax:proxy_cache_path path; -
Default: -- -
Context:httpproxy_zone其中的zone就是定义的path -
Syntax:proxy_cache zone | off; -
Default:proxy_cache off -
Context:http, server, location缓存过期周期,code就是状态码 -
Syntax:proxy_cache_valid [code ...] time; -
Default: -- -
Context:http, server, location如何清理指定缓存
-
-
rm -rf缓存目录内容 -
第三方模块
ngx_cache_purge如何让部分页面不缓存,url为参数-
Syntax:proxy_no_cache string ... -
Default: -- -
Context:http, server, location缓存命中分析 -
add_header Nginx-Cache "$upstream_cache_status";给response添加头信息 -
通过设置
log_format打印日志分析,也是使用$upstream_cache_status这个变量 -
$upstream_cache_status有以下状态MISS:未命中,请求被传送到后台处理HIT:缓存命中EXPIRED:缓存已经过期,请求被传送到后台处理UPDATING:正在更新缓存,经使用旧的应答STALE:后端得到过期的应答 缓存命中率 = HIT 次数 / 总请求次数,通过分析 Nginx 里的Access日志可以分析得到命中率
-
log_format main '"$upstream_cache_status"';对大文件的分片请求,前端请求到达之后,根据定义的分片,将文件进行切片再分为多个不同的小的请求同时请求后端
Syntax:slice size;Default:slice 0;Context:http, server, location优势:每个子请求收到的数据会形成一个独立文件,一个请求断了,其他请求不受影响 缺点:当文件很大或slice很小的时候,可能会导致文件描述符耗尽等情况