Nginx学习笔记

Nginx的中间件架构

什么是中间件,应用与应用之间的交互,应用与操作系统的交互。Nginx学习笔记_第1张图片

1、Nginx简述

Nginx是一个开源且高性能、可靠的HTTP中间件、代理服务。

2、为什么选择nginx?

原因一、 IO多路复用epoll
Nginx学习笔记_第2张图片
Nginx学习笔记_第3张图片
多个描述符的IO操作都能在一个线程内并发交替地顺利完成,这就叫IO多路复用,这里的“复用”指的是复用同一个线程。

什么是epoll?
IO多路复用的实现方式select、poll、epoll
Nginx学习笔记_第4张图片
select缺点

  1. 能够监听文件描述符的数量存在最大限制
  2. 线性扫描效率低下

原因二、轻量级
原因三、CPU亲和(affinity)
一、什么是CPU亲和
是一种把cpu核心和nginx工作进程绑定方式,把每个workder进程固定在一个cpu上执行,减少切换cpu的cache miss,获得更好的性能。

原因四、sendfile
sendfile: 设置为on表示启动高效传输文件的模式。sendfile可以让Nginx在传输文件时直接在磁盘和tcp socket之间传输数据。如果这个参数不开启,会先在用户空间(Nginx进程空间)申请一个buffer,用read函数把数据从磁盘读到cache,再从cache读取到用户空间的buffer,再用write函数把数据从用户空间的buffer写入到内核的buffer,最后到tcp socket。开启这个参数后可以让数据不用经过用户buffer。
Nginx学习笔记_第5张图片
Nginx学习笔记_第6张图片

nginx配置文件
Nginx学习笔记_第7张图片

1.Nginx日志轮转,用于logrotate服务的日志切割 | 配置文件

/etc/logrotate.d/nginx

2.Nginx住配置文件 | 目录、配置文件

/etc/nginx
/etc/nginx/nginx.conf
/etc/nginx/conf.d
/etc/nginx/conf.d/default.conf

3.cgi配置相关,fastcgi | 配置文件

/etc/nginx/fastcgi_params
/etc/nginx/scgi_params
/etc/nginx/uwsgi_params

4.编码转换映射转化文件 | 配置文件

/etc/nginx/koi-utf
/etc/nginx/koi-win
/etc/nginx/win-utf

5.设置http协议的Content-Type与扩展名对应关系:返回数据的类型 | 配置文件
/etc/nginx/mime.types

6.用于配置出系统守护进程管理器管理方式 : centos7.2 | 配置文件

/usr/lib/systemd/system/nginx-dubug.service
/usr/lib/systemd/system/nginx.service
/etc/sysconfig/nginx
/etc/sysconfig/nginx-dubug

7.Nginx模块目录 | 目录

/usr/lib64/nginx/modules
/etc/nginx/modules

8.Nginx服务的启动管理的终端命令 | 命令

/usr/sbin/nginx
/usr/sbin/nginx-debug

9.Nginx的手册和帮助文件 | 文件、目录

/usr/share/doc/nginx-1.10.2
/usr/share/doc/nginx-1.10.2/COPYRIGHT
/usr/share/man/man8/nginx.8.gz

10.Nginx的缓存目录 | 目录

/var/cache/nginx

11.Nginx的日志目录 | 目录

/var/log/nginx

2、http_access_module局限性
 局限性,如下图第一个所示,如果客户端通过一个代理,访问服务端,服务端获取的是代理的ip,而不是客户端的ip

解决方法:
1. 采用别的HTTP头信息控制访问,如:HTTP_X_FORWARD_FOR
2. 结合geo模块作(geo模块是nginx另外一个模块)
3. 通过HTTP自定义变量传递
Nginx学习笔记_第8张图片
3、http_x_forwarded_for
http_x_forwarded_for = Client IP, Proxy(1) IP, Proxy(2) IP,…
Nginx学习笔记_第9张图片
1、http_auto_basic_module

ngx_http_auth_basic_module模块实现让访问者,只有输入正确的用户密码才允许访问web内容。web上的一些内容不想被其他人知道,但是又想让部分人看到。nginx的http auth模块以及Apache http auth都是很好的解决方案。

默认情况下nginx已经安装了ngx_http_auth_basic_module模块,如果不需要这个模块,可以加上 --without-http_auth_basic_module 。

语法: auth_basic_user_file file;
默认值: —
配置段: http, server, location, limit_except

用户密码加密方式
http://nginx.org/en/docs/http/ngx_http_auth_basic_module.html

支持htpasswd等

htpasswd安装

yum install httpd-tools -y

首次创建并加入

htpasswd -c ./user_passwd admin

会出现

New password:
Re-type new password:
Adding password for user admin

两次密码都正确情况下创建用户成功

查看 cat user_passwd

继续添加用户

htpasswd user_passwd user2

或者 htpasswd -b user_passwd user3 123456

删除一个用户

[root@centos1 conf]# htpasswd -D user_passwd admin

nginx里配置

location /admin{
            auth_basic "auth: ";
            auth_basic_user_file /usr/local/nginx/conf/user_passwd;
       }

然后重启nginx
Nginx学习笔记_第10张图片

http_auto_basic_module局限性

  1. 用户信息依赖文件方式
  2. 操作管理机械,效率低下

解决方法:
一、 Nginx结合LUA实现高效验证
二、 Nginx和LDAP打通,利用nginx-auth-ldap模块

进阶学习 - 常见nginx中间架构
一、静态资源WEB服务
二、代理服务
三、负载均衡调度器SLB
四、动态缓存

一、静态资源WEB服务

Nginx学习笔记_第11张图片
静态请求和动态请求

  • 动态请求:需要经过服务端解析器、复杂运算,实时性封装再返回给用户
  • 静态请求:请求某个东西,在文件系统就可以找到

Nginx学习笔记_第12张图片
2、静态资源服务场景-CDN
Nginx学习笔记_第13张图片

sendfile on

性能优化-开启高效文件传输模式sendfile on;
sendfile on; #特殊的数据传输功能

参数sendfile on 用于开启文件高效传输模式,同时将tcp_nopush on 和tcp_nodelay on 两个指令设置为on,可防止网络及磁盘I/O阻塞,提升Nginx工作效率

(1) 设置参数 sendfile on

参数语法 sendfile on | off;
放置位置 http,server,location,if in location

tcp_nopush on;

设置参数 tcp_nopush on 说明:当有数据时,先别着急发送, 确保数据包已经装满数据, 避免了网络拥塞。适合大文件

参数语法 tcp_nopush on | off;
放置位置 http,server,location

tcp_nodelay on

设置参数 说明:有时要抓紧发货, 确保数据尽快发送, 提高可数据传输效率。

作用:keepalive连接下,提高网络包的传输实时性

参数语法 tcp_nodelay on | off;
放置位置 http,server,location

sendfile on配合使用(tcp_nopush on 和tcp_nodelay on, 但tcp_nopush on 和tcp_nodelay on只能选其一特别注意

在主配置文件nginx.conf中配置

worker_processes  2;
worker_cpu_affinity 0101 1010;
error_log logs/error.log;
 
#配置Nginx worker进程最大打开文件数
worker_rlimit_nofile 65535;
 
user www www;
events {
    #单个进程允许的客户端最大连接数
    worker_connections  20480;
    #使用epoll模型
    use epoll;
}
http {
    include       mime.types;
    default_type  application/octet-stream;
    #sendfile        on;
    keepalive_timeout  65;
    #访问日志配置
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
 
    #虚拟主机
    include /application/nginx/conf/extra/www.conf;
    include /application/nginx/conf/extra/blog.conf;
    include /application/nginx/conf/extra/bbs.conf;
    include /application/nginx/conf/extra/edu.conf;
    include /application/nginx/conf/extra/phpmyadmin.conf;
    include /application/nginx/conf/extra/status.conf;
 
    #nginx优化----------------------
    #隐藏版本号
    server_tokens on;
 
    #优化服务器域名的散列表大小 
    server_names_hash_bucket_size 64;
    server_names_hash_max_size 2048;
 
    #开启高效文件传输模式
    sendfile on;
    #减少网络报文段数量
    #tcp_nopush on;
    #提高I/O性能
    tcp_nodelay on;
}

配置语法 - 压缩

gzip的压缩页面需要浏览器和服务器双方都支持,实际上就是服务器端压缩,传到浏览器后浏览器解压并解析。减少网络传输中的消耗,减少带宽,减少传输的文件大小,从实现传输的实时性
Nginx学习笔记_第14张图片
参数语法 gzip on | off;
放置位置 http,server,location

作用:压缩传输

# 开启gzip
gzip on;

# 启用gzip压缩的最小文件,小于设置值的文件将不会压缩
gzip_min_length 1k;

# gzip 压缩级别,1-10,数字越大压缩的越好,也越占用CPU时间
gzip_comp_level 2;

# 进行压缩的文件类型。javascript有多种形式。其中的值可以在 mime.types 文件中找到。
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png font/ttf font/otf image/svg+xml;

# 是否在http header中添加Vary: Accept-Encoding,建议开启
gzip_vary on;

# 禁用IE 6 gzip
gzip_disable "MSIE [1-6]\.";



# 开启缓存
location ~* ^.+\.(ico|gif|jpg|jpeg|png)$ { 
    access_log   off; 
    expires      30d;
}

location ~* ^.+\.(css|js|txt|xml|swf|wav)$ {
    access_log   off;
    expires      24h;
}

location ~* ^.+\.(html|htm)$ {
    expires      1h;
}

location ~* ^.+\.(eot|ttf|otf|woff|svg)$ {
    access_log   off;
    expires max;
}

# 格式
# expires 30s;
# expires 30m;
# expires 2h;
# expires 30d;

其中的缓存时间可以自己根据需要修改。

4、扩展Nginx压缩模块

http_gzip_static_module 预读gzip功能

Nginx的动态压缩是对每个请求先压缩再输出,这样造成虚拟机浪费了很多cpu,解决这个问题可以利用nginx模块Gzip Precompression,这个模块的作用是对于需要压缩的文件,直接读取已经压缩好的文件(文件名为加.gz),而不是动态压缩,对于不支持gzip的请求则读取原文件。

nginx默认安装ngx_http_gzip_module,采用的是chunked方式的动态压缩,静态压缩需要使用http_gzip_static_module这个模块,进行pre-compress。

模块 ngx_http_gzip_static_module 允许发送以“.gz”作为文件扩展名的预压缩文件,以替代发送普通文件。需要指定 --with-http_gzip_static_module编译选项:

./configure --with-http_gzip_static_module

make

make install

若是nginx已安装过,需要把已配置过的参数一起编译,可以用nginx_home/sbin/nginx –V(大写)查看。安装前请确认nginx是否关闭:nginx-s stop 强制关闭;nginx -s quit 安全关闭。

Nginx配置文件:

location ~* \.(json)$ {
    gzip_static  on;
    gzip_proxied expired no-cache no-store private auth;               
}

a) 文件可以使用 gzip 命令来进行压缩,或任何其他兼容的命令。建议压缩文件和原始文件的修改日期和时间保持一致。

b) gzip_static配置优先级高于gzip。

c) 开启nginx_static后,对于任何文件都会先查找是否有对应的gz文件。

d) gzip_types设置对gzip_static无效。

e) gzip static默认适用HTTP 1.1。

浏览器缓存

HTTP协议定义的缓存机制(如:Expires;Cache-control等)
Nginx学习笔记_第15张图片
Nginx学习笔记_第16张图片
浏览器对于请求资源, 拥有一系列成熟的缓存策略. 按照发生的时间顺序分别为存储策略, 过期策略, 协商策略, 其中存储策略在收到响应后应用, 过期策略, 协商策略在发送请求前应用. 流程图如下所示.
Nginx学习笔记_第17张图片
1.http header中与缓存有关的key.

key 描述 存储策略 过期策略 协商策略
Cache-Control 指定缓存机制,覆盖其它设置 ✔️ ✔️
Pragma http1.0字段,指定缓存机制 ✔️
Expires http1.0字段,指定缓存的过期时间 ✔️
Last-Modified 资源最后一次的修改时间 ✔️
ETag 唯一标识请求资源的字符串 ✔️

2.缓存协商策略用于重新验证缓存资源是否有效, 有关的key如下.

key 描述
If-Modified-Since 缓存校验字段, 值为资源最后一次的修改时间, 即上次收到的Last-Modified值
If-Unmodified-Since 同上, 处理方式与之相反
If-Match 缓存校验字段, 值为唯一标识请求资源的字符串, 即上次收到的ETag值
If-None-Match 同上, 处理方式与之相反

Cache-Control

Cache-Control 头域分两种,一种用于 Request 的,一种是用于 Response 的,由于 Request 和 Response 都可以有 Cache-Control 头域,所以 Client 和 Server 都可以对缓存机制进行对应的控制。比如当 C 端要强制更新的时候,可以发送带 Cache control: no-store 的 Request。

Expires

Expires:Wed, 05 Apr 2017 00:55:35 GMT

即到期时间, 以服务器时间为参考系, 其优先级比 Cache-Control:max-age 低, 两者同时出现在响应头时, Expires将被后者覆盖. 如果Expires, Cache-Control: max-age, 或 Cache-Control:s-maxage 都没有在响应头中出现, 并且也没有其它缓存的设置, 那么浏览器默认会采用一个启发式的算法, 通常会取响应头的Date_value - Last-Modified_value值的10%作为缓存时间.

ETag

ETag:“fcb82312d92970bdf0d18a4eca08ebc7efede4fe”

实体标签, 服务器资源的唯一标识符, 浏览器可以根据ETag值缓存数据, 节省带宽. 如果资源已经改变, etag可以帮助防止同步更新资源的相互覆盖. ETag 优先级比 Last-Modified 高.

Last-Modified

语法: Last-Modified: 星期,日期 月份 年份 时:分:秒 GMT

Last-Modified: Tue, 04 Apr 2017 10:01:15 GMT

用于标记请求资源的最后一次修改时间, 格式为GMT(格林尼治标准时间). 如可用 new Date().toGMTString()获取当前GMT时间. Last-Modified 是 ETag 的fallback机制, 优先级比 ETag 低, 且只能精确到秒, 因此不太适合短时间内频繁改动的资源. 不仅如此, 服务器端的静态资源, 通常需要编译打包, 可能出现资源内容没有改变, 而Last-Modified却改变的情况.

Nginx学习笔记_第18张图片

Nginx优化之expires缓存设置

格式

expires 30s;#30秒
expires 30m;#30分钟
expires 2h;#2个小时
expires 30d;#30天

能够使浏览器缓存的HTTP头部信息主要有以下三种:
1、 last-modified实现浏览器缓存
last-modified是根据文件更新时间来确定是否再次发送加载。通过返回last-modified头部信息:
2、Etag确定浏览器缓存:
Etag的原理是将文件资源编号一个etag值,Response给访问者,访问者再次请求时,带着这个Etag值,与服务端所请求的文件的Etag对比,如果不同了就重新发送加载,如果相同,则返回304.
3、Expires浏览器缓存:
Expires是给一个资源设定一个过期时间,也就是说无需去服务端验证,直接通过浏览器自身确认是否过期即可,所以不会产生额外的流量。此种方法非常适合不经常变动的资源。如果文件变动较频繁,不要使用Expires来缓存。

server{

    index  index.html index.htm index.php;
    location~.*\.(gif|jpg|jpeg|bmp|png|ico|txt|mp3|mp4|swf){
        expires15d;
    }
    location~.*\.(css|js){
        expires12h;
    }
    ......
}

三、跨域访问

为什么浏览器禁止跨站访问

  1. 不安全,容易出现CSRF攻击

为什么还需要nginx打开跨域访问?

nginx配置文件通过使用add_header指令来设置response header。

使用ngx_http_headers_module中的add_header 指令,在响应头中添加允许跨域。

Syntax: add_header name value [always];
Default: —
Context: http, server, location, if in location

一般地,我们把允许跨域的头加在动态接口后面,比如php,就加在解析php后面

add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Headers X-Requested-With;
add_header Access-Control-Allow-Methods GET,POST;

注意,在实际中Allow-Origin不要指定为*,要设置为允许访问的域名,比如http://abc.com

http {
    include       mime.types;
       default_type  application/octet-stream ;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       8080;
        server_name  localhost;
        index index.html index.htm;
        root /usr/local/openresty/nginx/work;
        
        location ~* .(js)$ {
            add_header  Content-Type 'text/javascript;charset=utf-8';
        }
        
        location /dir {
            default_type application/javascript;
            content_by_lua_file /usr/local/openresty/nginx/work/resources/lua/index.lua;
        }
    }
}

四、防盗链

目的:防止资源被盗用

防盗链设置思路:
首要方式:区别哪些请求是非正常的用户请求

3、基于http_refer防盗链配置模块

当浏览器向web服务器发送请求的时候,一般会在头信息中带上Referer字段,告诉服务器我是从哪个页面链接过来的,服务器基此可以获得一些信息用于处理。基于头信息的
Referer字段,nginx识别指定的Referer,在客户端请求时,通过匹配referer头域与配置,对于指定放行,对于其他referer视为盗链。

nginx模块ngx_http_referer_module通常用于阻挡来源非法的域名请。

1.valid_referers

valid_referers配置项是属于ngx_http_referer_module模块传送门{:target="_blank"}

Syntax: valid_referers none | blocked | server_names | string …;
Default: —
Context: server, location

参数 说明
none 请求标头中缺少"Referer"字段,也就是空Referer
blocked "Referer"字段出现在请求标头中,但其值已被防火墙或代理服务器删除;这些值是不以"http://"或"https://"开头的字符串
server_names 允许某个域名通过如walidrea.com
arbitrary string 定义服务器名称和可选的URI前缀。服务器名称的开头或结尾可以包含“*”。在检查期间,“Referer”字段中的服务器端口被忽略
regular expression 第一个符号应为“~”。应该注意的是,表达式将与“http://”或“https://”之后的文本匹配

示例配置

location ~ .*\.(jpg|gif|png)$ {
	root  /opt/app/code/images;
	gzip on;
	gzip_http_version 1.1;
	gzip_comp_level 2;
	gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;

	valid_referers none blocked 116.62.113.218 walidream.com;
	if ($invalid_referer) {
		return 403;
	}	
}

允许116.62.113.218 walidream.com访问服务器图片

因为HTTPReferer头信息是可以通过程序来伪装生成的,所以通过Referer信息防盗链并非100%可靠,但是,它能够限制大部分的盗链

二、代理服务

代理区别

区别在于代理的对象不一样

  1. 正向代理代理的对象是客户端
  2. 反向代理代理的对象是服务端

反向代理proxy_pass的语法结构为

proxy_pass URL

其中,URL为要设置的被代理服务器的地址,包含传输协议、主机名称或IP地址加端口号、URI等要素。

例如:proxy_pass http://www.myweb.com/uri;

标准的代理配置
下面是一个基本的反向代理配置模板,将所有请求都转发给指定的后端应用。

例如,到http://your.ip:80/的请求都将重定向到 http://127.0.0.1:4433/ 私有服务器:

# One process for each CPU-Core
worker_processes  2;
# Event handler.
events {
    worker_connections  8096;
    multi_accept        on;
    use                 epoll;
}
http {
     # Basic reverse proxy server
     upstream backend  {
           server 127.0.0.1:4433;
     }
     # *:80 -> 127.0.0.1:4433
     server {
            listen       80;
            server_name  example.com;
            ## send all traffic to the back-end
            location / {
                 proxy_pass        http://backend;
                 proxy_redirect    off;
                 proxy_set_header  X-Forwarded-For $remote_addr;
            }
     }
}


反向代理优化要点(proxy_buffering配置)

什么是Proxy Buffer呢,我理解为缓存区,因为Nginx是作为客户端和服务端通信的桥梁,那么被代理服务器必然会将响应返回给Nginx,那么Nginx是同步的将接受到的响应发送给客户端,还是等接受到被代理服务器的响应到一定程度,一下返回给客户端呢,那么这就需要 Proxy Buffer的配置了,另外提一下,Proxy Buffer的配置不是全局的,而是每个请求都会按照这些指令的配置来设置各自的缓存。Proxy Buffer有7个指令,我们下面来看一看

Proxy Buffer配置
(1) 配置是否启用Proxy Buffer

proxy_buffering on | off;

默认为on,开启式Nginx会异步的将被代理服务器的响应数据传递给客户端,关闭时只要Nginx收到被代理服务器的响应就会同步给地给客户端,开启和关闭Proxy Buffer还可以使用响应头的“X-Accel-Buffering”设置“yes“” 和 “no”

(2)配置接受一次响应的buffer个数和你每个buffer的大小

proxy_buffer number size;

number代表数量,size代表大小,一般size设置为内存页的大小4k或者8k

proxy_buffer 4 4k;

那么一次响应的Proxy Buffer总大小为4 * 4k = 16k

(3) 配置从被代理服务器获取的第一份响应数据的大小

proxy_buffer_size size;

一般第一份响应数据中都包含了http响应头,Nginx通过它来获取响应数据和被代理数据的一些必要信息,一般保持与proxy_buffer指令中的size变量相同即可

(4)配置处于busy状态的Proxy Buffer的总大小

proxy_busy_buffers_size size;

buzy状态的Proxy Buffer是指当一个buffer被填满后,在将所有数据都响应给客户端的过程

(5)配置如果Proxy Buffer的容量不够,响应数据的存放地方

proxy_temp_path path [level1 [level2 [level3]]];

path设置磁盘上存放临时文件的路径
level1的意思是在path路径下的第几级hash目录存放临时文件

(6)配置所有临时文件的总体积大小

proxy_max_temp_file_size size;

存放在磁盘上的临时文件不应该超过该大小,默认值为1024MB

(7)配置同时写入临时文件的数据量的总大小

proxy_temp_file_write_size size;

size为设置的数据量总大小上限值,根据平台的不同,可以为8KB或16KB,一般与平台的内存页大小相同

跳转重定向

proxy_redirect

语法:proxy_redirect [ default|off|redirect replacement ]
默认值:proxy_redirect default
使用字段:http, server, location

Nginx做反向代理,如果在header设置了Host参数,同时如果有协议和二级目录有不一致的情况的时候,
当后端服务做302、301跳转的时候,需要用proxy_redirect将后端设置在response header中的Location做转换.

proxy_set_header

Nginx负载均衡

Nginx学习笔记_第19张图片

GSLB

SLB

Nginx学习笔记_第20张图片

Nginx学习笔记_第21张图片
Nginx学习笔记_第22张图片

nginx upstream模块–负载均衡

upstream模块相关说明
1、upstream模块应放于nginx.conf配置的http{}标签内
2、upstream模块默认算法是wrr (权重轮询 weighted round-robin)

一、分配方式
Nginx的upstream支持5种分配方式,下面将会详细介绍,其中前三种为Nginx原生支持的分配方式,后两种为第三方支持的分配方式。

1、轮询

轮询是upstream的默认分配方式,即每个请求按照时间顺序轮流分配到不同的后端服务器,如果某个后端服务器down掉后,能自动剔除。

upstream backend {
    server 192.168.1.101:8888;
    server 192.168.1.102:8888;
    server 192.168.1.103:8888;
}

2、weight

轮询的加强版,即可以指定轮询比率,weight和访问几率成正比,主要应用于后端服务器异质的场景下。

upstream backend {
    server 192.168.1.101 weight=1;
    server 192.168.1.102 weight=2;
    server 192.168.1.103 weight=3;
}

3、ip_hash

每个请求按照访问ip(即Nginx的前置服务器或者客户端IP)的hash结果分配,这样每个访客会固定访问一个后端服务器,可以解决session一致问题。

upstream backend {
    ip_hash;
    server 192.168.1.101:7777;
    server 192.168.1.102:8888;
    server 192.168.1.103:9999;
}

注意:
1、当负载调度算法为ip_hash时,后端服务器在负载均衡调度中的状态不能是weight和backup。
2、导致负载不均衡。

4、fair

fair顾名思义,公平地按照后端服务器的响应时间(rt)来分配请求,响应时间短即rt小的后端服务器优先分配请求。如果需要使用这种调度算法,必须下载Nginx的upstr_fair模块。

upstream backend {
    server 192.168.1.101;
    server 192.168.1.102;
    server 192.168.1.103;
    fair;
}

5、url_hash,目前用consistent_hash替代url_hash

与ip_hash类似,但是按照访问url的hash结果来分配请求,使得每个url定向到同一个后端服务器,主要应用于后端服务器为缓存时的场景下。

upstream backend {
    server 192.168.1.101;
    server 192.168.1.102;
    server 192.168.1.103;
    hash $request_uri;
    hash_method crc32;
}

其中,hash_method为使用的hash算法,需要注意的是:此时,server语句中不能加weight等参数。
提示:url_hash用途cache服务业务,memcached,squid,varnish。特点:每个rs都是不同的。

参数说明:

从上面实例不难看出upstream中server指令语法如下:server address [parameters]
参数说明:
server:关键字,必选。
address:主机名、域名、ip或unix socket,也可以指定端口号,必选。
parameters:可选参数,可选参数如下:

  1. down:表示当前server已停用
  2. backup:表示当前server是备用服务器,只有其它非backup后端服务器都挂掉了或者很忙才会分配到请求。
  3. weight:表示当前server负载权重,权重越大被请求几率越大。默认是1.
  4. max_fails和fail_timeout一般会关联使用,如果某台server在fail_timeout时间内出现了max_fails次连接失败,那么Nginx会认为其已经挂掉了,从而在fail_timeout时间内不再去请求它,fail_timeout默认是10s,max_fails默认是1,即默认情况是只要发生错误就认为服务器挂掉了,如果将max_fails设置为0,则表示取消这项检查。

举例说明如下:

upstream backend {
    server    backend1.example.com weight=5;
    server    127.0.0.1:8080 max_fails=3 fail_timeout=30s;
    server    unix:/tmp/backend3;           
}

四、缓存服务

缓存类型

  1. 服务端缓存:mencache、redis 、key-value
  2. 代理缓存:nginx缓存
  3. 客户端缓存:缓存在浏览器

数据都是从服务端来的
Nginx学习笔记_第23张图片

proxy_cache模块

在nginx.conf文件中添加如下代码:

http{
    ......
    proxy_cache_path/data/nginx/tmp-test levels=1:2 keys_zone=tmp-test:100m inactive=7d max_size=1000g;
}

代码说明:

  • proxy_cache_path 缓存文件路径
  • levels 设置缓存文件目录层次;levels=1:2 表示两级目录
  • keys_zone 设置缓存名字和共享内存大小
  • inactive 在指定时间内没人访问则被删除
  • max_size 最大缓存空间,如果缓存空间满,默认覆盖掉缓存时间最长的资源。

当配置好之后,重启nginx,如果不报错,则配置的proxy_cache会生效

查看 proxy_cache_path /data/nginx/目录,
会发现生成了tmp-test文件夹。

缓存过期周期(proxy_cache_valid)

nginx的配置项 proxy_cache_valid:配置nginx cache中的缓存文件的缓存时间,如果配置项为:

proxy_cache_valid 200 304 2m;
proxy_cache_valid any 10m;

说明对于状态为200和304的缓存文件的缓存时间是2分钟,两分钟之后再访问该缓存文件时,文件会过期,从而去源服务器重新取数据

缓存的维度(proxy_cache_key)

proxy_cache_key $host$uri$is_args$args;

如何清理指定缓存

方法一、 rm -rf 缓存目录内容
方法二、第三方扩展模块ngx_cache_purge

如何让部分页面不缓存

使用proxy_no_cache

server {
        listen 80;
        server_name _;
        server_tokens off;
        location / {
                proxy_pass              http://127.0.0.1:8080/;
                proxy_set_header        Host                    $host;
                proxy_set_header        X-Real-IP               $remote_addr;
                proxy_set_header        X-Forwarded-For         $proxy_add_x_forwarded_for;
                proxy_cache  my-cache;
                proxy_cache_valid 3s;
                proxy_no_cache $cookie_PHPSESSID;
                proxy_cache_bypass $cookie_PHPSESSID;
                proxy_cache_key         "schemehost$request_uri";
                add_header X-Cache $upstream_cache_status;
        }
}

proxy_no_cache $cookie_PHPSESSID;

禁止反向缓存代理缓存具有PHPSESSIDCookie的请求。否则,您的登录用户页面将被缓存并显示给其他人。如果您使用的Cookie框架使用Cookie的默认PHPSESSID以外的Cookie名称,请务必替换。

proxy_cache_bypass $cookie_PHPSESSID;

指示代理绕过缓存,并且如果传入请求包含PHPSESSID Cookie,则将请求转发到后端。 否则,你最终会显示登录的用户,登出的版本(从缓存提供)。

大文件分片请求(slice)

Nginx的slice模块可以将一个请求分解成多个子请求,每个子请求返回响应内容的一个片段,让大文件的缓存更有效率。
Nginx学习笔记_第24张图片
优势:每个子请求收到的数据都会形成一个独立文件,一个请求断了请求不受影响

缺点:当文件很大或者slice很小的时候,可能会导致文件描述符耗尽等情况

HTTP Range请求

HTTP客户端下载文件时,如果发生了网络中断,必须重新向服务器发起HTTP请求,这时客户端已经有了文件的一部分,只需要请求剩余的内容,而不需要传输整个文件,Range请求就可以用来处理这种问题。

如果HTTP请求的头部有Range字段,如下面所示

Range: bytes=1024-2047

表示客户端请求文件的第1025到第2048个字节,这时服务器只会响应文件的这部分内容,响应的状态码为206,表示返回的是响应的一部分。如果服务器不支持Range请求,仍然会返回整个文件,这时状态码仍是200。

Nginx启用slice模块

ngx_http_slice_filter_module模块默认没有编译到Nginx程序中,需要编译时添加–with-http_slice_module选项。

编译完成后, 需要在Nginx配置文件中开启,配置如下所示

location / {
    slice             1m;
    proxy_cache       cache;
    proxy_cache_key   $uri$is_args$args$slice_range;
    proxy_set_header  Range $slice_range;
    proxy_cache_valid 200 206 1h;
    proxy_pass        http://localhost:8000;
}

slice指令设置分片的大小为1m。 这里使用了proxy_set_header指令,在取源时的HTTP请求中添加了Range头部,向源服务器请求文件的一部分,而不是全部内容。在proxy_cache_key中添加slice_range变量这样可以分片缓存。

slice_range变量

slice_range这个变量作用非常特殊,这个变量的值是当前需要向源服务器请求的分片,如果分片的大小为1m,那么最开始变量的值为bytes=0-1048575,通过配置文件中的proxy_set_header Range $slice_range;可以知道取源时请求的Range头部为Range:bytes=0-1048575,源服务器如果支持Range请求,便会返回响应的前1m字节,得到这个响应后slice_range变量的值变为bytes=1048576-2097171 ,再次取源时便会取后1m字节,依次直到取得全部响应内容。

Nginx分片的实现

Nginx的slice模块是通过挂载filter模块来起作用的,处理流程如下所示
Nginx学习笔记_第25张图片
每次取源时都会携带Range头部,
第一次取源请求前1m内容,如果响应在1m以内,或者源服务器不支持Range请求,返回状态码为200,这时会直接跳过slice模块。
在body_filter中向客户端发送得到的当前的分片,然后检查是否到达文件末尾,如果没有则生成一个子请求,子请求会向源服务器请求下一个分片,依次循环。

深度学习

一、动静分离

通过中间件将动态请求和静态请求分离

分离资源,对服务端减少不必要的请求消耗,减少请求延时

二、Nginx高级模块

secure_link_module模块

一、指定并允许检查请求的链接的真实性以及保护资源免遭未经授权的访问
二、限制链接生效周期
默认情况下nginx不会安装secure_link模块,需要手动指定,配置参数如下

默认情况下nginx不会安装secure_link模块,需要手动指定,配置参数如下

 # ./configure --with-http_secure_link_module \
 --prefix=/usr/local/nginx-1.4.2 --with-http_stub_status_module
 # make
 # make install

配置nginx

server {

    listen       80;
    server_name  s1.down.ttlsa.com;
    access_log  /data/logs/nginx/s1.down.ttlsa.com.access.log  main;

    index index.html index.php index.html;
    root /data/site/s1.down.ttlsa.com;

    location / {
        secure_link $arg_st,$arg_e;
        secure_link_md5 ttlsa.com$uri$arg_e;

        if ($secure_link = "") {
            return 403;
        }

        if ($secure_link = "0") {
            return 403;
        }
    }
}

测试nginx防盗链
打开http://test.ttlsa.com/down.php点击上面的连接下载
下载地址如下:
http://s1.down.ttlsa.com/web/nginx-1.4.2.tar.gz?st=LSVzmZllg68AJaBmeK3E8Q&e=1378881984
页面不要刷新,等到5分钟后在下载一次,你会发现点击下载会跳转到403页面。

secure link 防盗链原理

  • 用户访问down.php
  • down.php根据secret密钥、过期时间、文件uri生成加密串
  • 将加密串与过期时间作为参数跟到文件下载地址的后面
  • nginx下载服务器接收到了过期时间,也使用过期时间、配置里密钥、文件uri生成加密串
  • 将用户传进来的加密串与自己生成的加密串进行对比,一致允许下载,不一致403

Nginx学习笔记_第26张图片
Nginx学习笔记_第27张图片
整个过程实际上很简单,类似于用户密码验证. 尤为注意的一点是大家一定不要泄露了自己的密钥,否则别人就可以盗链了,除了泄露之外最好能经常更新密钥.

secure link 指令
secure_link
语法: secure_link md5_hash[,expiration_time]
默认: none
配置段: location
variables: yes

这个指令由uri中的MD5哈希值和过期时间组成. md5哈希必须由base64加密的,过期时间为unix时间.如果不加过期时间,那么这个连接永远都不会过期.

secure_link_md5
语法: secure_link_md5 secret_token_concatenated_with_protected_uri
默认: none
配置段: location
variables: yes
md5值对比结果,使用上面提供的uri、密钥、过期时间生成md5哈希值.如果它生成的md5哈希值与用户提交过来的哈希值一致,那么这个变量的值为1,否则为0

secure_link_secret
语法: secure_link_secret word
默认:
配置段: location
Reference: secure_link_secret
nginx 0.8.50之后的版本已经使用secure_link_md5取代,不在多说.

注意事项

  1. 密钥防止泄露、以及经常更新密钥
  2. 下载服务器和php服务器的时间不能相差太大,否则容易出现文件一直都是过期状态.

你可能感兴趣的:(Nginx)