nginx-全文通

Nginx 的其他应用

Nginx的stream allow deny 应用

Nginx yum安装

配置Nginx的yum源

[nginx] 
name=nginx repo 
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/ 
gpgcheck=0 
enabled=1

安装以及重启,检查

yum -y install nginx 默认安装最新版本
启动 关闭 重启 加载
systemctl start/stop/restart/reload nginx
设置开机自启动
systemctl ensible nginx

测试:浏览器访问或者curl访问
检查服务进程:ps aux |grep nginx
检查端口监听:netstat -lnp |grep ‘:80’
有防火墙,需加规则iptables -I INPUT -p tcp --dport 80 -j ACCEPT
nginx -V查看版本以及各个目录、参数

[root@localhost yum.repos.d]# nginx -V 
nginx version: nginx/1.24.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib64/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -fPIC' --with-ld-opt='-Wl,-z,relro -Wl,-z,now -pie'

nginx 源码安装

wget http://nginx.org/download/nginx-1.24.0.tar.gz

tar -zxvf nginx-1.24.0.tar.gz -C /opt

安装编译环境
yum -y install gcc pcre-devel openssl-devel
编译安装
./configure --prefix=/opt/nginx-1.24.0
make && make install
nginx启动
/opt/nginx-1.24.0/sbin/nginx
Nginx加载
/opt/nginx-1.24.0/sbin/nginx -s reload
Nginx关闭
/opt/nginx-1.24.0/sbin/nginx -s stop

nginx 的控制脚本

#/bin/bash 
NGINX_SBIN="/opt/nginx-1.24.0/sbin/nginx"
NGINX_CONF="/opt/nginx-1.24.0/conf/nginx.conf"
NGINX_PID="/opt/nginx-1.24.0/logs/nginx.pid"
RETVAL=0
prog="Nginx"

start() 
{
    echo -n $"Starting $prog: "
    mkdir -p /dev/shm/nginx_temp
    daemon $NGINX_SBIN -c $NGINX_CONF
    RETVAL=$?
    echo
    return $RETVAL
}

stop() 
{
    echo -n $"Stopping $prog: "
    killproc -p $NGINX_PID $NGINX_SBIN -TERM
    rm -rf /dev/shm/nginx_temp
    RETVAL=$?
    echo
    return $RETVAL
}

reload()
{
    echo -n $"Reloading $prog: "
    killproc -p $NGINX_PID $NGINX_SBIN -HUP
    RETVAL=$?
    echo
    return $RETVAL
}

restart()
{
    stop
    start
}

configtest()
{
    $NGINX_SBIN -c $NGINX_CONF -t
    return 0
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  reload)
        reload
        ;;
  restart)
        restart
        ;;
  configtest)
        configtest
        ;;
  *)
        echo $"Usage: $0 {start|stop|reload|restart|configtest}"
        RETVAL=1
esac

exit $RETVAL

Nginx的目录解析

ls -la /usr/local/nginx/conf 配置文件
ls -la /usr/local/nginx/logs 日志
ls -la /usr/local/nginx/html 默认页
/usr/local/nginx/sbin/nginx -V 查看版本号

Nginx配置文件

全局配置

全局配置(user、worker_processes、error_log、pid)
注意:Nginx的访问日志access.log的访问日志,不是在全局配置,是在http配置

worker配置

在这里插入图片描述
这个跟worker配置有关系,这个设置大少跟cpu决定

#user  nobody;
worker_processes  2;

events配置项结构

网络连接相关,worker_connections)

默认配置

这个是Nginx的默认配置

events {
    worker_connections  1024;
}

定义每个work_process同时开启的最大连接数,即允许最多只能有这么多连接

选项配置

accept_mutex on;
multi_accept on;
use epoll;

accept_mutex on;
当某一个时刻只有一个网络连接请求服务器时,服务器上有多个睡眠的进程会被同时叫醒,这样会损耗一定的服务器性能。
Nginx中的accept_mutex设置为on,将会对多个Nginx进程(worker processer)接收连接时进行序列化,防止多个进程争抢资源。
默认就是on。

multi_accept on;
nginx worker processer可以做到同时接收多个新到达的网络连接,前提是把该参数设置为on。
默认为off,即每个worker process一次只能接收一个新到达的网络连接。

Nginx服务器提供了多个事件驱动器模型来处理网络消息。
其支持的类型有:select、poll、kqueue、epoll、rtsing、/dev/poll以及eventport。

  • select:只能在Windows下使用,这个事件模型不建议在高负载的系统使用

  • poll:Nginx默认首选,但不是在所有系统下都可用

  • kqueue:这种方式在FreeBSD 4.1+, OpenBSD2.9+, NetBSD 2.0, 和 MacOS X系统中是最高效的

  • epoll: 这种方式是在Linux 2.6+内核中最高效的方式

  • rtsig:实时信号,可用在Linux 2.2.19的内核中,但不适用在高流量的系统中

  • /dev/poll: Solaris 7 11/99+,HP/UX 11.22+, IRIX 6.5.15+, and Tru64 UNIX 5.1A+操作系统最高效的方式

  • eventport: Solaris 10最高效的方式

http配置项

官方文档

MIME-Type

http {
    include       mime.types;
    default_type  application/octet-stream;

include mime.types; //cat conf/mime.types
这个文件在conf同一级别的文件
定义nginx能识别的网络资源媒体类型(如,文本、html、js、css、流媒体等)定义很多Nginx的支持打开的文件的类型,这样浏览器才能打开

default_type application/octet-stream;
定义默认的type,如果不定义该项,默认为text/plain.

log_format

#log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

log_format main '$remote_addr - r e m o t e u s e r [ remote_user [ remoteuser[time_local] “KaTeX parse error: Double superscript at position 30: … '̲status b o d y b y t e s s e n t " body_bytes_sent " bodybytessent"http_referer” ’
‘“ h t t p u s e r a g e n t " " http_user_agent" " httpuseragent""http_x_forwarded_for”’;

其中main为日志格式的名字,后面的为nginx的内部变量组成的一串字符串。
这个可以,设置全流程访问 request_time和转发后台的访问配置upstream_response_time

access_log logs/access.log main;

定义日志的路径以及采用的日志格式,该参数可以在server配置块中定义。

server配置项

Nginx 的架构分析

Nginx模块化

Nginx有很多可选的第三方模块,比如HTTP模块、邮件模块

Nginx的web请求机制

并行处理:多进程、多线程、异步

Nginx的事件驱动模型

Nginx的事件驱动模式,跟liunx的内核有关系,比如poll模型 epoll模型 select模型

Nginx的设计架构的概览

Nginx基于模块化设计、基于事件驱动模型处理请求、主进程和工作进程
Nginx服务器使用 master/worker 多进程模式。
master进程是接受和处理外部信号;
work是调用第三方模块以及对事件的接收和处理等工作。
主进程的工作模式:
字进程的工作模式:

Nginx虚拟主机配置

在http 配置中有server配置,每一个server是一个虚拟主机

为了更方便学习,这里采用分配置文件的方式,在http配置中添加,并把server部分进行删除或者注释避免冲突。

       # deny access to .htaccess files, if Apache's document root
        # concurs with nginx's one
        #
        #location ~ /\.ht {
        #    deny  all;
        #}
        include vhost/*.conf
    }

按照这个配置,需要在conf目录下创建一个vhost目录,再从vhost目录下创建各种配置文件
mkdir /usr/local/nginx/conf/vhost

先做一个虚拟主机的配置文件,1.conf
为了方便管理后续的网站 :创建一个网站根目录 mkdir -p /data/wwwroot 后续所有的网站文件都放到网站根目录下
创建网站目录以及测试文件:
mkdir -p /data/wwwroot/www.1.com/
mkdir -p /data/wwwroot/www.2.com/
echo www.1.com > /data/wwwroot/www.1.com/index.html
echo www.2.com > /data/wwwroot/www.2.com/index.html
创建分配置文件
vim /usr/local/nginx/conf/vhost/www.1.com.conf

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
}

vim /usr/local/nginx/conf/vhost/www.2.com.conf

server{
  listen 80;
  server_name www.2.com;
  root /data/wwwroot/www.2.com;
}

检查配置文件加载服务
/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s relaod

使用curl 检查结果
在这里插入图片描述
从截图可以看出,在访问没有定义的网站,也可以访问到,www.1.com 这种特性叫做默认虚拟主机,不管你使用什么域名,都可以访问到默认的虚拟主机。

Nginx配置默认虚拟主机

默认不加跟目录,就会默认第一个虚拟主机是默认虚拟主机

vim  conf/vhost/default.conf 
server{
  listen 80 default_server;
  deny all;
}

重新加载,并进行测试访问
在这里插入图片描述

Nginx虚拟主机的泛解析

vim www.king.com.conf 
server {
    listen 80;
    server_name *.www.king.com;
    root /data/wwwroot/www.king.com;
    index index.html;
}

在这里插入图片描述

Nginx虚拟主机的配置规范

主配置文件include虚拟主机配置文件
在conf目录下创建vhost目录,在vhosts目录下面定义虚拟主机配置

做分配置文件,也方便后续的管理和维护。

Nginx基于端口的虚拟主机

vim   conf/vhost/www.1.com.conf2.conf 
server{
  listen 80;
  server_name www.1.com;
  index index.html;
  root /data/wwwroot/www.1.com_8080;



}

在这里插入图片描述
图显示,如果使用两个相同的端口,就会被忽略一个。存在域名的端口冲突

vim   conf/vhost/www.1.com.conf2.conf 
server{
  listen 8080;
  server_name www.1.com;
  index index.html;
  root /data/wwwroot/www.1.com_8080;

}

在这里插入图片描述

这个基于端口的虚拟主机,使用在什么样的场景下:
做多节点公用,使用不同端口,使用相同的域名

Nginx的Rewrite配置

rewrite规则
格式:rewrite  regex replacement [flag] 

* rewrite配置可以在server、location以及if配置段内生效

* regex是用于匹配URI的正则表达式,其不会匹配到$host(域名)

* replacement是目标跳转的URI,可以以http://或者https://开头,也可以省略掉$host,直接写$request_uri部分(即请求的链接)

* flag,用来设置rewrite对URI的处理行为,其中有break、last、rediect、permanent,其中break和last在前面已经介绍过,
rediect和permanent的区别在于,前者为临时重定向(302),而后者是永久重定向(301),对于用户通过浏览器访问,这两者的效果是一致的。
但是,对于搜索引擎蜘蛛爬虫来说就有区别了,使用301更有利于SEO。所以,建议replacemnet是以http://或者https://开头的flag使用permanent。
示例1
location / {
    rewrite /(.*) http://www.aming.com/$1 permanent;
}
说明:.*为正则表达式,用()括起来,在后面的URI中可以调用它,第一次出现的()用$1调用,第二次出现的()用$2调用,以此类推。
示例2
location / {
    rewrite /.* http://www.aming.com$request_uri permanent;
}
说明:在replacement中,支持变量,这里的$request_uri就是客户端请求的链接
示例3
server{
    listen 80;
    server_name www.123.com;
    root /tmp/123.com;
    index index.html;
    rewrite /(.*) /abc/$1 redirect;
}
说明:本例中的rewrite规则有问题,会造连续循环,最终会失败,解决该问题有两个方案。
关于循环次数,经测试发现,curl 会循环50次,chrome会循环80次,IE会循环120次,firefox会循环20次。
示例4
server{
    listen 80;
    server_name www.123.com;
    root /tmp/123.com;
    index index.html;
    rewrite /(.*) /abc/$1 break;
}
说明:在rewrite中使用break,会避免循环。
示例5
server{
    listen 80;
    server_name www.123.com;
    root /tmp/123.com;
    index index.html;
    if ($request_uri !~ '^/abc/')
    {
        rewrite /(.*) /abc/$1 redirect;
    }
}
说明:加一个条件限制,也可以避免产生循环
实验
server{
  listen 80;
  server_name www.2.com;
  root /data/wwwroot/www.2.com;
  location / {
       rewrite /(.*) /abc/$1 redirect;
  }
}

在这里插入图片描述
在这里插入图片描述
curl -x 127.0.0.1:80 www.2.com/1.html -L -I
-L 是默认跳转50次,想退出跳转,可以添加break

server{
  listen 80;
  server_name www.2.com;
  root /data/wwwroot/www.2.com;
  if ($request_uri !~ "^/abc")
  {
       rewrite /(.*) /abc/$1 redirect;

  }



}

在这里插入图片描述
rewrite 可以写到location if server 里面

前置条件: 依赖PCRE库和模块:ngx_http_rewrite_module

实现原理: 域名跳转(重定向)、URL重写(伪静态)、动静分离(跳转域名,并接入CDN实现加速)
对于小站点可以使用,但是对于大流量,比较鸡肋

错误日志级别变更

#user  nobody;
worker_processes  2;

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

#pid        logs/nginx.pid;


events {
    worker_connections  1024;
}

错误日志级别,变更到notice 只有在notice级别的错误日志,才会被记录 Rwite的错误信息

实验步骤

使用break和last的重写效果

在原有www.1.com 虚拟主机上进行实验

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;
  rewrite /1.html /2.html;
  rewrite /2.html /3.html;
}

需要打开错误日志记录 rewrite_log on
在这里插入图片描述
测试结果,是返回333,是返回3.html的页面

在这里插入图片描述
通过日志信息,是先访问 到1.html 再匹配到2.html 再转发到3.html

如果只想让他rewrite 一次,只需要添加break 就可以停止转发

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;
  rewrite /1.html /2.html break;
  rewrite /2.html /3.html;
}

在这里插入图片描述
在这里插入图片描述
只重写到2.html 就停止转发

使用last 和break 是一样的效果

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;
  rewrite /1.html /2.html last;
  rewrite /2.html /3.html;
  



}

在这里插入图片描述
在这里插入图片描述

使用location 的转发,达到同样的效果
server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;
  location / {
        rewrite /1.html /2.html;
        rewrite /2.html /3.html;
  
  }
  location /2.html { 
        rewrite /2.html /3.html;
  } 

  location /3.html { 
        rewrite /3.html /b.html;
  } 

}

在这里插入图片描述
在这里插入图片描述
疑问:为什么匹配到b还会继续配置1.html 和2.html
这个就是,location的配置规则,所有的都需要匹配到的规则

那如果添加了break 和last 又是一个什么样的效果

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;
  location / {
        rewrite /1.html /2.html break;
        rewrite /2.html /3.html;
  
  }
  location /2.html { 
        rewrite /2.html /3.html;
  } 

  location /3.html { 
        rewrite /3.html /b.html;
  } 

}

在这里插入图片描述
在这里插入图片描述

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;
  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;
  }

}

在这里插入图片描述

在这里插入图片描述

break 与last的区别

break 是退出整个 location last 是退出当前location

nginx的return指令

return 跟rewrite 的配置是差不多

该指令一般用于对请求的客户端直接返回响应状态码。在该作用域内return后面的所有nginx配置都是无效的。
可以使用在server、location以及if配置中。

除了支持跟状态码,还可以跟字符串或者url链接。
直接返回状态码
示例1:
server{
    listen 80;
    server_name www.aming.com;
    return 403;
    rewrite /(.*) /abc/$1;  //该行配置不会被执行。
}

示例2:
server {
.....

if ($request_uri ~ "\.htpasswd|\.bak")
{
    return 404;
    rewrite /(.*) /aaa.txt;  //该行配置不会被执行。
}
//如果下面还有其他配置,会被执行。
.....
}
返回字符串
示例3:
server{
    listen 80;
    server_name www.aming.com;
    return 200 "hello";
}
说明:如果要想返回字符串,必须要加上状态码,否则会报错。
还可以支持json数据

示例4:
location ^~ /aming {
    default_type application/json ;
    return 200  '{"name":"aming","id":"100"}';
}

也支持写一个变量

示例5:
location /test {
    return 200 "$host $request_uri";
}
返回url
示例6:
server{
    listen 80;
    server_name www.aming.com;
    return http://www.aminglinux.com/123.html;
    rewrite /(.*) /abc/$1;  //该行配置不会被执行。
}
注意:return后面的url必须是以http://或者https://开头的。
生产场景实战
背景:网站被黑了,凡是在百度点击到本网站的请求,全部都跳转到了一个赌博网站。
通过nginx解决:
if ($http_referer ~ 'baidu.com') 
{
    return 200 "<html><script>window.location.href='//$host$request_uri';</script></html>";
}

如果写成:
return http://$host$request_uri; 在浏览器中会提示“重定向的次数过多”。
if指令
格式:if (条件判断) { 具体的rewrite规则 }
条件举例
条件判断语句由Nginx内置变量、逻辑判断符号和目标字符串三部分组成。
其中,内置变量是Nginx固定的非自定义的变量,如,$request_method, $request_uri等。
逻辑判断符号,有=, !=, ~, ~*, !~, !~*
!表示相反的意思,~为匹配符号,它右侧为正则表达式,区分大小写,而~*为不区分大小写匹配。
目标字符串可以是正则表达式,通常不用加引号,但表达式中有特殊符号时,比如空格、花括号、分号等,需要用单引号引起来。
示例1
if ($request_method = POST)  //当请求的方法为POST时,直接返回405状态码
{
    return 405; //在该示例中并未用到rewrite规则,if中支持用return指令。
}
示例2
if ($http_user_agent ~ MSIE) //user_agent带有MSIE字符的请求,直接返回403状态码
{
    return 403;
}

如果想同时限制多个user_agent,还可以写成这样

if ($http_user_agent ~ "MSIE|firefox|spider")
{
    return 403;
}
示例3
if(!-f $request_filename)  //当请求的文件不存在,将会执行下面的rewrite规则
{
    rewrite 语句;
}
示例4
if($request_uri ~* 'gid=\d{9,12}/')  //\d表示数字,{9,12}表示数字出现的次数是9到12次,如gid=123456789/就是符合条件的。
{
    rewrite 语句;
}

实验返回状态码

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;

  if ($request_uri ~ "\.htpasswd|\.bak")
     {
        return 405;
         rewrite /(.*) /aaa.txt;  
     }
     # //如果下面还有其他配置,会被执行。

}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实验返回html代码

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;

  if ($request_uri ~ "\.htpasswd|\.bak")
     {
        return 200 "<html><script>window.location.href='//$host$request_uri';</script></html>";
     }
     # //如果下面还有其他配置,会被执行。

}

HTML代码是双引号,是里面引用了变量

在这里插入图片描述

在这里插入图片描述

实验返回链接

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;

  if ($request_uri ~ "\.htpasswd|\.bak")
     {
        return 301  http://www.tangking.com/r.html;
     }
     # //如果下面还有其他配置,会被执行。

}

在这里插入图片描述

如果返回码是200,那就不会跳转,默认是重定向302 要想跳转,就需要302或者301

server{
  listen 80;
  server_name www.1.com;
  root /data/wwwroot/www.1.com;
  rewrite_log on;

  if ($request_uri ~ "\.htpasswd|\.bak")
     {
        return 200  http://www.tangking.com/r.html;
     }
     # //如果下面还有其他配置,会被执行。

}

在这里插入图片描述

Nginx的全局变量

nginx 常用全局变量
变量说明
$args请求中的参数,如www.123.com/1.php?a=1&b=2的$args就是a=1&b=2
$content_lengthHTTP请求信息里的"Content-Length"
$conten_typeHTTP请求信息里的"Content-Type"
$document_rootnginx虚拟主机配置文件中的root参数对应的值
$document_uri当前请求中不包含指令的URI,如www.123.com/1.php?a=1&b=2的$document_uri就是1.php,不包含后面的参数
$host主机头,也就是域名
$http_user_agent客户端的详细信息,也就是浏览器的标识,用curl -A可以指定
$http_cookie客户端的cookie信息
$limit_rate如果nginx服务器使用limit_rate配置了显示网络速率,则会显示,如果没有设置, 则显示0
$remote_addr客户端的公网ip
$remote_port客户端的port
$remote_user如果nginx有配置认证,该变量代表客户端认证的用户名
$request_body_file做反向代理时发给后端服务器的本地资源的名称
$request_method请求资源的方式,GET/PUT/DELETE等
$request_filename当前请求的资源文件的路径名称,相当于是 d o c u m e n t r o o t / document_root/ documentroot/document_uri的组合
$request_uri请求的链接,包括 d o c u m e n t u r i 和 document_uri和 documenturiargs
$scheme请求的协议,如ftp,http,https
$server_protocol客户端请求资源使用的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等
$server_addr服务器IP地址
$server_name服务器的主机名
$server_port服务器的端口号
$uri和$document_uri相同
$http_referer客户端请求时的referer,通俗讲就是该请求是通过哪个链接跳过来的,用curl -e可以指定
实验document_root

在这里插入图片描述

实验 http_user_agent

在这里插入图片描述

实验可以添加多个全局变量
server{
  listen 80;
  server_name www.2.com;
  root /data/wwwroot/www.2.com;
  return 200 "$http_user_agent $request_method";
  access_log /tmp/2.log;

}

Nginx的请求方式 $request_method
在这里插入图片描述

实验 http_referer

主要是记录从那个链接跳进来访问

server{
  listen 80;
  server_name www.2.com;
  root /data/wwwroot/www.2.com;
  return 200 "$http_user_agent $request_method $http_referer ";
  access_log /tmp/2.log;

}

在这里插入图片描述
在这里插入图片描述

Rewrite实战

本部分内容为nginx生产环境中使用的场景示例。
域名跳转(域名重定向)
示例1(不带条件的):
server{
    listen 80;
    server_name www.aminglinux.com;
    rewrite /(.*) http://www.aming.com/$1 permanent;
    .......
    
}

示例2(带条件的):
server{
    listen 80;
    server_name www.aminglinux.com aminglinux.com;
    if ($host != 'www.aminglinux.com')
    {
        rewrite /(.*) http://www.aminglinux.com/$1 permanent;
    }
    .......
    
}

示例3(http跳转到https):
server{
    listen 80;
    server_name www.aminglinux.com;
    rewrite /(.*) https://www.aminglinux.com/$1 permanent;
    .......
    
}
示例4(域名访问二级目录)
server{
    listen 80;
    server_name bbs.aminglinux.com;
    rewrite /(.*) http://www.aminglinux.com/bbs/$1 last;
    .......
    
}
示例5(静态请求分离)
server{
    listen 80;
    server_name www.aminglinux.com;
    location ~* ^.+.(jpg|jpeg|gif|css|png|js)$
    {
        rewrite /(.*) http://img.aminglinux.com/$1 permanent;
    }

    .......
    
}

备注: location ~* ^.+. ~* 是不区分 大小写得匹配, ^ 是以什么开头 .是任意一个字符 +是 .号前面有多个,后面那个. 是.jps css 等这些文件样式
或者:
server{
listen 80;
server_name www.aminglinux.com;
if ( u r i   ∗ ′ j p g ∣ j p e g ∣ g i f ∣ c s s ∣ p n g ∣ j s uri ~* 'jpg|jpeg|gif|css|png|js uri jpgjpeggifcsspngjs’)
{
rewrite /(.*) http://img.aminglinux.com/$1 permanent;
}

    .......
    
}
防盗链
示例6
server{
    listen 80;
    server_name www.aminglinux.com;
    location ~* ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
    {
        valid_referers none blocked server_names *.aminglinux.com aminglinux.com *.aming.com aming.com;
        if ($invalid_referer)
        {
            rewrite /(.*) http://img.aminglinux.com/images/forbidden.png;
        }
    }

    .......
    
}
说明:*这里是通配,跟正则里面的*不是一个意思,none指的是referer不存在的情况(curl -e 测试),
      blocked指的是referer头部的值被防火墙或者代理服务器删除或者伪装的情况,
      该情况下,referer头部的值不以http://或者https://开头(curl -e 后面跟的referer不以http://或者https://开头)。
或者:
    location ~* ^.+.(jpg|jpeg|gif|css|png|js|rar|zip|flv)$
    {
        valid_referers none blocked server_names *.aminglinux.com *.aming.com aminglinux.com aming.com;
        if ($invalid_referer)
        {
            return 403;
        }
    }
伪静态
示例7(discuz伪静态):
location /  {
    rewrite ^([^\.]*)/topic-(.+)\.html$ $1/portal.php?mod=topic&topic=$2 last;
    rewrite ^([^\.]*)/forum-(\w+)-([0-9]+)\.html$ $1/forum.php?mod=forumdisplay&fid=$2&page=$3 last;
    rewrite ^([^\.]*)/thread-([0-9]+)-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=viewthread&tid=$2&extra=page%3D$4&page=$3 last;
    rewrite ^([^\.]*)/group-([0-9]+)-([0-9]+)\.html$ $1/forum.php?mod=group&fid=$2&page=$3 last;
    rewrite ^([^\.]*)/space-(username|uid)-(.+)\.html$ $1/home.php?mod=space&$2=$3 last;
    rewrite ^([^\.]*)/(fid|tid)-([0-9]+)\.html$ $1/index.php?action=$2&value=$3 last;
}
rewrite多个条件的并且
示例8:
location /{
    set $rule 0;
    if ($document_uri !~ '^/abc')
    {
        set $rule "${rule}1";
    }
    if ($http_user_agent ~* 'ie6|firefox')
    {
       set $rule "${rule}2";
    }
    if ($rule = "012")
    {
        rewrite /(.*) /abc/$1 redirect;
    }
}

Nginx的location配置

安装第三方模块echo-nginx-module

下载 https://github.com/openresty/echo-nginx-module/tags

安装步骤:
1、先清理之前的,这个必须在编译前的目录进行清理
例如:你的Nginx的二进制包是放在/root/下
cd /root/nginx-1.2.1, 接着执行,而不是在你的安装后的目录清新清理

make clean
./configure --prefix=/usr/local/nginx --add-module=/root/echo-nginx-module-0.63
make && make install
重启Nginx
./sbin/nginx
./sbin/nginx -V 查找魔力是否安装成功

location的使用

location 结合echo 模块的使用

访问一个指定的域名下的一个指定的区域,就会访问一个不关重要的数据
生产环境一般很少用这个

server{
  listen 80;
  server_name www.2.com;
  root /data/wwwroot/www.2.com;
  access_log /tmp/2.log;
  location /abc
    {
    echo 123;
    }

}

测试:
在这里插入图片描述

location的语法格式

nginx的location配置
nginx location语法规则:location [=|~|~*|^~] /uri/ { … }
nginx的location匹配的变量是$uri
符号说明
=表示精确匹配
^~表示uri以指定字符或字符串开头
~表示区分大小写的正则匹配
~*表示不区分大小写的正则匹配
/通用匹配,任何请求都会匹配到
规则优先级
=  高于  ^~  高于  ~* 等于 ~  高于  /
规则示例
location = "/12.jpg" { ... }
如:
www.aminglinux.com/12.jpg 匹配
www.aminglinux.com/abc/12.jpg 不匹配

location ^~ "/abc/" { ... }
如:
www.aminglinux.com/abc/123.html 匹配
www.aminglinux.com/a/abc/123.jpg 不匹配

location ~ "png" { ... }
如:
www.aminglinux.com/aaa/bbb/ccc/123.png 匹配
www.aminglinux.com/aaa/png/123.html 匹配

location ~* "png" { ... }
如:
www.aminglinux.com/aaa/bbb/ccc/123.PNG 匹配
www.aminglinux.com/aaa/png/123.html 匹配


location /admin/ { ... }
如:
www.aminglinux.com/admin/aaa/1.php 匹配
www.aminglinux.com/123/admin/1.php 不匹配
小常识
有些资料上介绍location支持不匹配 !~,
如: location !~ 'png'{ ... }
这是错误的,location不支持 !~

如果有这样的需求,可以通过if来实现,
如: if ($uri !~ 'png') { ... }

注意:location优先级小于if

Nginx 负载均衡原理与实践

负载均衡的原理及处理流程

负载均衡一般有两种方式:
系统的扩展可以分为纵向扩展和横向扩展
纵向扩展是从单机的角度出发,通过增加系统的硬件处理能力来提升服务器的处理能力;横向扩展是通过添加机器来满足大型网站服务的处理能力。

Nginx 七层负载均衡

Nginx要实现七层负载均衡需要用到proxy_pass代理模块配置。Nginx默认安装支持这个模块,我们不需要再做任何处理。Nginx的负载均衡是在Nginx的反向代理基础上把用户的请求根据指定的算法分发到一组【upstream虚拟服务池】

upstream指令

upstream:该指令是用来定义一组服务器,它们可以使监听不同端口的服务器,并且也可以是同时监听TCP和Unix socket的服务器。服务器可以指定不同的权重,默认为1。更多关于企业集群运维管理系列的学习文章,请参阅:玩转企业集群运维管理专栏,本系列持续更新中。

语法 upstream name{...}
默认值 ——
位置 http

server指令

server:该指令用来指定后端服务器的名称和一些参数,可以使用域名、IP、端口或者unix socket。

语法 server name [parameters];
默认值 ——
位置 upstream

Nginx负载均衡配置

#服务器1
server {
 listen 9001;
 server_name localhost;
 default_type text/html;
 
 location / {
  return 200 '<h1>server:9001</h1>';
 }
}
#服务器2
 server {
  listen 9002;
  server_name localhost;
  default_type text/html;
  
  location / {
   return 200 '<h1>server:9002</h1>';
  }
 }
#服务器3
server {
 listen 9003;
 server_name localhost;
 default_type text/html;
 
 location / {
  return 200 '<h1>server:9003</h1>';
 }
}

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

Nginx负载均衡状态

代理服务器在负责均衡调度中的状态有以下几个

  • down #当前的server暂时不参与负载均衡
  • backup #预留的备份服务器
  • max_fails #允许请求失败的次数
  • fail_timeout #经过max_fails次失败后,服务暂停的时间
  • max_conns #限制最大的接收连接数
状态down

down:将该服务器标记为永久不可用,那么该代理服务器将不参与负载均衡。

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001 down;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}
状态backup

backup:将该服务器标记为备份服务器,当主服务器不可用时,将用来传递请求。

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001 down;
    # 9002 作为 9003 的备份服务器
 server localhost:9002 backup;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

此时需要将9003端口的访问禁止掉来模拟当唯一能对外提供访问的服务宕机以后,backup的备份服务器就要开始对外提供服务。此时为了测试验证,我们需要使用防火墙进行拦截。

介绍一个工具fire-wall-cmd,该工具是Linux提供的专门用来操作firewall的。

#查询防火墙中指定的端口是否开放
firewall-cmd --query-port=9001/tcp
 
#开放一个指定的端口
firewwall-cmd --permanent --add-port=9002/tcp
 
#批量添加开发端口
firewall-cmd --permanent --add-port=9001-9003/tcp
 
#移除一个指定的端口
firewall-cmd --permanent --remove-port=9003/tcp
 
#重新加载
firewall-cmd --reload
状态:max_fails

max_fails=numer:设置允许请求代理服务器失败的次数,默认为1。

状态:fail_timeout

fail_timeout=time:设置经过max_fail次失败后,服务暂停的时间,默认是10秒。

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001 down;
    # 9002 作为 9003 的备份服务器
 server localhost:9002 backup;
 server localhost:9003 max_fails=3 fail_timeout=15;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}
状态:max_conns

max_conns=number:用来设置代理服务器同时活动链接的最大数量,默认为0,表示不限制,使用该配置可以根据后端服务器处理请求的并发量来进行设置,防止后端服务器被压垮。

Nginx负载均衡策略

介绍完Nginx负载均衡的相关指令后,我们已经能实现将用户的请求分发到不同的服务器上,那么除了采用默认的分配方式外,我们还能采用什么样的负载算法?

Nginx的upstream支持如下六种方式的分配算法,分别是:

算法名称说明
轮询默认方式
weight权重方式
ip_hase根据IP进行分配
leas_conn依据最少连接方式
URL_hase依据URL分配方式
fair依据响应时间
轮询

轮询是upstream模块负载均衡默认的策略,每个请求会按时间顺序逐个被分配到不同的后端服务器。轮询不需要额外的配置。

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}
weight加权(加权轮询)

weight=number:用来设置服务器的权重,默认为1,权重数字越大,被分配到请求的几率越大。该权重值主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的,所有此策略比较适合服务器的硬件配置差别比较大的情况。

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001 weight=10;
 server localhost:9002 weight=5;
 server localhost:9003 weight=3;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}
ip_hash

当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某一个IP的用户在后端Web服务器A上登录后,再访问该站点的其他URL,能保证其访问的还是后端web服务器A。

语法 ip_hash;
默认值 ——
位置 upstream
#代理服务器
#设置服务器组
upstream backend {
    ip_hash;
 server localhost:9001;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

注意:使用ip_hash指令无法保证后端服务器的负载均衡,可能导致有些后端服务器接收到的请求多,有些后端服务器接受的请求少,而且设置后端服务器权重等方法将不起作用。

least_conn

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

# 代理服务器
# 设置服务器组
upstream backend {
    least_conn;
 server localhost:9001;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

此负载均衡适合请求处理时间长短不一造成服务器过载的情况。更多关于企业集群运维管理系列的学习文章,请参阅:玩转企业集群运维管理专栏,本系列持续更新中。

url_hash

按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,要配合缓存命中来使用。同一个资源多次请求,可能会到达不同的服务器上,导致不必要的多次下载,缓存命中率不高,以及一些资源时间的浪费。而使用url_hash,可以使得同一个url(也就是同一个资源请求)会到达同一台服务器,一旦缓存住了资源,再次收到请求,就可以从缓存中读取。

# 代理服务器
# 设置服务器组
upstream backend {
    hash $request_uri;
 server localhost:9001;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}
fair

fair采用的不是内建负载均衡使用的均衡算法,而是可以根据页面大小、加载时间长短智能地进行负载均衡。那么如何使用第三方模块的fair负载均衡策略?

# 代理服务器
# 设置服务器组
upstream backend {
    fair;
 server localhost:9001;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

但是如果直接使用会报错,因为fair属于第三方模块实现的负载均衡。需要添加nginx-upstream-fair,如何添加对应的模块,下载nginx-upstream-fair模块。

下载地址:https://github.com/gnosek/nginx-upstream-fair

#将下载的文件上传到服务器并进行解压缩。
unzip nginx-upstream-fair-master.zip
#重命名资源。
mv nginx-upstream-fair-master fair
#使用./configure命令将资源添加到Nginx模块中。
./configure --add-module=/root/fair
#编译。
make
 
#编译可能会出现如下错误:
nginx_http_upstream_srv_conf_t结构中缺少default_port
#解决方案:在Nginx的源码中src/http/nginx_http_upstream.h,找到ngx_http_upstream_srv_conf_s,在模块中添加default_port属性:
in_port_t default_port
然后再进行make。

更新Nginx

#将sbin目录下的nginx进行备份
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginxold
 
#将安装目录下的objs中的nginx拷贝到sbin目录
cd objs
cp nginx /usr/local/nginx/sbin
 
#更新
cd ../
make upgrade
编译测试使用Nginx。

Nginx七层负载均衡的案例

案例1:——对所有请求实现一般轮询规则的负载均衡

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001;
 server localhost:9002;
 server localhost:9003;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

案例2: ——对所有请求实现加权轮询规则的负载均衡

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001 weight=7;
 server localhost:9002 weight=5;
 server localhost:9003 weight=3;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

案例3:——对特定资源实现负载均衡

#代理服务器
#设置服务器组
upstream backend {
 server localhost:9001 weight=7;
 server localhost:9002 weight=5;
 server localhost:9003 weight=3;
}
server {
 listen 8080;
 server_name localhost;
 
 location / {
  # backend 就是服务器组的名称
  proxy_pass http://backend/;
 }
}

案例3:——对特定资源实现负载均衡

#代理服务器
#设置服务器组
upstream videobackend {
 server localhost:9001;
 server localhost:9002;
}
upstream filebackend {
 server localhost:9003;
 server localhost:9004;
}
server {
 listen 8080;
 server_name localhost;
 
 location /video/ {
  # backend 就是服务器组的名称
  proxy_pass http://videobackend;
 }
 location /file/ {
  proxy_pass http://filebackend;
 }
}

案例4:——对不同域名实现负载均衡

#代理服务器
#设置服务器组
upstream aaabackend {
 server 192.168.200.146:9001;
 server 192.168.200.146:9002;
}
upstream bbbbackend {
 server 192.168.200.146:9003;
 server 192.168.200.146:9004;
}
server {
 listen 8080;
 server_name www.aaa.com;
 location / {
  proxy_pass http://aaabackend;
 }
}
server {
 listen 8081;
 server_name www.bbb.com;
 location / {
  proxy_pass http://bbbbackend;
 }
}

案例5:——实现带有URL重写的负载均衡

#代理服务器
#设置服务器组
upstream backend {
 server 192.168.200.146:9001;
 server 192.168.200.146:9002;
}
server {
 listen 8080;
 server_name localhost;
 
 # URL重写
 location /file/ {
  rewrite ^(/file/.*) /server/$1 last;
 }
 
 location /server {
  proxy_pass http:backend;
 }
}

Nginx四层负载均衡

Nginx在1.9之后,增加了一个stream模块,用来实现四层协议的转发、代理、负载均衡等。stream模块的用法跟http的用法类似,允许我们配置一组TCP或者UDP等协议的监听,然后通过proxy_pass来转发我们的请求,通过upstream添加多个后端服务,实现负载均衡。

四层协议负载均衡的实现,一般都会用到LVS、HAProxy、F5等,要么很贵要么配置很麻烦,而Nginx的配置相对来说更简单,更能快速完成工作。

添加stream模块的支持

Nginx默认是没有编译这个模块的,需要使用到stream模块,那么需要在编译的时候加上–with-stream。

完成添加–with-stream的实现步骤:

将原有/usr/local/nginx/sbin/nginx进行备份;
拷贝nginx之前的配置信息;
在nginx的安装源码进行配置指定对应模块 ./configure --with-stream
通过make模板进行编译;
将objs下面的nginx移动到/usr/local/nginx/sbin下;
在源码目录下执行 make upgrade 进行升级,这个可以实现不停机添加新模块的功能

Nginx四层负载均衡的指令

stream指令
stream:该指令提供在其中指定流服务器的配置文件上下文。和http指令同级。

语法 stream {...}
默认值 ——
位置 main
upstream指令
upstream:该指令和http的upstream指令是类似的。

Nginx四层负载均衡的案例

实验背景: 一台Nginx服务分发到3台redis和1台Tomcat下

实现步骤:准备Redis服务器,在一台服务器(192.168.200.146)上准备三个Redis,端口分别是9379,9378,9377;

#上传redis的安装包
redis-4.0.14.tar.gz

#将安装包进行解压缩
tar -zxf -redis-4.0.14.tar.gz

#进入redis的安装包
cd redis-4.0.14

#使用make和install进行编译和安装
make PREFIX=/usr/local/redis/redis01 install

#拷贝redis配置文件redis.conf到/usr/local/redis/redis01/bin目录中
cp redis.conf /usr/local/redis/redis01/bin

#修改redis.conf配置文件
port 9379; # redis 的端口
deamonize yes; # 后台启动redis

#将redis01复制两份为redis02,redis03
cp -r -redis01/ redis02
  
#修改redis02,redis03的配置redis.conf配置文件   
port 9378; # redis 的端口
deamonize yes; # 后台启动redis

port 9377; # redis 的端口
deamonize yes; # 后台启动redis

#修改3个redis的redis.conf中如下内容:
bind 127.0.0.1 ==> bind 0.0.0.0
 
#分别启动,即可获取3个redis,并查看
ps -ef | grep redis
使用Nginx将请求分发到不同的Redis服务器上。
  • 准备Tomcat
#上传tomcat的安装包,apache-tomcat-8.5.56.tar.gz
 
#将安装包进行解压缩
tar -zxf apache-tomcat-8.5.56.tar.gz
 
#进入tomcat的bin目录
cd apache-tomcat-8.5.56/bin
./startup
# 配置nginx四层负载均衡相关内容
stream {
# redis 服务器群组
upstream redisbackend {
 server 192.168.200.146:9379;
 server 192.168.200.146:9378;
 server 192.168.200.146:9377;
}
# 监听并转发至redis服务器组
server {
 listen 81;
 # server_name 指令在该块不能使用
 # redisbackend 为服务群组的名称
 proxy_pass redisbackend;
}

Nginx 七层与四层反向代理

反向代理和正向代理概述

1.代理服务器如果配置在客户端即为正向代理,如果配置在服务端即为反向代理,和机器个数没有关系。
2.正向代理代替客户端去发送请求,反向代理代替服务端接受请求。
3.正是因为正向代理代替客户端发送请求,正向代理服务器和客户端对外表现为一个客户端,所以正向代理隐藏了真实的客户端;反向代理代替服务端接受请求,反向代理服务器和真实服务器对外表现为一个服务端,所以反向代理服务器隐藏真实的服务端。
综上,本质上代理服务器还是那个代理服务器,如果替客户端干活就是正向代理,如果替服务端干活就是反向代理。更多关于企业集群运维管理系列的学习文章,请参阅:玩转企业集群运维管理专栏,本系列持续更新中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

运维螺丝钉

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值