浅谈Nginx

2021/8/1 7:08:57

本文主要是介绍浅谈Nginx,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

什么是Nginx ?

  Nginx(发音为“ engine x”)是由俄罗斯软件工程师Igor Sysoev编写的免费开源Web服务器。是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器;同时也是一个IMAP、POP3、SMTP代理服务器;Nginx可以作为一个HTTP服务器进行网站的发布处理,另外Nginx可以作为反向代理进行负载均衡的实现。

  那么Nginx可以做些什么呢?

  • Nginx可以作为静态资源服务器,用于部署静态资源,如作为WEB服务器
  • Nginx可以作为反向代理服务器,进行服务端的负载、转发等操作
  • Nginx可以提供API服务器,如OpenResty

  

  关于反向代理,首先我们要与正向代理相区分,简单来说,正/反向代理是与代理属于客户端还是服务端有关,如代理服务器与客户端绑定则为正向代理,代理服务器与服务端绑定则为反向代理服务器,如下图所示:

   

  关于API服务器,nginx采用模块化设计,一些第三方模块可以直接读写数据库,所以nginx可以通过安装第三方模块来操作数据库,有lua模块提供这样的操作。

  OpenResty是一个基于 NGINX 的可伸缩的 Web 平台,提供了很多高质量的第三方模块。OpenResty 是一个强大的 Web 应用服务器,Web 开发人员可以使用 Lua 脚本语言调动 Nginx 支持的各种 C 以及 Lua 模块,在性能方面,OpenResty可以快速构造出足以胜任 10K 以上并发连接响应的超高性能 Web 应用系统。

为什么要采用Nginx?

  Nginx具备以下特点:

  • Nginx: 开源,高并发,高性能,可扩展性好,高可靠性,热部署
  • Apache低效: 一个连接一个进程

  如果是使用Apache作为Web服务器软件,由于Apache一个进程就是创建一个对应的连接。假设您有1,000个同时连接的客户端,他们请求了类似的内容。如果每个客户端仅分配1 MB的额外内存,则将导致1000 MB(约1 GB)的额外内存专用于仅为1000个客户端提供100 KB的内容。事实上,典型的基于Apache的Web服务器通常为每个连接分配超过1 MB的额外内存,对于持久连接,处理并发性的问题更加明显,因为要避免与建立新的HTTP连接相关的延迟,客户端将保持连接状态,并且对于每个连接的客户端,Web服务器都会分配一定数量的内存。如下所示Nginx市场趋势如下:

  

1、Nginx配置概述

  1.1、配置文件结构

  Nginx配置文件结构目录如下图所示:

  

  具体模块功能分工如下:

  • 全局块

  该部分配置主要影响Nginx全局,通常包括下面几个部分:配置运行Nginx服务器用户(组)、worker process数、Nginx进程PID存放路径、错误日志的存放路径配置文件的引入。

  • events块

  该部分配置主要影响Nginx服务器与用户的网络连接,主要包括:设置网络连接的序列化、是否允许同时接收多个网络连接、事件驱动模型的选择、最大连接数的配置。

  • http块

  定义MIMI-Type自定义服务日志、允许sendfile方式、传输文件连接超时时间、单连接请求数上限。

  • server块

  配置网络监听基于名称的虚拟主机配置、基于IP的虚拟主机配置。

  • location块

  location配置请求根目录配置、更改location的URI、网站默认首页配置。

  1.2、配置文件语法

  Nginx的配置语法如下:

  • 配置文件由指令与指令块构成,每条指令以;结尾,
  • 指令与参数间以空格符号分割
  • 指令块以{}大括号将多条指令组织在一起
  • include语句允许组合多个配置文件以提升可维护性
  • 使用#符号添加注释,提供可读性
  • 使用$符号使用变量
  • 部分指令的参数支持正则表达式

  如示例:

   

2、Nginx详细配置

  2.1、Nginx全局块配置

  配置示例:

user  nobody nobody;
worker_processes  3;

error_log  logs/error.log;
error_log  logs/error.log  notice;
error_log  logs/error.log  info;

pid        logs/nginx.pid;
worker_rlimit_nofile 65535;

  2.1.1、配置运行Nginx服务器用户(组)

  指令格式:user user [group];

  user:指定可以运行Nginx服务器的用户

  group:可选项,可以运行Nginx服务器的用户组。

  如果user指令不配置或者配置为user nobody nobody,则默认所有用户都可以启动Nginx进程(window下不指定)。

  2.1.2、worker process数配置

  Nginx服务器实现并发处理服务的关键,指令格式:worker_processes number | auto;

  number:Nginx进程最多可以产生的worker process数。

  auto:Nginx进程将自动检测并设定worker process数。

  worker_processes设置为多少,Nginx的主进程就会创建多少个worker_processes子进程,根据硬件调整,通常worker_process数等于CPU数量或者2倍于CPU。

  2.1.3、Nginx进程PID存放路径

  Nginx进程是作为系统守护进程在运行,需要在某文件中保存当前运行程序的主进程号,Nginx支持该保存文件路径的自定义。

  指令格式:pid file;

  file:指定存放路径和文件名称如果不指定默认置于路径 logs/nginx.pid。

  2.1.4、错误日志的存放路径

  指定格式:error_log file | stderr;

  file:日志输出到某个文件。

  filestderr:日志输出到标准错误输出。

  这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg。

error_log  logs/error.log;  
error_log  logs/error.log  notice;  
error_log  logs/error.log  info;  

  2.1.5、指定指定进程可以打开的最大描述符

worker_rlimit_nofile 65535;

  这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀,所以最好与ulimit -n 的值保持一致。

  现在在linux 2.6内核下开启文件打开数为65535,worker_rlimit_nofile就相应应该填写65535。这是因为nginx调度时分配请求到进程并不是那么的均衡,所以假如填写10240,总并发量达到3-4万时就有进程可能超过10240了,这时会返回502错误。

  2.2、events模块配置

  配置示例:

use epoll;
accept_mutex on;
multi_accept on;
worker_connections  1024;
keepalive_timeout 60;
client_header_buffer_size 4k;  
open_file_cache max=65535 inactive=60s;   
open_file_cache_valid 80s;
open_file_cache_min_uses 1;

  2.2.1、指定事件模型

use epoll;

  使用epoll的I/O 模型。linux建议epoll,FreeBSD建议采用kqueue,window下不指定。

补充说明:与apache相类,nginx针对不同的操作系统,有不同的事件模型。

A)标准事件模型

  Select、poll属于标准事件模型,如果当前系统不存在更有效的方法,nginx会选择select或poll。

B)高效事件模型

  Kqueue:适用于FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0 和 MacOS X。使用双处理器的MacOS X系统使用kqueue可能会造成内核崩溃。

  Epoll:适用于Linux内核2.6版本及以后的系统。

  /dev/poll:适用于Solaris 7 11/99+,HP/UX 11.22+ (eventport),IRIX 6.5.15+ 和 Tru64 UNIX 5.1A+。

  Eventport:适用于Solaris 10。 为了防止出现内核崩溃的问题, 有必要安装安全补丁。

  2.2.2、设置网络连接的序列化

  指令格式:accept_mutex on | off;

  该指令默认为on状态,但在1.11.3的后续版本中默认为off。表示会对多个Nginx进程接收连接进行序列化,防止多个进程对连接的争抢。也就是防止“惊群现象”发生,就Nginx的场景来解释的话大致的意思就是:当一个新网络连接来到时,多个worker进程会被同时唤醒,但仅仅只有一个进程可以真正获得连接并处理之。如果每次唤醒的进程数目过多的话,其实是会影响一部分性能的。

  所以在这里,如果accept_mutex on,那么多个worker将是以串行方式来处理,其中有一个worker会被唤醒;反之若accept_mutex off,那么所有的worker都会被唤醒,不过只有一个worker能获取新连接,其它的worker会重新进入休眠状态。

Changes with nginx 1.11.3                                        26 Jul 2016
    *) Change: now the "accept_mutex" directive is turned off by default.

  这个值的开关与否其实是要和具体场景挂钩的。 

  2.2.3、是否允许同时接收多个网络连接

  指令格式:multi_accept on | off;

  该指令默认为off状态,意指每个worker process 一次只能接收一个新到达的网络连接。若想让每个Nginx的worker process都有能力同时接收多个网络连接,则需要开启此配置。

  2.2.4、工作进程的最大连接数量

worker_connections 512;

  每个工作进程的最大连接数量。根据硬件调整,和前面工作进程配合起来用,尽量大,但是别把cpu跑到100%就行。每个进程允许的最多连接数,默认512,理论上每台nginx服务器的最大连接数为:worker_processes*worker_connections。

  2.2.5、其余配置

keepalive_timeout 60;  #keepalive超时时间。

#客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求头的大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
#分页大小可以用命令getconf PAGESIZE 取得。但也有client_header_buffer_size超过4k的情况,但是client_header_buffer_size该值必须设置为“系统分页大小”的整倍数。
client_header_buffer_size 4k;  

#这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
open_file_cache max=65535 inactive=60s;   

#这个是指多长时间检查一次缓存的有效信息。
open_file_cache_valid 80s;
#open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如下例,如果有一个文件在inactive时间内一次没被使用,它将被移除。
open_file_cache_min_uses 1;

  2.3、HTTP全局配置模块

  2.3.1、定义MIME-Type

#设定mime类型,类型由mime.type文件定义
include       mime.types;
#指定默认文件类型,默认为text/plain。MIME-Type指的是网络资源的媒体类型,也即前端请求的资源类型include指令将mime.types文件包含进来
default_type  application/octet-stream;

  我们通过cat mime.types来查看mime.types文件内容,我们发现其就是一个types结构,里面包含了各种浏览器能够识别的MIME类型以及对应类型的文件后缀名字,如下所示:

  

  2.3.2、自定义服务日志

  指令格式:access_log path [format],适用于HTTP全局模块、Server全局模块。

  path:自定义服务日志的路径 + 名称

  format:可选项,自定义服务日志的字符串格式。

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';
log_format  log404 '$status [$time_local] $remote_addr $host$request_uri $sent_http_location';

#用了log_format指令设置了日志格式之后,需要用access_log指令指定日志文件的存放路径;
access_log  logs/access.log  main;
access_log  logs/host.access.404.log  log404;

  日志格式如下所示:

$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
$remote_user:用来记录客户端用户名称;
$time_local: 用来记录访问时间与时区;
$request: 用来记录请求的url与http协议;
$status: 用来记录请求状态;成功是200,
$body_bytes_sent :记录发送给客户端文件主体内容大小;
$http_referer:用来记录从那个页面链接访问过来的;
$http_user_agent:记录客户浏览器的相关信息;

  注意:通常web服务器放在反向代理的后面,这样就不能获取到客户的IP地址了,通过$remote_add拿到的IP地址是反向代理服务器的iP地址。反向代理服务器在转发请求的http头信息中,可以增加x_forwarded_for信息,用以记录原有客户端的IP地址和原来客户端的请求的服务器地址。

  2.3.3、缓存配置

  open_file_cache max指令指定缓存是否启用,可以适用于在HTTP全局模块、server全局模块以及location模块进行使用,如下所示:

# 这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
open_file_cache max=65535 inactive=60s;

# 语法:open_file_cache_errors on | off ,默认值:off
# 配置适用模块:http, server, location,这个指令指定是否在搜索一个文件是记录cache错误。
open_file_cache_errors on

#语法:open_file_cache_min_uses number 默认值:1 
# 配置适用模块:http, server, location,这个指令指定了在open_file_cache指令无效的参数中一定的时间范围内可以使用的最小文件数,如果使用更大的值,文件描述符在cache中总是打开状态.
open_file_cache_min_uses 2

# 语法:open_file_cache_valid time 默认值:60 
# 配置适用模块:http, server, location 这个指令指定了何时需要检查open_file_cache中缓存项目的有效信息.
open_file_cache_valid 30s

  2.3.4、允许sendfile方式传输文件

  sendfile参数用于开启高效文件传输模式,也就是基于IO的零拷贝技术,其配置说明如下:

# sendfile指令指定nginx是否调用sendfile函数(zero copy方式)来输出文件,对于普通应用,必须设为on。
# 如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络IO处理速度,降低系统uptime。
# 默认为off,可以在http块,server块,location块。
sendfile on | off;  
# size>0,则Nginx进程的每个worker process每次调用sendfile()传输的数据了最大不能超出此值;若size=0则表示不限制。默认值为0
sendfile_max_chunk size;  #如100K
# 在FreeBSD上使用TCP_NOPUSH套接字选项, 在Linux上使用TCP_CORK套接字选项。 在Linux和FreeBSD 4.*上将响应头和正文的开始部分一起发送;此选项仅在使用sendfile的时候使用。
tcp_nopush on;
#  这个选项仅在将连接转变为长连接的时候才被启用。将tcp_nopush和tcp_nodelay两个指令设置为on用于防止网络阻塞;
tcp_nodelay on;

  2.3.5、HttpGzip模块配置

  gzip模块支持在线实时压缩输出数据流,浏览器请求会告诉服务端当前浏览器支持的压缩类型,服务端会将数据根据浏览器支持的压缩类型进行压缩返回。浏览器请求时会附带支持的压缩类型,如下图所示:

  

  配置示例及含义如下:

# 用于设置开启或者关闭gzip模块,“gzip on”表示开启GZIP压缩,实时压缩输出数据流;
gzip on;
# 设置允许压缩的页面最小字节数,页面字节数从header头的Content-Length中获取。默认值是0,不管页面多大都进行压缩。建议设置成大于1K的字节数,小于1K可能会越压越大;
gzip_min_length 1K
# 表示申请4个单位为16K的内存作为压缩结果流缓存,默认值是申请与原始数据大小相同的内存空间来存储gzip压缩结果;
gzip_buffers 4 16k;
# 用于设置识别HTTP协议版本,默认是1.1,目前大部分浏览器已经支持GZIP解压,使用默认即可;
gzip_http_version 1.1;
# 用来指定GZIP压缩比(1~9),1 压缩比最小,处理速度最快;9 压缩比最大,传输速度快,但处理最慢,也比较消耗cpu资源;
gzip_comp_level 2;
# 用来指定压缩的类型,无论是否指定,“text/html”类型总是会被压缩的;
gzip_types text/plain application/json application/x-javascript application/css application/xml application/xml+rss 
    text/javascript application/x-httpd-php image/jpeg image/gif image/png image/x-ms-bmp;
# 选项可以让前端的缓存服务器缓存经过GZIP压缩的页面,例如用Squid缓存经过Nginx压缩的数据。
gzip_vary o

  效果如下所示(原始文件+效果):

  

  

  2.3.6、负载均衡配置

  upstream是Nginx的HTTP Upstream模块,这个模块通过一个简单的调度算法来实现客户端IP到后端服务器的负载均衡。upstream常见参数如下:

 

service:反向服务地址 加端口。
weight:权重。
max_fails:允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误;并认为主机已挂掉则,踢出。
fail_timeout:踢出后重新探测时间,也就是在经历了max_fails次失败后,暂停服务的时间。max_fails可以和fail_timeout一起使用。
down:表示当前的server暂时不参与负载均衡;
backup:预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻;
max_conns:允许最大连接数。
slow_start:当节点恢复,不立即加入,而是等待 slow_start 后加入服务对列。

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

  upstream支持以下几种负载均衡算法,配置如下所示:

  • 轮询(默认)

  每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。

upstream backserver {
  server 192.168.0.14;
  server 192.168.0.15;
}
  • 指定权重

  指定轮询几率,weight和访问比率成正比,用于后端服务器性能不均的情况。

upstream backserver {
  server 192.168.0.14 weight=8;
  server 192.168.0.15 weight=10;
}
  • ip_hash(IP绑定)

  每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决分布式session的问题。

upstream backserver {
  ip_hash;
  server 192.168.0.14:8888;
  server 192.168.0.15:8080;
}
  • least_conn最少连接优先

  把请求转发给连接数较少的后端服务器。轮询算法是把请求平均的转发给各个后端,使它们的负载大致相同;但是有些请求占用的时间很长,会导致其所在的后端负载较高。这种情况下,least_conn这种方式就可以达到更好的负载均衡效果。

upstream backserver {
    least_conn; #把请求转发给连接数较少的后端服务器
    server localhost:8080 weight=2;
    server localhost:8081;
    server localhost:8082 backup;
    server localhost:8083 max_fails=3 fail_timeout=20s;
}
  • fair(第三方)

  按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream backserver {
    server server1;
    server server2;
    fair;
}
  • url_hash(第三方)

  按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

upstream backserver {
  server squid1:3128;
  server squid2:3128;
  hash $request_uri;
  hash_method crc32;
}

  2.3.7、其他配置文件

server_names_hash_bucket_size 128;
# 保存服务器名字的hash表是由指令server_names_hash_max_size 和server_names_hash_bucket_size所控制的。
# 参数hash bucket size总是等于hash表的大小,并且是一路处理器缓存大小的倍数。在减少了在内存中的存取次数后,使在处理器中加速查找hash表键值成为可能。
# 如果hash bucket size等于一路处理器缓存的大小,那么在查找键的时候,最坏的情况下在内存中查找的次数为2。
# 第一次是确定存储单元的地址,第二次是在存储单元中查找键 值。因此,如果Nginx给出需要增大hash max size 或 hash bucket size的提示,那么首要的是增大前一个参数的大小。

client_header_buffer_size 4k;
# 客户端请求头部的缓冲区大小。这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k,不过由于一般系统分页都要大于1k,所以这里设置为分页大小。
# 分页大小可以用命令getconf PAGESIZE取得。

large_client_header_buffers 8 128k;
# 客户请求头缓冲大小。nginx默认会用client_header_buffer_size这个buffer来读取header值,如果header过大,它会使用large_client_header_buffers来读取。

client_max_body_size 300m;
# 设定通过nginx上传文件的大小。

proxy_connect_timeout 90; 
#后端服务器连接的超时时间_发起握手等候响应超时时间。

proxy_read_timeout 180;
# 连接成功后_等候后端服务器响应时间_其实已经进入后端的排队之中等候处理(也可以说是后端服务器处理请求的时间)。

proxy_send_timeout 180;
# 后端服务器数据回传时间_就是在规定时间之内后端服务器必须传完所有的数据。

proxy_buffer_size 256k;
# 设置从被代理服务器读取的第一部分应答的缓冲区大小,通常情况下这部分应答中包含一个小的应答头。
# 默认情况下这个值的大小为指令proxy_buffers中指定的一个缓冲区的大小,不过可以将其设置为更小。

proxy_buffers 4 256k;
# 设置用于读取应答(来自被代理服务器)的缓冲区数目和大小,默认情况也为分页大小,根据操作系统的不同可能是4k或者8k

proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
# 设置在写入proxy_temp_path时数据的大小,预防一个工作进程在传递文件时阻塞太长

proxy_temp_path /data0/proxy_temp_dir;
# proxy_temp_path和proxy_cache_path指定的路径必须在同一分区

proxy_cache_path /data0/proxy_cache_dir levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
# 设置内存缓存空间大小为200MB,1天没有被访问的内容自动清除,硬盘缓存空间大小为30GB。

keepalive_timeout 120;
# keepalive超时时间。

client_body_buffer_size 512k;
# 如果把它设置为比较大的数值,例如256k,那么,无论使用firefox还是IE浏览器,来提交任意小于256k的图片,都很正常。
# 如果注释该指令,使用默认的client_body_buffer_size设置,也就是操作系统页面大小的两倍,8k或者16k,问题就出现了。
# 无论使用firefox4.0还是IE8.0,提交一个比较大,200k左右的图片,都返回500 Internal Server Error错误

proxy_intercept_errors on;
# 表示使nginx阻止HTTP应答代码为400或者更高的应答。

  2.4、Server全局模块

listen 80;
# listen用于指定虚拟主机的服务端口。
server_name 192.168.8.18 cszhi.com;
# server_name用来指定IP地址或者域名,多个域名之间用空格分开。
index index.html index.htm index.php;
# index用于设定访问的默认首页地址。
root /wwwroot/www.cszhi.com
# root指令用于指定虚拟主机的网页根目录,这个目录可以是相对路径,也可以是绝对路径。
charset gb2312;
# Charset用于设置网页的默认编码格式。
access_log logs/www.ixdba.net.access.log main;
# access_log用来指定此虚拟主机的访问日志存放路径,最后的main用于指定访问日志的输出格式。
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
# 错误页,如果返回对应错误码则跳到对应错误页面

  2.5、location模块

  2.5.1、location模块语法

  location URL配置块位于Server模块之内,URL地址匹配是进行Nginx配置中最灵活的部分。 location支持正则表达式匹配,也支持条件判断匹配,用户可以通过location指令实现Nginx对动、静态网页进行过滤处理。使用location URL匹配配置还可以实现反向代理,用于实现PHP动态解析或者负载负载均衡。location语法为是 location[=|~|~*|^~|@]/uri/{……} ,uri前面的方括号中的内容是可选项,解释如下:

  • / 基于uri目录匹配。
  • = 表示把URI作为字符串,以便与参数中的uri做完全匹配。
  • ~ 表示正则匹配URI时是字母大小写敏感的。
  • ~* 表示正则匹配URI时忽略字母大小写问题。
  • ^~ 表示正则匹配URI时只需要其前半部分与uri参数匹配即可。

  2.5.2、正则优先级

  如果根据匹配规则,多条location命中,则按照优先级进行匹配,其流程如下流程图所示:

优先级:(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)

  

  如下所示示例:

location = / {  
   return 250; 
}
location / {  
   return 251;
} 
location /documents/ {  
   return 252;
}  
location ~ /documents/Abc {
    return 253;
}
location ^~ /images/ {
    return 254;
}
location ~* \.(gif|jpg|jpeg)$ {
    return 255; 
}
location /images/abc {
    return 256;
}
location ~ /images/abc/ {
    return 257;
}

  测试结果如下:

http://localhost/ -> return 250
http://localhost/downloads/download.html -> return 251
http://localhost/images/1.gif -> return 254
http://localhost/images/abc -> return 256  此处实验和理论结果冲突,理论上该是返回254,欢迎大家实验指正
http://localhost/images/abc/def -> return 257 此处试验和理论结果冲突,理论上该是返回254,欢迎大家实验指正
http://localhost/documents/document.html -> return 252
http://localhost/documents/1.jpg -> return 255
http://localhost/documents/Abc.jpg -> return 253

  2.5.3、rewrite重定向

  指令语法:rewrite regex replacement[flag];

  应用位置:server、location、if

  rewrite是实现URL重定向的重要指令,他根据regex(正则表达式)来匹配内容跳转到replacement,结尾是flag标记。

  如:

location /rewrite_to_baidu {
       rewrite ^/ http://www.baidu.com;
}

  效果如下,访问http://localhost/rewrite_to_baidu,直接跳转到了http://www.baidu.com。

  

  rewrite会用到以下语法。

  • last – 基本上都用这个Flag。
  • break – 中止rewirte,不在继续匹配。
  • redirect – 返回临时重定向的HTTP状态302。
  • permanent – 返回永久重定向的HTTP状态301。

  注:last和break最大的不同在于,break是终止当前location的rewrite检测,而且不再进行location匹配 - last是终止当前location的rewrite检测,但会继续重试location匹配并处理区块中的rewrite规则。

 

  • last
  1. 结束当前的请求处理,用替换后的URI重新匹配location;
  2. 可理解为重写(rewrite)后,发起了一个新请求,进入server模块,匹配location;
  3. 如果重新匹配循环的次数超过10次,nginx会返回500错误;
  4. 返回302 http状态码 ;
  5. 浏览器地址栏显示重地向后的url。

 

  • break
  1. 结束当前的请求处理,使用当前资源,不在执行location里余下的语句;
  2. 返回302 http状态码 ;
  3. 浏览器地址栏显示重地向后的url。

 

  另外,还可以通过if判断进行rewrite,语法如下:

Syntax:    if (condition) { ... }
Default:    —
Context:    server, location

  能作为条件的内容如下:

  • 变量名;如果变量的值为空字符串或“ 0”,则为false;否则为true (在1.0.1版之前,任何以“ 0”开头的字符串都被视为错误值。)。
  • 使用“ =”和“ !=”运算符将变量与字符串进行比较;
  • 将变量同使用“ ~”(区分大小写的匹配)和“ ~*”(不区分大小写的匹配)的正则表达式进行匹配。正则表达式也可以使用占位符用于以后通过$1..$9变量进行填充。也可使用非运算符“ !~”和“ !~*”。如果正则表达式包含“ }”或“ ;”字符,则整个表达式应用单引号或双引号引起来。
  • 使用“ -f”和“ !-f”运算符检查文件是否存在;
  • 使用“ -d”和“ !-d”运算符检查目录是否存在;
  • 使用“ -e”和“ !-e”运算符检查文件,目录或符号链接是否存在;
  • 使用“ -x”和“ !-x”运算符检查可执行文件。

  常见参数如下:

$args #这个变量等于请求行中的参数。
$content_length #请求头中的Content-length字段。
$content_type #请求头中的Content-Type字段。
$document_root #当前请求在root指令中指定的值。
$host #请求主机头字段,否则为服务器名称。
$http_user_agent #客户端agent信息
$http_cookie #客户端cookie信息
$limit_rate #这个变量可以限制连接速率。
$request_body_file #客户端请求主体信息的临时文件名。
$request_method #客户端请求的动作,通常为GET或POST。
$remote_addr #客户端的IP地址。
$remote_port #客户端的端口。
$remote_user #已经经过Auth Basic Module验证的用户名。
$request_filename #当前请求的文件路径,由root或alias指令与URI请求生成。
$query_string #与$args相同。
$scheme #HTTP方法(如http,https)。
$server_protocol #请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr #服务器地址,在完成一次系统调用后可以确定这个值。
$server_name #服务器名称。
$server_port #请求到达服务器的端口号。
$request_uri #包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri #不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”。
$document_uri #与$uri相同。

  示例:

# 多目录转成参数 abc.domian.com/sort/2 => abc.domian.com/index.php?act=sort&name=abc&id=2
if ($host ~* (.*)\.domain\.com) {
    set $sub_name $1;   
    rewrite ^/sort\/(\d+)\/?$ /index.php?act=sort&cid=$sub_name&id=$1 last;
}

# 目录对换 /123456/xxxx -> /xxxx?id=123456
rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;

# 例如下面设定nginx在用户使用ie的使用重定向到/nginx-ie目录下:
if ($http_user_agent ~ MSIE) {
    rewrite ^(.*)$ /nginx-ie/$1 break;
}

# 目录自动加“/”
if (-d $request_filename){
    rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
}

# 所有路径为 /images/*.png|jpg的请求都转发到/test下,try_files会依次顺序访问接下来的路径,前一个路径不存在则访问下一个。
# 如下例,要是$arg_file不存在则最后会返回"image not found exception"
location / {
    rewrite '^/images/(.*)\.(png|jpg)$' /test?file=$1.$2;
    set $image_file $1;
    set $image_type $2;
}
location /test {
   root html;
   try_files /$arg_file /image404.html;
}
location /image404.html {
    return 404 "image not found exception";
}

  最后一个示例如下所示:

  

  2.5.4、proxy_pass

  proxy_pass主要用作代理转发,相较rewrite,proxy_pass不影响浏览器地址栏的url。在nginx中配置proxy_pass代理转发时,如果在proxy_pass后面的url加/,表示绝对根路径;如果没有/,表示相对路径,把匹配的路径部分也给代理走。

假设下面四种情况分别用 http://192.168.1.1/proxy/test.html 进行访问。
# 第一种:代理到URL:http://127.0.0.1/test.html
location /proxy/ {
    proxy_pass http://127.0.0.1/;
}
# 第二种(相对于第一种,最后少一个 / ),代理到URL:http://127.0.0.1/proxy/test.html
    location /proxy/ {
proxy_pass http://127.0.0.1;
}
# 第三种:代理到URL:http://127.0.0.1/aaa/test.html
location /proxy/ {
    proxy_pass http://127.0.0.1/aaa/;
}
# 第四种(相对于第三种,最后少一个 / ),代理到URL:http://127.0.0.1/aaatest.html
location /proxy/ {
    proxy_pass http://127.0.0.1/aaa;
}

# 另外可与负载均衡upstream进行配合使用,如下所示,会被负载到:http://30.4.4.4:9999/proxy/test.html或者http://30.4.4.5:8888/proxy/test.html
upstream apptest {
    server 30.4.4.4:9999;
    server 30.4.4.5:8888;
}
location /proxy {
    proxy_pass http://apptest;
    proxy_set_header Host whhealth.org.cn:2005;        
}

  2.5.5、deny、allow

  Nginx的deny和allow指令是由ngx_http_access_module模块提供,Nginx安装默认内置了该模块。 除非在安装时有指定 --without-http_access_module。

  语法:allow/deny address | CIDR | unix: | all

  它表示,允许/拒绝某个ip或者一个ip段访问.如果指定unix:,那将允许socket的访问。注意:unix在1.5.1中新加入的功能。在nginx中,allow和deny的规则是按顺序执行的。

# 示例1:这段配置值允许192.168.0.0/24网段和127.0.0.1的请求,其他来源IP全部拒绝。
location / {
    allow 192.168.0.0/24;
    allow 127.0.0.1;
    deny all;
}
# 示例2:访问的uri中包含admin的请求,只允许110.21.33.121这个IP的请求。
location ~ "admin" {
    allow 110.21.33.121;
    deny all
}
# 禁止多个目录
location ~ ^/(cron|templates)/ {
    deny all;
    break;
}

  效果如下所示:

  

3、常见场景配置

  3.1、日常常见操作

#第一个必选规则是直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。  
#这里是直接转发给后端应用服务器了,也可以是一个静态首页  
location = / {  
    proxy_pass http://tomcat:8080/index  
}  

# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项  
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用  
location ^~ /static/ {  
    root /webroot/static/;  
}  
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {  
    root /webroot/res/;  
}  

# 第三个规则就是通用规则,用来转发动态请求到后端应用服务器  
# 非静态文件请求就默认是动态请求 
location / {  
    proxy_pass http://tomcat:8080/  
}  

  3.2、日志切割

  我们可以通过crontab生成定时任务,定时对nginx日志进行归档。

# 列出当前用户的定时任务crontab
crontab -l
# 编辑crontab
crontab -e
# 分 时 日 月 星期 command
MAILTO=“”
0 0 * * * sh /usr/local/nginx/logs/rotate.sh
# 重启crontab
systemctl restart crond.service
# 查看crontab状态
systemctl status crond.service

  编写rotate.sh脚本进行日志归档操作。

#!/bin/bash
log_path="/usr/local/nginx/logs/"
datetime=$(date -d "-1 day" "+%Y%m%d")
mkdir -p $log_path/history
mv $log_path/access.log $log_path/history/access.log_$datetime.log
mv $log_path/error.log $log_path/history/error.log_$datetime.log

# 像Nginx主进程发送USR1信号重新生成日志文件
kill -USE1 $(cat $log_path/nginx.pid)

  3.3、反向代理

  正向代理,是指客户端与目标服务器之间增加一个代理服务器,客户端直接访问代理服务器,在由代理服务器访问目标服务器并返回客户端并返回 。这个过程当中客户端需要知道代理服务器地址,并配置连接。

# 正向代理
location = /baidu.html {
    proxy_pass http://www.baidu.com;
}

  反向代理,是指客户端访问目标服务器,在目标服务内部有一个统一接入网关将请求转发至后端真正处理 的服务器并返回结果。这个过程当中客户端不需要知道代理服务器地址,代理对客户端而言是透明的。

# 反向代理
location = /fox {
    proxy_pass http://127.0.0.1:8080/;
}

  代理相关参数

proxy_pass # 代理服务
proxy_redirect off; # 是否允许重定向
proxy_set_header Host $host; # 传 header 参数至后端服务
proxy_set_header X-Forwarded-For $remote_addr; # 设置request header 即客户端IP地址 proxy_connect_timeout 90; # 连接代理服务超时时间
proxy_send_timeout 90; # 请求发送最大时间
proxy_read_timeout 90; # 读取最大时间
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;

  3.4、代理缓存

  代理缓存,获取服务器端内容进行缓存,详情可参考官网,http://nginx.org/en/docs/http/ngx_http_proxy_module.html

#proxy_cache_path 缓存路径
#levels 缓存层级及目录位数
#keys_zone 缓存区内存大小
#inactive 有效期
proxy_cache_path /tmp/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
    server {
        listen 80;
        server_name  localhost *.yuanma.com;
        location / {
          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_pass http://backend/;
        proxy_cache my_cache; #以全路径md5值作为Key
        proxy_cache_key $host$uri$is_args$args;
    }
}

  缓存参数详细说明:

  

 

 

  缓存清除 ,添加ngx_cache_purge模块,步骤如下:

#下载ngx_cache_purge 模块包
wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
#查看已安装模块
./sbin/nginx -V
#进入nginx安装包目录 重新构建 --add-module为模块解压的全路径
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with- http_ssl_module --with-debug --add-module=/root/ngx_cache_purge-2.3
#重新编译
make
#热升级
kill -SIGUSR2 nginx的pid号

  清除缓存配置如下:

location ~ /clear(/.*) { 
  #允许访问的IP
  allow 192.168.3.1;
  #禁止访问的IP
  deny all; 
  #配置清除指定缓存区和路径(与proxy_cache_key一致)         
  proxy_cache_purge my_cache $host$1$is_args$args;
}

  3.5、下载限速

 

  3.6、https转http

  生成自签名证书,https://www.cnblogs.com/hnxxcxg/p/7610582.html

# 使用openssl工具生成一个RSA私钥
openssl genrsa -des3 -out server.key 1024 # 生成CSR(证书签名请求)
openssl req -new -key server.key -out server.csr # 删除私钥中的密码
openssl rsa -in server.key -out server.key
# 生成自签名证书
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

  配置https服务 : http://nginx.org/en/docs/http/configuring_https_servers.html

http {
    #监听本机443端口为https协议
    server {
        listen  443 ssl;
        server_name  localhost;

        ssl_certificate      cert.pem;    #SSL证书路径
        ssl_certificate_key  cert.key;    #SSL证书key路径

        ssl_session_cache    shared:SSL:1m;
        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers  on;

        location / {
            proxy_pass http://localhost:8080    #将监听443的https服务转发到本机的8080 http服务
        }
   }
}

 



这篇关于浅谈Nginx的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程