Nginx优化(2)
Nginx优化(2)

Nginx优化(2)

ngx_http_rewrite_module模块

if指令,set指令,break指令,return指令

[root@localhost confd]#vim www.shuhong.com.conf 
server{
      listen 80;
      listen 443 ssl http2;
      ssl_certificate /apps/nginx/certs/www.shuhong.com.pem;
      ssl_certificate_key /apps/nginx/certs/www.shuhong.com.key;
      ssl_session_cache shared:sslcache:20m;
      ssl_session_timeout 10m;
      server_name www.shuhong.com;
      root /data/www/html/pc;
      location = /favicon.ico {
          root /data/www/html/pc/images;
          expires 365d;
          access_log off;
      }
      location /if {
          index index.html;
          default_type text/html;
          echo "if----> $scheme";
          if ( !-e $request_filename ){
             echo "$request_filename is not exist";
             #return 409;
          }
      }
      location /set {
          root /data/nginx/html/pc;
          index index.html;
          default_type text/html;
          set $name shuhong;
          echo $name;
          set $my_port $server_port;
          echo $my_port;
     }
     location /break {
         default_type text/html;
         set $name shuhong;
         echo "break_before:name=$name" ;
         break;
         set $my_port $server_port;
         echo "break_after:my_port=$my_port" ;
         echo "break_after:name=$name" ;
     }
     if ($scheme = http) {
        return https://www.shuhong.com/;
     }
}
if指令判断文件不存在返回指定信息
set指令设置参数
break指令打断rewrite模块指令的执行,但不影响其他模块执行
return指令实现http自动跳转https,curl不支持https的认证所以直接访问会提示证书问题,加K跳过认证,请注意此处是访问的http,自动跳转https

Rewirt 指令 flag 使用

redirect;
#临时重定向,重写完成后以临时重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求;使用相对路径,或者http://或https://开头,状态码:302
permanent;
#重写完成后以永久重定向方式直接返回重写后生成的新URL给客户端,由客户端重新发起请求,状态码:301
break;
#重写完成后,停止对当前URL在当前location中后续的其它重写操作,而后直接跳转至重写规则配置块之后的其它配置;结束循环,建议在location中使用
#适用于一个URL一次重写
last;
#重写完成后,停止对当前URI在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,不建议在location中使用
#适用于一个URL多次重写,要注意避免出现超过十次以及URL重写后返回错误的给用户

break

[root@localhost confd]#mkdir -p /data/site
[root@localhost confd]#echo "1.html" >/data/site/1.html
[root@localhost confd]#echo "2.html" >/data/site/2.html
[root@localhost confd]#echo "3.html" >/data/site/3.html
[root@localhost confd]#echo "a.html" >/data/site/a.html
[root@localhost confd]#echo "b.html" >/data/site/b.html

[root@localhost confd]#vim mobile.shuhong.com.conf 
server {
       listen 80;
       server_name m.shuhong.com;
       root /data/site;

       location / {
           rewrite /1.html /2.html break;
           rewrite /2.html /3.html;
       }

       location /2.html {
           rewrite /2.html /a.html;
       }

       location /3.html {
           rewrite /3.html /b.html;
       }
}
#测试结果: 当请求/1.html,最终会访问/2.html
#原因:在location{}内部,遇到break,本location{}内以及后面的所有location{}内的所有指令都不再执行。

last

[root@localhost confd]#vim mobile.shuhong.com.conf 
server {
       listen 80;
       server_name m.shuhong.com;
       root /data/site;

       location / {
           rewrite /1.html /2.html last;
           rewrite /2.html /3.html;
       }

       location /2.html {
           rewrite /2.html /a.html;
       }

       location /3.html {
           rewrite /3.html /b.html;
       }
}
# 测试结果:当请求/1.html,最终会访问/a.html
# 原因:在location{}内部,遇到last,本location{}内后续指令不再执行,
# 而重写后的url会对所在的server{…}标签重新发起请求,从头到尾匹配一遍规则,哪个匹配则执行哪个。

permanent 301永久重定向

[root@localhost confd]#vim mobile.shuhong.com.conf 
server {
       listen 80;
       server_name m.shuhong.com;
       root /data/site;

       location / {
           rewrite /1.html /2.html permanent;
           rewrite /2.html /3.html;
       }
}
#测试结果: 当请求/1.html,最终会访问/2.html
#原因:在location{}内部遇到permanent,客户端会重新发起新请求到新的重定向地址进行访问,而且url会修改为后面的新URL

redirect 临时重定向302

[root@localhost confd]#vim mobile.shuhong.com.conf 
server {
       listen 80;
       server_name m.shuhong.com;
       root /data/site;

       location / {
           rewrite /1.html /2.html redirect;
           rewrite /2.html /3.html;
       }
}
#测试结果: 当请求/1.html,最终会访问/2.html
#原因:在location{}内部遇到redirect,客户端会重新发起新请求到新的重定向地址进行访问,而且url会修改为后面的新URL

应用案例

自动跳转 https

[root@localhost confd]#vim www.shuhong.com.conf 
server{
      listen 80;
      listen 443 ssl http2;
      ssl_certificate /apps/nginx/certs/www.shuhong.com.pem;
      ssl_certificate_key /apps/nginx/certs/www.shuhong.com.key;
      ssl_session_cache shared:sslcache:20m;
      ssl_session_timeout 10m;
      server_name www.shuhong.com;
      root /data/www/html/pc;
      location = /favicon.ico {
          root /data/www/html/pc/images;
          expires 365d;
          access_log off;
      }
      location / { #针对全站跳转
          root /data/www/html/pc;
          index index.html;
          if ($scheme = http ){ #如果没有加条件判断,会导致死循环
              rewrite ^/(.*) https://$host/$1 redirect;
          }
     }
     location /login { #针对特定的URL进行跳转https
          if ($scheme = http ){ #如果没有加条件判断,会导致死循环
              rewrite / https://$host/login redirect;
          }
     }
}
全站重定向https
#针对指定路径重定向https

判断文件是否存在

[root@localhost confd]#vim www.shuhong.com.conf 
server{
      listen 80;
      listen 443 ssl http2;
      ssl_certificate /apps/nginx/certs/www.shuhong.com.pem;
      ssl_certificate_key /apps/nginx/certs/www.shuhong.com.key;
      ssl_session_cache shared:sslcache:20m;
      ssl_session_timeout 10m;
      server_name www.shuhong.com;
      root /data/www/html/pc;
      location = /favicon.ico {
          root /data/www/html/pc/images;
          expires 365d;
          access_log off;
      }
      location / { #针对全站跳转
          root /data/www/html/pc;
          index index.html;
          if ($scheme = http ){ #如果没有加条件判断,会导致死循环
              rewrite ^/(.*) https://$host/$1 redirect;
          }
          if (!-e $request_filename){
              rewrite .* http://www.shuhong.com/index.html;  #重定向错误页面到主页
          }
     }
     location /login { #针对特定的URL进行跳转https
          if ($scheme = http ){ #如果没有加条件判断,会导致死循环
              rewrite / https://$host/login redirect;
          }
     }
}
#访问不存在的路径重定向到主页

指定客户端类型跳转新的域名

[root@localhost confd]#vim www.shuhong.com.conf 
server{
      listen 80;
      listen 443 ssl http2;
      ssl_certificate /apps/nginx/certs/www.shuhong.com.pem;
      ssl_certificate_key /apps/nginx/certs/www.shuhong.com.key;
      ssl_session_cache shared:sslcache:20m;
      ssl_session_timeout 10m;
      server_name www.shuhong.com;
      root /data/www/html/pc;
      location = /favicon.ico {
          root /data/www/html/pc/images;
          expires 365d;
          access_log off;
      }
      if ($http_user_agent ~* "android|iphone|ipad") {
          rewrite ^/(.*)$ http://m.shuhong.com/$1 redirect;
          #return 302 http://m.shuhong.com$request_uri ;
      }
}
#根据客户端类型跳转页面,上面输入的是www的站点,回车后会跳转为m.shuhong.com站点

网站维护跳转

[root@localhost confd]#vim www.shuhong.com.conf 
server{
      listen 80;
      listen 443 ssl http2;
      ssl_certificate /apps/nginx/certs/www.shuhong.com.pem;
      ssl_certificate_key /apps/nginx/certs/www.shuhong.com.key;
      ssl_session_cache shared:sslcache:20m;
      ssl_session_timeout 10m;
      server_name www.shuhong.com;
      root /data/www/html/pc;
      location = /favicon.ico {
          root /data/www/html/pc/images;
          expires 365d;
          access_log off;
      }
      #在server层下设定ip变量值为0
      set $ip 0;
      #如果来源IP是10.0.0.152或153则设定变量为ip变量为1。
      if ($remote_addr = 10.0.0.152) {
          set $ip 1;
      }
      if ($remote_addr = 10.0.0.153) {
          set $ip 1;
      }
      #如果来源IP不是10.0.0.152或153、则跳转至/data/site/weihu.html这个页面,否则不做任何处理
      if ($ip = 0) {
          rewrite ^(.*)$ /weihu.html break;
      }
      #如果想针对某个location进行操作,则将如上配置写入location中即可
}
#参与维护的ip可以访问
#不参与维护的客户机跳转到维护界面等待

防盗链实现

[root@centos8 ~]# vim /apps/nginx/conf/conf.d/pc.conf
server {
       index index.html;
       valid_referers none blocked server_names *.magedu.com *.wang.org ~\.google\. ~\.baidu\. ~\.bing\. ~\.so\. ; #定义有效的referer
       if ($invalid_referer) { #假如是使用其他的无效的referer访问
           return 403 "Forbidden Access"; #返回状态码403
           #return 302 http://www.wangxiaochun.com/testdir/daotu.jpg;
           #rewrite ^(.*)$ /daolian.jpg break;#或者返回错误图片
       }
......
}
#重启Nginx并访问测试
#指定referer为http://www.baidu.com进行访问
[root@centos7 ~]# curl -e 'http://www.baidu.com' www.wang.org
#指定referer为http://www.xxx.com进行访问,被拒绝
[root@centos7 ~]# curl -e 'http://www.xxx.com' www.wang.org
#不加http的referer不会拒绝
[root@centos7 ~]# curl -e 'www.xxx.com' www.wang.org

反向代理单台 web 服务器

[root@localhost confd]#vim www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       location / {
           proxy_pass http://10.0.0.154;
           proxy_set_header Host $http_host; #转发主机头至后端服务器
           proxy_connect_timeout 10s;
       }
}
#153作为代理转发152的请求给154

指定 location 实现反向代理

[root@localhost confd]#vim www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       location / {
           index index.html index.php;
           root /data/www/html/pc;
       }
       location /static {
           proxy_pass http://10.0.0.154:80/; #注意有后面的/, 表示置换
           #proxy_pass http://10.0.0.154:80; #后面没有 / , 表示附加
       }
}
#访问指定路径/static才作为代理跳转到154

反向代理示例: 缓存功能

#未开启缓存测压
[root@localhost ~]#curl www.shuhong.com
10.0.0.154
[root@localhost ~]#ab -n 2000 -c200 http://www.shuhong.com/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.shuhong.com (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests


Server Software:        nginx
Server Hostname:        www.shuhong.com
Server Port:            80

Document Path:          /
Document Length:        11 bytes

Concurrency Level:      200
Time taken for tests:   0.413 seconds
Complete requests:      2000
Failed requests:        0
Total transferred:      508000 bytes
HTML transferred:       22000 bytes
Requests per second:    4842.72 [#/sec] (mean)
Time per request:       41.299 [ms] (mean)
Time per request:       0.206 [ms] (mean, across all concurrent requests)
Transfer rate:          1201.22 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    8   2.7      9      12
Processing:     6   31  15.4     29      92
Waiting:        2   31  15.4     29      92
Total:          7   39  15.3     38      96

Percentage of the requests served within a certain time (ms)
  50%     38
  66%     39
  75%     39
  80%     39
  90%     45
  95%     88
  98%     92
  99%     93
 100%     96 (longest request)

#准备缓存配置
[root@localhost confd]#vim /apps/nginx/conf/nginx.conf
proxy_cache_path /data/www/proxycache levels=1:1:1 keys_zone=proxycache:20m inactive=120s max_size=1g; #配置在nginx.conf http配置段
[root@localhost confd]#vim www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       location / {
           proxy_pass http://10.0.0.154:80;
           proxy_cache proxycache;
           proxy_cache_key $request_uri;
           #proxy_cache_key $host$uri$is_args$args;
           proxy_cache_valid 200 302 301 10m;
           proxy_cache_valid any 5m; #必须指定哪些响应码的缓存
           proxy_set_header Host $http_host; #转发主机头至后端服务器
           #proxy_set_header clientip $remote_addr
       }

}



#配置缓存功能后的性能
[root@localhost ~]#curl www.shuhong.com
10.0.0.154
[root@localhost ~]#ab -n 2000 -c200 http://www.shuhong.com/
This is ApacheBench, Version 2.3 <$Revision: 1843412 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking www.shuhong.com (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests


Server Software:        nginx
Server Hostname:        www.shuhong.com
Server Port:            80

Document Path:          /
Document Length:        11 bytes

Concurrency Level:      200
Time taken for tests:   0.200 seconds
Complete requests:      2000
Failed requests:        0
Total transferred:      508000 bytes
HTML transferred:       22000 bytes
Requests per second:    10023.00 [#/sec] (mean)
Time per request:       19.954 [ms] (mean)
Time per request:       0.100 [ms] (mean, across all concurrent requests)
Transfer rate:          2486.17 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    9   1.4      9      15
Processing:     6    9   2.0      9      17
Waiting:        1    9   1.7      9      16
Total:         12   18   2.5     18      27

Percentage of the requests served within a certain time (ms)
  50%     18
  66%     18
  75%     19
  80%     19
  90%     22
  95%     25
  98%     26
  99%     27
 100%     27 (longest request)

#验证153代理服务器缓存文件
[root@localhost confd]#tree /data/www/proxycache/
/data/www/proxycache/
└── 9
    └── d
        └── 7
            └── 6666cd76f96956469e7be39d750cc7d9

3 directories, 1 file

添加响应报文的头部信息

[root@localhost confd]#vim www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       location / {
           proxy_pass http://10.0.0.154:80;
           proxy_cache proxycache;
           proxy_cache_key $request_uri;
           #proxy_cache_key $host$uri$is_args$args;
           proxy_cache_valid 200 302 301 10m;
           proxy_cache_valid any 5m; #必须指定哪些响应码的缓存
           proxy_set_header Host $http_host; #转发主机头至后端服务器
           #proxy_set_header clientip $remote_addr
           add_header X-Via $server_addr; #当前nginx主机的IP
           add_header X-Cache $upstream_cache_status; #缓存命中HIT,未命中MISS
           add_header X-Accel $server_name; #客户访问的FQDN
       }

}
#第一次X-Cach:MISS无缓存,第二次X-Cach:HIT有缓存

实现反向代理客户端 IP 透传(一级)

[root@localhost confd]#vim www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       location / {
           index index.html index.php;
           root /data/nginx/html/pc;
           proxy_pass http://10.0.0.154;
           #proxy_set_header X-Real-IP $remote_addr; #只添加客户端IP到请求报文头  部,转发至后端服务器
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #添加客户端IP和反向代理服务器IP到请求报文头部
       }
}
#说明$proxy_add_x_forwarded_for
#此变量表示将客户端IP追加请求报文中X-Forwarded-For首部字段,多个IP之间用逗号分隔,如果请求中没有X-Forwarded-For,就使用$remote_add

#后端apache日志配置,查看穿透结果
[root@rocky8 html]#vim /etc/httpd/conf/httpd.conf 
LogFormat "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
[root@rocky8 html]#systemctl restart httpd
#网站访问
#从日志查看IP穿透

实现反向代理客户端 IP 透传(二级)

#二级IP穿透
#代理服务器都开启访问者日志

#第一台代理服务器配置153
[root@localhost confd]#vim www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       location / {
           #proxy_pass http://10.0.0.155;
           proxy_pass http://www.hh.com;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       }
}

#第二台代理服务器配置155
[root@rocky8 ~]#vim /etc/nginx/nginx.conf
    server {
           listen 80;
           server_name www.hh.com;
           location = / {
               proxy_pass http://10.0.0.154;
               proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           }
    }
#访问站点
#第一台代理服务器的访问日志
#第二台服务器访问日志
#应用服务器访问日志

实战案例: 基于Cookie 实现会话绑定

[root@localhost conf]#vim nginx.conf
        upstream websrvs {
            hash $cookie_hello; #hello是cookie的key的名称
            server 10.0.0.155:80 weight=2;
            server 10.0.0.154:80 weight=1;
        }
[root@localhost conf]#vim confd/www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       location / {
           proxy_pass http://websrvs;
           proxy_set_header Host $http_host; #转发主机头至后端服务器
       }
}
#不带cookie的时候按权重负载,带cookie按找cookie值绑定调度

实战案例: 实现 HTTPS 的负载均衡

[root@localhost conf]#vim confd/www.shuhong.com.conf
upstream websrvs {
       server 10.0.0.154:80 ;
       server 10.0.0.155:80 ;
}
server {
       listen 80;
       server_name www.shuhong.com;
       return 302 https://$server_name$request_uri;
}
server {
       listen 443 ssl http2;
       server_name www.shuhong.com;
       ssl_certificate /apps/nginx/certs/www.shuhong.com.pem;
       ssl_certificate_key /apps/nginx/certs/www.shuhong.com.key;
       ssl_session_cache shared:sslcache:20m;
       ssl_session_timeout 10m;
       location / {
           proxy_pass http://websrvs;
           proxy_set_header Host $http_host;
       }
}
#客户端访问服务时候转换为https,后端代理发送请求给服务器以http

Nginx解决跨域问题

#跨域问题说明
#当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。
通常由于同域安全策略(the same-origin security policy),浏览器会禁止跨域请求。
值得注意的是:虽然因为跨域的原因会导致浏览器禁止访问而获取数据失败,但返回的状态码仍为200
常见的解决方案有:CORS,JSONP,Nginx反向代理等

采用CORS(Cross-Origin Resource Sharing 跨域资源共享)技术,可以允许当前域的Web相关资源被其他域的脚本请求访问
CORS是一种基于HTTP头的机制,该机制允许使用AJAX发送跨域请求,只要HTTP响应头中包含了相应的CORS响应头。CORS需要浏览器和服务器同时支持,CORS机制在老版本的浏览器中不支持,现代浏览器都支持CORS。在使用CORS发送AJAX请求时浏览器端代码和过去一致,服务器端需要配置CORS的响应头。
www.shuzihan.com 上运行动态程序
[root@rocky8 ~]#./web_demo 
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.

[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
 - using env:	export GIN_MODE=release
 - using code:	gin.SetMode(gin.ReleaseMode)

[GIN-debug] GET    /hello                    --> main.sayHello (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080


#准备出现跨域问题的页面
[root@localhost confd]#vim /apps/nginx/html/cors.html 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cross-origin resource sharing</title>
</head>
    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
    <script>
       $.ajax({
        url:'https://www.shuzihan.com:8080/hello',
        type:'get',
        data:{},
        success:function(res){
            //res = JSON.parse(res);
            console.log('请求成功',res)
        },
        error:function(er){
            console.log('请求错误')
        }
      })
    </script>
<body>
</body>
</html>

[root@localhost confd]#curl www.shuzihan.com:8080/hello
{"age":18,"message":"Hello world!","name":"wangxiaochun"}


#www.shuhong.com 做代理 ,并修改前端页面文件,解决跨域问题
[root@localhost confd]#vim www.shuhong.com.conf
server {
       listen 80;
       server_name www.shuhong.com;
       root /apps/nginx/html;
       location /hello {
           proxy_pass https://www.shuzihan.com:8080; #指向第二个域
}
}

[root@localhost confd]#vim /apps/nginx/html/cors.html 
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cross-origin resource sharing</title>
</head>
    <script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
    <script>
       $.ajax({
        url:'http://www.shuhong.com/hello',
        type:'get',
        data:{},
        success:function(res){
            //res = JSON.parse(res);
            console.log('请求成功',res)
        },
        error:function(er){
            console.log('请求错误')
        }
      })
    </script>
<body>
</body>
</html>