Nginx

Nginx进阶

  Nginx主要作用:隐藏真实服务器信息内容,用户在请求的永远是nginx监听的端口,不会访问到真实服务器的IP,黑客攻击的时候是nginx服务,nginx服务瘫痪了,重启就行。安全性的防患,和并发问题(转发:负载均衡),日志解析。

1. Nginx快速入门

1.1 Nginx简介

   Nginx(发音同 engine x)是一款基于异步框架的轻量级/高性能的Web 服务器/反向代理服务器/缓存服务器[静态文件服务]/电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev(伊戈尔·赛索耶夫)所开发,最初供俄国大型网站Rambler.ru及搜寻引擎Rambler使用。

   Web 服务器【apache+php】

Nginx特点

  优点:
      * 高并发量:基于 epoll/kqueue 模型开发,支持高并发量,官方说其支持高达 5w 并发连接数的响应
      * 内存消耗少:善于处理静态文件,相较于其他web(比如:apache),占用更少的内存及资源
      * 简单稳定:配置简单(一个conf文件),运行简单(nginx命令),而且运行稳定
      * 模块化程度高:功能模块插件化设计,可以自由配置相应的功能。[如:负载均衡]
      * 支持Rwrite重写规则:能够根据域名、URL等请求关键点,实现定制化的高质量分发。
      * 低成本:Nginx的负载均衡功能很强大而且免费开源,相较于几十万的硬件负载均衡器成本相当低。
      * 支持多系统:Nginx代码完全用C语言从头写成,可以在各系统上编译并使用。

   缺点:
      * 动态处理差:nginx善于处理静态文件,但是处理动态页面相较于Apache之类重量级的web软件能力稍欠缺。
      * rewrite弱:虽然nginx支持rewrite功能多,但是相较于Apache之类重量级的web软件能力稍欠缺。

1.2 Nginx部署

Nginx软件部署

安装Nginx软件

sudo apt-get install nginx
方法一:快
apt-get install -y build-essential libssl-dev libtool libpcre3 libpcre3-dev make openssl zlib1g-dev 
apt-get install nginx -y
方法二:定制标准高
编译安装,请关注后续"shell自动化运维"课程
检查效果:
netstat -tnulp | grep nginx
浏览器查看
服务相关命令
systemctl start|stop|reload|... nginx
/etc/init.d/nginx start|stop|reload|...
/usr/sbin/nginx ...
nginx -V
Nginx -t # 测试nginx 
Nginx -s reload # 平稳的重启服务

移除相关命令:
查看和nginx相关软件
dpkg --get-selections|grep nginx
移除nginx,包括相关文件
apt-get --purge remove nginx
apt-get --purge remove nginx-common
apt-get --purge remove nginx-core

Nginx配置简介

nginx软件目录:
工作目录:/etc/nginx
执行文件: /usr/sbin/nginx
日志目录:/var/log/nginx
启动文件:/etc/init.d/nginx
web目录:/var/www/html/,首页文件是index.nginx-debian.html
/usr/share/nginx/html/ 首页文件是index.html
6-全局配置段.png

nginx配置文件:

默认文件:
/etc/nginx/nginx.conf
/etc/nginx/conf.d/项目.conf # 项目配置文件
其他目录:
/etc/nginx/{sites-available/sites-enabled/conf.d}
文件结构:
      全局配置段
      http配置段
          server配置段           项目或者应用
              location配置段     url配置
6-nginx访问原理.png

1.3 配置详解

全局配置段

主要是全局性的和服务级别的属性配置,常见的主要有以下几种设置:

user                  设置使用用户(worker)
worker_processes      进行增大并发连接数的处理 跟cpu保持一致 八核设置八个
error_log                 nginx的错误日志
pid                   nginx服务启动时候pid 
events                    定义事件相关的属性
  worker_connections  一个进程允许处理的最大连接数
  use                     定义使用的内核模型

http配置段

主要配置server通用的一些配置
include mime.types;                       # 文件扩展名与文件类型映射表
default_type application/octet-stream;        # 默认文件类型
sendfile on;                              # 开启高效文件传输模式。
autoindex on;                                 # 开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on;                                # 防止网络阻塞
tcp_nodelay on;                           # 防止网络阻塞
keepalive_timeout 120;                        # 长连接超时时间,单位是秒
gzip on;                                  # 开启gzip压缩输出

Server常见配置属性 【创建子集文件(/etc/nginx/conf.d),书写项目的配置信息】
常见样式

server {
    listen 端口;
    server_name 主机名;
    ...
}

server配置段最重要的属性是listen和server_name。它们都是用于匹配并处理请求的。

listen属性

  作用:定义Server监听的ip和port,当ip/port匹配时候才进行下一步匹配
  表现形式:默认监听:80端口

形式 描述 示例 完整示例
IP:Port 地址精确表示样式 listen 10.10.10.10:99 listen 10.10.10.10:99
IP 自动监听 IP:80地址 listen 10.10.10.10 listen 10.10.10.10:80
Port 自动监听 全地址:Port listen 99或 [::]:99 listen 0.0.0.0:99
default_server 自动使用默认的地址 listen default_server listen localhost:80

  使用原则:
     首先将所有样式补全成IP:Port,然后匹配,匹配Server多,那么接着使用Server_name匹配

server_name属性
  作用:定义Server监听的域名,当域名匹配时候才进行下一步操作
   表现形式:

格式 完整样式 前缀正则样式 后缀正则样式 禁止非法域名或IP
形式 www.example.com *.example.com www.example.* _

  使用原则:
    优先使用完整样式,然后使用前缀正则样式,最后使用后缀正则样式,如果正则样式相同的时候,匹配最长,否则就走非法规则。
    非法域名/IP,表示请求到该主机上一个不存在的IP或者域名

root属性
  作用:定义Server相应请求的html文件所在路径
  表现形式:
    root /var/www/html;

index属性
   作用:定义响应请求后返回的文件名称或格式
   表现形式:
    index index.html index.htm index.nginx-debian.html;

return属性
  作用:定义响应请求后返回的http状态码
  表现形式:
    return 444;

location常见配置属性
  location主要是根据Server匹配到的请求路径和关键字去响应和处理。
  语法:

location optional_modifier location_match { ... } 
location @name { ... }

  其中:optional_modifier是匹配条件,location_match是匹配的样式,{}是要执行的操作。匹配条件主要有两种:正则/前缀字符。

匹配规则

类型 含义 匹配方式 优先级 样式
=/路径 精确匹配 前缀 1 l ocation = /image {}
~ 优先匹配 前缀 2 location ~ /page {}
@ 内部重定向 前缀 location @name {}
空 / 通用匹配 前缀 3 location / {}

使用原则:
   前提:根据请求url,获取uri即除了域名/IP之外的部分,用于location匹配
  如果有精确匹配,即 =/路径,找到匹配项后,结束匹配。
    location = 路径 {} 或者 location 完整路径 {}
  如果有优先匹配,即 ~,找到匹配项后,结束匹配。
    location ~ 路径

  @name示例

@用来定义一个命名location。主要用于内部重定向,不能用来处理正常的请求。其用法如下:
location / {
   try_files $uri $uri/ @custom
}
location @custom {
   # ...do something
   # custom 命名的 location中不能再嵌套其它的命名location
}

  关于URL尾部的/有如下注意事项:
  1. location中的location_match字符有无"/"不受影响。/user/等同/user。
  2. 对于访问网站域名(http://sswang.com/),尾部有无"/"不受影响。因为浏览器会自动补全"/"。
  3. 对于访问网站域名后面的路径(http://sswang.com/other/)。尾部的"/"很重要。
    URL尾部的"/"表示目录,没有"/"表示文件,而且文件找不到的话,会发生重定向。
      /other/:表示服务器会自动去该目录下找对应的默认文件。
      /other:表示服务器会先去找other文件,找不到的话会将other当成目录,重定向到/other/,去该目录下找默认文件。

location常见动作:
   在location内部常用的功能属性非常多,常见的基本属性、临时跳转、访问控制、目录列表等。
   基本属性

location / {
      root   /var/www/html;                   # 指定响应请求的文件所在路径
      index  index.php index.html index.htm;  # 指定响应请求的默认文件名称
      expires 7d;                             # 指定响应请求的文件过期时间,一般用于静态文件
      try_files $uri $uri/ =404;              # 如果root指定的路径下有查找的文件,就返回,否则报错
}

  临时跳转

location = /test/ {
    return 302 http://sswang.com/;            # 访问旧url的时候,临时跳转到新url,两个url均不失效 
}

  访问控制

location /nginx-status {
    stub_status on;                       # 开启nginx的状态页面,默认关闭
    allow 192.168.8.14;                       # 允许的访问地址
    deny all;                             # 其他拒绝
}
注意:
  该功能依赖于ngx_http_stub_status_module 模块(默认没有安装,需要定制化安装)

  目录列表

location /upload {
    alias   /var/www/upload;      # 指定查看文件列表路径(绝对路径)
    autoindex on;                     # 开启目录自动索引
    autoindex_exact_size off;     # 默认on,显示文件确切大小(bytes)。off表示显示文件的大概大小(kB/MB/...)
    autoindex_localtime on;       # 默认off,显示的文件时间为GMT时间。on表示显示文件的服务器时间
}
注意:
  该alias指定的目录下,不允许出现index属性指定的文件。

location核心动作
  Nginx的配置语法灵活,可控制度非常高。在0.7以后的版本中加入了一个try_files指令,配合命名location,可以部分替代原本常用的rewrite配置方式,提高解析效率。
指令语法

try_files file ... uri
try_files file ... =code

  作用:
    响应时按顺序查找file,找到则返回file内容,否则的话进行内部重定向(uri)或返回状态码(code)。

2. Nginx进阶知识

正向代理:针对人群:客户端(用户)。用户访问网站,服务器可以获得用户请求IP地址。
  黑客:请求正向代理服务器,正向代理服务器发出请求。隐藏客户端的信息,服务器不知道真实客户端的IP地址。
反向代理:针对人群:服务器,服务器可以屏蔽IP地址。隐藏web服务器的信息,防止别人进行攻击。
  服务器:服务器。服务器访问反向代理服务器,客户请求是访问的是反向代理服务器IP,防止攻击。
  将用户的请求,转发给反向代理服务器。

2.1 反向代理【转发操作】

代理是什么?
  简单来说,我找一个中间人,代替我去做一件事情,只要他给我结果就可以。
  代理一般分为两种:正向代理、反向代理
正向代理&反向代理
示意图


示意图.png

区别
  从用途上来讲:
    正向代理-为局域网客户端向外访问Internet服务。可以使用缓冲特性减少网络使用率。
    反向代理-为局域网服务器向外提供Internet服务。可以使用负载平衡提高客户访问量。还可以基于高级URL策略和管理技术对服务进行高质量管控。

  从安全性来讲:
    正向代理-必须采取安全措施确保内网客户端通过它访问外部网站。隐藏客户端的身份
    反向代理-对外提供服务是透明的,客户端并不知道自己访问的是一个代理。隐藏服务端的身份

nginx 代理模块
官方介绍
  官方资料:http://www.nginx.cn/doc/standard/httpproxy.html
  官方的代理属性很多,我们主要介绍proxy_pass和proxy_set_header属性
  官方代码示例

location / {
: proxy_pass        http://localhost:8000;        # 设定请求跳转后的地址,可以使用hostname或IP:Port形式
: proxy_set_header  X-Real-IP  $remote_addr;  # 后端请求携带原始请求的真实IP地址
}

  属性详解:
    proxy_pass 指令设置被代理服务器的地址和被映射的URI,地址可以使用主机名或IP加端口号的形式

proxy_pass关键点
  proxy_pass后面的路径最后的/作用很重要!!!
  示例代码:

location /html/ {
  1 proxy_pass http://proxy.com; 
    2 proxy_pass http://proxy.com/;
}

  假设我们访问的url是 http://domain.com/html/test.js,如何理解上述两种proxy_pass的区别呢?

对于 1 来说 proxy.com后面没有"/",表示"/html/" 请求(包括自己)后续的路径及其参数等关键字都由http://a.com/来处理,代理后的样式如下:
http://proxy.com/html/test.js
对于 2 来所 proxy.com后面有"/",表示"/html/" 请求后续的路径及其参数等关键字都由http://a.com/来处理,代理后的样式如下:
http://proxy.com/test.js

nginx代理实践
代理的配置文件

~# vim /etc/nginx/conf.d/proxy.conf 
server {
  listen 192.168.8.14:80;
  server_name www.sswang.com;
  location / {
    proxy_pass http://192.168.8.14:9999/hello/;
  }
}

后端服务配置文件

~# vim /etc/nginx/conf.d/hello.conf 
server {
  listen 192.168.8.14:9999;
  location /hello/ {
    alias /var/www/html/hello/;
    try_files $uri $uri/ =404;
  } 
}

准备后端服务文件

mkdir -p /var/www/html/hello/
echo '<h1>proxy_backend</h1>' > /var/www/html/hello/index.html

检查nginx配置后重载服务

/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

查看效果


查看效果.png

2.2 负载均衡

负载均衡是什么?
  我们之前使用proxy_pass的方式实现了nginx代理请求到后端的效果,随着我们的网站访问量越来越多,一个后端就不现实了,那么接下来我们应该如果在访问量日渐增大的情况下,满足线上业务的稳定呢?
  解决方法就是:负载均衡
  负载均衡简单说来人多力量大,打群架。
  在nginx中的负载均衡主要有两种:四层负载(IP:Port)、七层负载(http://xxx)

nginx upstream模块
官方介绍
  官方资料:http://www.nginx.cn/doc/standard/httpupstream.html
  官方的代理属性很多,我们主要介绍upstream和ip_hash属性
  官方代码示例

upstream backend  {
  server backend1.example.com weight=5;
  server backend2.example.com:8080;
  server unix:/tmp/backend3;
}
 
server {
  location / {
    proxy_pass  http://backend;
  }
}

  属性详解:
    upstream 主要是定义一个后端服务地址的集合列表,每个后端服务使用一个server命令表示
     upstream {} 和 Server {} 两部分内容属于平级关系。

后端服务状态
  在upstream模块中,可以使用server命令指定后端服务器的地址,同时还可以设置后端服务器在负载均衡调度中的状态,常用的状态有以下几种:
   down: 表示当前server主机暂时不参与负载均衡。
  backup:后备主机,当所有非backup机器出现故障或者繁忙的时候,才会请求backup机器。
  max_fails:允许请求的最大失败数,默认为1,配合fail_timeout一起使用
   fail_timeout:经历max_fails次失败后,暂停服务的时间,默认为10s。

nginx负载均衡实践【轮询、加权、ip_hash】
负载均衡配置文件

~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
  server 192.168.8.14:10086;
  server 192.168.8.14:10087;
  server 192.168.8.14:10088;
}
server {
  listen 80;
  server_name localhost;
  location / {
    proxy_pass http://backends;
  }
}

后端代理配置文件

~# vim /etc/nginx/conf.d/backend.conf
server {
  listen 192.168.8.14:10086;
  location / {
    root /var/www/html/hello/;
    try_files $uri $uri/ =404;
  }
}
server {
  listen 192.168.8.14:10087;
  location / {
    root /var/www/html/nihao/;
    try_files $uri $uri/ =404;
  }
}
server {
  listen 192.168.8.14:10088;
  location / {
    root /var/www/html/huanying/;
    try_files $uri $uri/ =404;
  }
}

准备后端服务文件

mkdir -p /var/www/html/hello/
echo '<h1>backend_hello</h1>' > /var/www/html/hello/index.html
mkdir -p /var/www/html/nihao/
echo '<h1>backend_nihao</h1>' > /var/www/html/nihao/index.html
mkdir -p /var/www/html/huanying/
echo '<h1>backend_huanying</h1>' > /var/www/html/huanying/index.html

检查nginx配置后重载服务

/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

查看效果

~# for i in {1..100};do curl http://192.168.8.14;done
<h1>backend_hello</h1>
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>
...
<h1>backend_hello</h1>
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>

负载均衡调度算法
  官方资料:http://nginx.org/en/docs/http/ngx_http_upstream_module.html#example
  Nginx提供的负载均衡策略有两种:
     内置策略:nginx自带的算法
    雨露均沾型:轮训、加权轮训、哈希
    定向服务型:ip_hash、least_conn、cookie、route、lean、
    商业类型:ntlm、least_time、queue、stick
  扩展策略:各种结合业务场景自定义的算法或者第三方算法
    自定义算法
    第三方算法:fair、url_hash
  常用算法简介:

轮询(默认):请求按顺序逐一分配到不同的后端服务器。
weight:指定轮询权重,值越大,分配到的几率就越高,适用于后端服务器性能不均衡情况。
ip_hash:按访问IP的哈希结果分配请求,分配后访客访问固定后端服务器,有效的解决动态网页会话共享问题。
fair:基于后端服务器的响应时间来分配请求,响应时间短的优先分配。
url_hash:按访问URL的哈希结果分配请求,使同URL定向到同一台后端服务器,可提高后端缓存服务器的效率。

加权轮训实践
修改负载均衡配置文件

~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
  server 192.168.8.14:10086 backup;
  server 192.168.8.14:10087 weight=1;
  server 192.168.8.14:10088 weight=2;
}
...

检查nginx配置后重载服务

/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

查看效果

~# for i in {1..100};do curl http://192.168.8.14;done
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>
<h1>backend_huanying</h1>
...
<h1>backend_nihao</h1>
<h1>backend_huanying</h1>
<h1>backend_huanying</h1>

ip_hash实践
修改负载均衡配置文件

~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
  ip_hash;
  server 192.168.8.14:10086 ;
  ...
}
...

检查nginx配置后重载服务

/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

查看效果

~# for i in {1..100};do curl http://192.168.8.14;done
<h1>backend_huanying</h1>
...
<h1>backend_huanying</h1>

2.3 日志解析

日志功能简介
日志简介 Logging Settings
  Nginx默认提供了两个日志文件 access.log和error.log,通过access.log可以得到用户请求的相关信息;通过error.log可以获取某个web服务故障或其性能瓶颈等信息。
  而且nginx的日志支持定制化格式,这样我们就可以根据实际的业务情况更好的高效工作。最常见的场景就是获取客户端的IP,记录用户访问量。
  官方介绍:http://nginx.org/en/docs/http/ngx_http_log_module.html
基本配置

# cat /etc/nginx/nginx.conf -n
    40        access_log /var/log/nginx/access.log;
    41        error_log /var/log/nginx/error.log;
注意:
  nginx日志属性设置的完整格式是: 
      属性名称 access_log 
      存储位置 /var/log/nginx/access.log
          日志格式 位置为空表示使用默认的combined 日志格式。它是通过log_format设置的

默认日志格式

log_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';
注意:
log_format是有一批nginx内置变量组合而成的。

日志样式:

# tail /var/log/nginx/access.log
192.168.8.14 - - [12/Nov/2018:08:24:18 -0800] "GET /favicon.ico HTTP/1.0" 404 580 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"

nginx常用内置变量
   nginx常用的内置变量主要是用来分析日志中的http记录的,我们可以根据内置的变量精确的获取相关的信息
默认变量

$remote_addr      前一台主机的ip地址,不一定是真实的客户端IP
$remote_user      用于记录远程客户端的用户名称(一般为“-”)
$time_local           用于记录访问时间和时区
$request          用于记录请求的url以及请求方法
$status               响应状态码,例如:200成功、404页面找不到等。
$body_bytes_sent  给客户端发送的文件主体内容字节数
$http_referer     可以记录用户是从哪个链接访问过来的
$http_user_agent  用户所使用的代理(一般为浏览器)

其他常用变量

$request_uri      包含请求参数的原始URI,不包含主机名
$uri              不带请求参数的当前URI,不包含主机名
$http_x_forwarded_for 可以记录客户端IP,通过代理服务器来记录客户端的ip地址
$http_x_real_ip       可以记录客户端IP,通过代理服务器来记录客户端的ip地址
$args                 这个变量等于请求行中的参数,同$query_string
$host                 请求主机头字段,否则为服务器名称。
$scheme           HTTP方法(如http,https)
$document_uri         与$uri相同
$document_root        当前请求文件配置文件中html的根目录即root值
$request_filename     当前请求的文件路径,由root或alias指令与URI请求生成

示例:

例:http://localhost:10086/sswang1/sswang2/test.txt
$host             localhost
$server_port      10086
$request_uri      /sswang1/sswang2/test.txt
$document_uri     /sswang1/sswang2/test.txt
$document_root        /var/www/html
$request_filename /var/www/html/sswang1/sswang2/test.txt

自定义日志实践
需求:
  基于代理方式访问app1应用,日志存放在/var/logs/nginx/app1/access.log,要求能从日志中获取客户端的IP地址
  因为是获取代理前面客户端的真实IP,需要nginx开启 --with-http_realip_module 功能,使用nginx -V来检查,ubuntu默认安装的已经开启了该功能。

  1. 设置日志格式
 ~# vim /etc/nginx/nginx.conf
  ##
  # Logging Settings
  ##
        log_format proxy_format '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent "$http_referer"'
                    '"$http_user_agent" "$http_x_real_ip" "$http_x_forwarded_for"';

2.负载均衡配置文件

~# vim /etc/nginx/conf.d/upstream.conf
upstream backends {
  server 192.168.8.14:10086;
}
server {
  listen 80;
  server_name localhost;
  location / {
    proxy_pass http://backends;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

3.后端代理配置文件

~# vim /etc/nginx/conf.d/backend.conf
server {
  listen 192.168.8.14:10086;
  root /var/www/html/app1/;
  access_log /var/log/nginx/app1/access.log proxy_format;
  real_ip_header X-Forwarded-For; 
  set_real_ip_from 192.168.0.0/16; 
  real_ip_recursive on;
  location / {
    try_files $uri $uri/ =404;
  }
}

4.准备后端服务文件

mkdir -p /var/www/html/app1/
echo '<h1>backend_app1</h1>' > /var/www/html/app1/index.html
mkdir /var/log/nginx/app1 -p

5.检查nginx配置后重载服务

/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

6.查看效果

在多台主机上执行如下命令
curl http://192.168.8.14

7.查看日志:

app1日志
192.168.8.1 - - [12/Nov/2018:18:28:46 -0800] "GET / HTTP/1.0" 200 22 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36" "192.168.8.1" "192.168.8.1"
192.168.8.14 - - [12/Nov/2018:18:29:30 -0800] "GET / HTTP/1.0" 200 22 "-" "curl/7.47.0" "192.168.8.14" "192.168.8.14"
192.168.8.15 - - [12/Nov/2018:18:31:43 -0800] "GET / HTTP/1.0" 200 22 "-" "curl/7.29.0" "192.168.8.15" "192.168.8.15"
注意:
因为我们的虚拟机使用的是nat网络模型,所以我们用外部的宿主机来访问的话,是通过VMnat8网卡IP来访问nginx代理的,所以记录的是192.168.8.1

注意:
  如果生产中出现了多级代理,
    在第一层代理上添加 proxy_set_header X-Real-IP remote_addr;属性 &emsp;&emsp;&emsp;&emsp;在所有代理上必须添加 proxy_set_header X-Forwarded-Forproxy_add_x_forwarded_for;属性
    真实主机上使用 real_ip_header X-Forwarded-For;属性

2.4 URL重写

  经过上面反向代理和负载均衡的学习,我们知道Nginx可以基于这些方法实现比较好的分发请求的效果,而Nginx还有一个非常强大的精确分发请求的功能:Rewrite
URL重写简介
使用场景
  根据开发功能需求定制用户浏览的URL,访问起来更规范合理,亦方便互联网搜索引擎搜录网站内容
  结合nginx内置变量分析用户请求信息,进行URL定制,达到用户请求的精确分发
  方便企业动态调整项目URL,特别是伪静态处理和项目整体更新(域名)

Rewrite 作用
   rewrite 指令的作用是实现 URL 地址重写(或跳转)。Nginx 的 rewrite 规则需要 PCRE 软件的支持,即通过 Perl 兼容正则表达式语法进行规则匹配。

Rewrite 语法
  rewrite regex replacement [flag];
  语法详解
    rewrite 指令
    regex 正则表达式,用于匹配旧的 URL 地址
    replacement 重写/跳转到新的 URL 地址
    [flag] 标记符号--重写类型
    last 本条规则匹配完成后,继续向下匹配新的location URI规则,用于Server/if配置段
    break 本条规则匹配完成即终止,不再匹配后面的任何规则,一般用于Location配置段
    redirect 返回302临时重定向,浏览器地址会显示跳转后的URL地址,默认属性
    permanent 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址

  regex 常用正则表达式说明

字符            描述                  字符          描述                  字符          描述
\         转义字符            \d          匹配数字                [c]         匹配单个字符c
^         锚定首字符           {n}         重复n次                [a-z]       匹配a-z间任一小写字母
$         锚定尾字符           {n,}        重复>=n次          [^\/]       匹配非/之外的任意字符
*         匹配前面的字符>=0次。如"it*"能匹配"i"及"it"、"itt"
+         匹配前面的字符>=1次。如"it+"能匹配"it"及"itt"、"ittt",但不能匹配"i"
?         匹配前面的字符0/1次,例如"do(es)?"能匹配"do"或者"does","?"等效于"{0,1}"
.         匹配除"\n"之外的任何单个字符,若要匹配包括"\n"在内的任意字符,请使用诸如"[.\n]"之类的模式。
(pattern) 匹配括号内pattern内容,常用$0...$9属性整体获取小括号中的内容,要匹配圆括号字符需要\(Content\)

简单示例

server {
    # 访问 /last.html 的时候,页面内容重写到 /index.html 中
    rewrite /last.html /index.html last;
    # 访问 /break.html 的时候,页面内容重写到 /index.html 中,并停止后续的匹配
    rewrite /break.html /index.html break;
    # 访问 /redirect.html 的时候,页面直接302定向到 /index.html中
    rewrite /redirect.html /index.html redirect;
    # 访问 /permanent.html 的时候,页面直接301定向到 /index.html中
    rewrite /permanent.html /index.html permanent;
    # 把 /html/*.html => /post/*.html ,301定向
    rewrite ^/html/(.+?).html$ /post/$1.html permanent;
    # 把 /search/key => /search.html?keyword=key
    rewrite ^/search\/([^\/]+?)(\/|$) /search.html?keyword=$1 permanent;
}

Rewrite VS location
  rewrite 是在同一域名内更改获取资源的路径
  location 结合 proxy_pass实现反向代理,不会对请求的资源路径进行变动
   location 结合 rewrite 对某个具体的请求进行重写
  这三种状况虽然能实现大致同样的效果,但是有一个优先级保证了他们的基本使用标准:
    1. 执行server块的rewrite指令
    2. 执行location匹配
    3. 执行选定的location中的rewrite指令


rewrite规则.png

Rewrite简单实践(1)
配置文件

~# vim /etc/nginx/conf.d/rewrite.conf
server {
  listen 80;
  server_name rewrite.com;
  rewrite ^/(.*) http://www.rew.com/$1;
}

server {
  listen 80;
  server_name www.rew.com;
  location / {
    root /var/www/html/rew/;
    index index.html index.htm;
  }
}

准备后端服务文件

mkdir -p /var/www/html/rew/
echo '<h1>Rewrite</h1>' > /var/www/html/rew/index.html

# vim /etc/hosts
192.168.8.14 rewrite.com www.rew.com

检查nginx配置后重载服务

/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

查看效果

浏览器检查
curl -I rewrite.com

Rewrite简单实践(2)
配置文件

~# vim /etc/nginx/conf.d/last_break.conf
server {
    listen 80;
    server_name localhost;
    location / {
        rewrite /last/ /ok.html last;
        rewrite /break/ /ok.html break;
    }
    location = /ok.html {
        return 400;
    }
}

准备后端服务文件

echo '<h1>break_OK</h1>' > /var/www/html/ok.html
检查nginx配置后重载服务
/usr/sbin/nginx -t
systemctl reload nginx
netstat -tnulp | grep nginx

查看效果

浏览器检查
curl localhost/break/
curl localhost/last/

if 指令简介
  if指令主要是基于nginx的内置变量值来获取请求的关键字,从而进行精确的分发功能。
if语法

if(内置变量 操作符 值){ ... }

  对给定的条件(内置变量 操作符 值)进行判断。如果为真,大括号内的rewrite指令将被执行。
  if条件(conditon)可以是如下任何内容:
   内置变量主要来自于nginx内部,可以参考2.2.3部分。
  操作符主要有三类:
    精确匹配: =、!=
    正则匹配:*、!~
    文件匹配:
       -f、!-f 判断是否存在普通文件
      -d、!-d 判断是否存在目录文件
      -e、!-e 判断是否存在文件或目录
      -x、!-x 判断文件是否可执行

if指令示例
  如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302

if ($request_method = POST) {
    return 405;
}

  如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查

if (!-f $request_filename){
    break;
    proxy_pass  http://127.0.0.1;
}

  如果host不是www.nihao.com,则重定向到标准的www.nihao.com

server {
  listen 80;
  server_name nihao.com www.nihao.com;

  if ( $host != "www.nihao.com" ){
      rewrite ^/(.*)$ http://www.nihao.com/$1 permanent;
  }
  location / {
    try_files $uri $uri/ =404;
  }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • 大多数 Nginx 新手都会频繁遇到这样一个困惑,那就是当同一个location配置块使用了多个 Nginx 模块...
    SkTj阅读 7,401评论 0 12
  • Nginx简介 解决基于进程模型产生的C10K问题,请求时即使无状态连接如web服务都无法达到并发响应量级一万的现...
    魏镇坪阅读 1,958评论 0 9
  • I/O模型Nginx介绍Nginx的安装和目录结构Nginx的配置Nginx的编译安装 一、I/O模型 (一)I/...
    哈喽别样阅读 865评论 0 4
  • 1.简介:  Nginx:engine X ,2002年,开源,商业版 http协议:web服务器(类似于ht...
    尛尛大尹阅读 1,828评论 0 3
  • Nginx入门 本文目的是学习Nginx+Lua开发,对于Nginx基本知识可以参考如下文章: nginx启动、关...
    小梅飘雪阅读 4,255评论 0 6