nginx-nginx和反向代理概念

1.nginx-nginx和反向代理概念

1.1 代理概念

代理(英语:Proxy),也称网络代理,是一种特殊的网络服务,允许一个网络终端(一般为客户端)通过这个服务与另一个网络终端(一般为服务器)进行非直接的连接。一些网关、路由器等网络设备具备网络代理功能。一般认为代理服务有利于保障网络终端的隐私或安全,防止攻击。

提供代理服务的电脑系统或其它类型的网络终端称为代理服务器(英文:Proxy Server)。一个完整的代理请求过程为:客户端首先与代理服务器创建连接,接着根据代理服务器所使用的代理协议,请求对目标服务器创建连接、或者获得目标服务器的指定资源(如:文件)。

代理服务器英文全称是(Proxy Server),其功能就是代理网络用户去取得网络信息。形象的说:它是网络信息的中转站。代理服务器就好象一个大的Cache,这样就能显著提高浏览速度和效率。

1.2 正向代理和反向代理

在计算机网络中,反向代理是代理服务器的一种。服务器根据客户端的请求,从其关联的一组或多组后端服务器(如Web服务器,tomcat)上获取资源,然后再将这些资源返回给客户端,客户端只会得知反向代理的IP地址,而不知道在代理服务器后面的服务器簇的存在

与前向代理不同,前向代理作为客户端的代理,将从互联网上获取的资源返回给一个或多个的客户端,服务端(如Web服务器)只知道代理的IP地址而不知道客户端的IP地址;而反向代理是作为服务器端(如Web服务器)的代理使用,而不是客户端。客户端借由前向代理可以间接访问很多不同互联网服务器(簇)的资源,而反向代理是供很多客户端都通过它间接访问不同后端服务器上的资源,而不需要知道这些后端服务器的存在,而以为所有资源都来自于这个反向代理服务器。

1560145770349

1560145911948

1.3 nginx介绍

Nginx (“engine x”) 是一个高性能的 HTTP反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器。

第一个公开版本0.1.0发布于2004年10月4日

其将源代码以类BSD许可证的形式发布,因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名

官方测试nginx能够支撑5万并发链接,并且cpu、内存等资源消耗却非常低,运行非常稳定

2011年6月1日,nginx 1.0.4发布。
apache httpd

Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。由俄罗斯的程序设计师Igor Sysoev所开发,

其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:新浪、网易、腾讯等。

功能:

  • web服务器
  • web reverse proxy
  • smtp reverse proxy

Nginx和apache httpd的优缺点

  1. nginx相对于apache的优点:

    轻量级,同样起web 服务,比apache 占用更少的内存及资源

    抗并发,nginx 处理请求是异步非阻塞的,而apache 则是阻塞型的,在高并发下nginx 能保持低资源低消耗高性能

    高度模块化的设计,编写模块相对简单

    社区活跃,各种高性能模块出品迅速

  2. apache 相对于nginx 的优点:

    rewrite ,比nginx 的rewrite 强大

    模块超多,基本想到的都可以找到

    少bug ,nginx 的bug 相对较多

  3. Nginx 配置简洁, Apache 复杂

  4. 最核心的区别在于apache是同步多进程模型,一个连接对应一个进程;nginx是异步的,多个连接(万级别)可以对应一个进程

1.4 Nginx和Tengine

Tengine 是nginx的加强版,封装版,淘宝开源

官网http://tengine.taobao.org/

动态模块加载(DSO支持。加入一个模块不再需要重新编译整个Tengine;

支持SO_REUSEPORT选项,建连性能提升为官方nginx的三倍;

–支持SPDY v3协议,自动检测同一端口的SPDY请求和HTTP请求;

流式上传到HTTP后端服务器或FastCGI服务器,大量减少机器的I/O压力;

–更加强大的负载均衡能力,包括一致性hash模块会话保持模块还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线,以及动态解析upstream中出现的域名

输入过滤器机制支持。通过使用这种机制Web应用防火墙的编写更为方便;

–支持设置proxy、memcached、fastcgi、scgi、uwsgi在后端失败时的重试次数

动态脚本语言Lua支持。扩展功能非常高效简单;

支持管道(pipe)和syslog(本地和远端)形式的日志以及日志抽样

–支持按指定关键字(域名,url等)收集Tengine运行状态

组合多个CSSJavaScript文件的访问请求变成一个请求

自动去除空白字符和注释从而减小页面的体积

–…….

2.nginx安装配置

安装之前准备

  1. 依赖 gcc openssl-devel pcre-devel zlib-devel
    • 安装:yum install gcc openssl-devel pcre-devel zlib-devel
  2. 创建用户和用户组。为了方便nginx运行而不影响linux安全
    • 创建组:groupadd -r nginx
    • 创建用户:useradd -r -g nginx -M nginx
      • -M 表示不创建用户的家目录。

安装nginx

./configure \

–prefix=/usr/tengine-2.1

make && make install

1559719120924

    • 第一步: ./configure –prefix=/opt/sxt/nginx 设置安装路径

      • Error1:没有C语言编译器:yum install gcc

      • Error2:没有PCRE:yum search pcre 用仓库搜索是否有对应的安装包

        yum install pcre-devel (自动匹配安装那个版本)

      • Error3:没有openssl:yum install openssl-devel

      以上操作完成后再次执行安装操作(./configure –prefix=/opt/sxt/nginx),安装成功后tengine-2.1.0中就自动生成Makefile文件。

      [root@node01 tengine-2.1.0]# ./configure
      checking for OS
       + Linux 2.6.32-642.el6.x86_64 x86_64
      checking for C compiler ... not found
      
      ./configure: error: C compiler cc is not found
      
      [root@node01 tengine-2.1.0]# yum install -y gcc
      
      [root@node01 tengine-2.1.0]# ./configure
      checking for OS
       + Linux 2.6.32-642.el6.x86_64 x86_64
      checking for C compiler ... found
       + using GNU C compiler
       + gcc version: 4.4.7 20120313 (Red Hat 4.4.7-17) (GCC) 
      checking for gcc -pipe switch ... found
      .............
      ./configure: error: the HTTP rewrite module requires the PCRE library.
      You can either disable the module by using --without-http_rewrite_module
      option, or install the PCRE library into the system, or build the PCRE library
      statically from the source with nginx by using --with-pcre=<path> option.
      
      [root@node01 tengine-2.1.0]# yum search PCRE
      已加载插件:fastestmirror
      Loading mirror speeds from cached hostfile
      ================================================================ N/S Matched: PCRE =================================================================
      pcre-devel.i686 : Development files for pcre
      pcre-devel.x86_64 : Development files for pcre
      pcre-static.x86_64 : Static library for pcre
      pcre.i686 : Perl-compatible regular expression library
      pcre.x86_64 : Perl-compatible regular expression library
      
        Name and summary matches only, use "search all" for everything.
      
      [root@node01 tengine-2.1.0]# yum install pcre-devel
      ............
      
      [root@node01 tengine-2.1.0]# ./configure
      .......
      ./configure: error: SSL modules require the OpenSSL library.
      You can either do not enable the modules, or install the OpenSSL library
      into the system, or build the OpenSSL library statically from the source
      with nginx by using --with-openssl=<path> option.
      
      [root@node01 tengine-2.1.0]# yum search openssl
      已加载插件:fastestmirror
      Loading mirror speeds from cached hostfile
      =============================================================== N/S Matched: openssl ===============================================================
      openssl-devel.i686 : Files for development of applications which will use OpenSSL
      openssl-devel.x86_64 : Files for development of applications which will use OpenSSL
      
      [root@node01 tengine-2.1.0]# yum install openssl-devel
      
      
    • 第二步,执行make命令,在源码的目录下。

      [root@node01 tengine-2.1.0]# make
      
    • 第三步,执行make install 命令

      [root@node01 tengine-2.1.0]# make install
      
  1. 安装完成后可以进入安装路径查看是是否存在可执行程序ngix

    [root@node01 tengine-2.1.0]# cd /usr/local/nginx/sbin
    [root@node01 sbin]# ls
    dso_tool  nginx
    
  2. 启动web server: ./nginx

    [root@node01 sbin]# ./nginx
    
  3. 浏览器访问对应IP,验证是否可以查看登录页面。端口号:80

    注意:此时应该将linux的防火墙关闭,否则无法在浏览器进行访问

    [root@node01 ~]# service iptables stop
    

    显示以下界面即安装成功

1559721096883

配置Nginx为系统服务,以方便管理

  1. 在/etc/rc.d/init.d/目录中建立文本文件nginx

  2. 在文件中粘贴下面的内容:

    #!/bin/sh
    #
    # nginx - this script starts and stops the nginx daemon
    #
    # chkconfig:   - 85 15 
    # description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
    #               proxy and IMAP/POP3 proxy server
    # processname: nginx
    # config:      /etc/nginx/nginx.conf
    # config:      /etc/sysconfig/nginx
    # pidfile:     /var/run/nginx.pid
     
    # Source function library.
    . /etc/rc.d/init.d/functions
     
    # Source networking configuration.
    . /etc/sysconfig/network
     
    # Check that networking is up.
    [ "$NETWORKING" = "no" ] && exit 0
    
    #修改为nginx实际安装的目录下的sbin/nginx 按默认安装的话一般为/usr/local/nginx/sbin/nginx
    nginx="/usr/sbin/nginx"     
    prog=$(basename $nginx)
    
    #修改为安装目录下的conf/nginx.conf 默认地址安装即为 /usr/local/nginx/conf/nginx.conf
    NGINX_CONF_FILE="/etc/nginx/nginx.conf"
     
    [ -f /etc/sysconfig/nginx ] && . /etc/sysconfig/nginx
     
    lockfile=/var/lock/subsys/nginx
     
    make_dirs() {
       # make required directories
       user=`nginx -V 2>&1 | grep "configure arguments:" | sed 's/[^*]*--user=\([^ ]*\).*/\1/g' -`
       options=`$nginx -V 2>&1 | grep 'configure arguments:'`
       for opt in $options; do
           if [ `echo $opt | grep '.*-temp-path'` ]; then
               value=`echo $opt | cut -d "=" -f 2`
               if [ ! -d "$value" ]; then
                   # echo "creating" $value
                   mkdir -p $value && chown -R $user $value
               fi
           fi
       done
    }
     
    start() {
        [ -x $nginx ] || exit 5
        [ -f $NGINX_CONF_FILE ] || exit 6
        make_dirs
        echo -n $"Starting $prog: "
        daemon $nginx -c $NGINX_CONF_FILE
        retval=$?
        echo
        [ $retval -eq 0 ] && touch $lockfile
        return $retval
    }
     
    stop() {
        echo -n $"Stopping $prog: "
        killproc $prog -QUIT
        retval=$?
        echo
        [ $retval -eq 0 ] && rm -f $lockfile
        return $retval
    }
     
    restart() {
        configtest || return $?
        stop
        sleep 1
        start
    }
     
    reload() {
        configtest || return $?
        echo -n $"Reloading $prog: "
        killproc $nginx -HUP
        RETVAL=$?
        echo
    }
     
    force_reload() {
        restart
    }
     
    configtest() {
      $nginx -t -c $NGINX_CONF_FILE
    }
     
    rh_status() {
        status $prog
    }
     
    rh_status_q() {
        rh_status >/dev/null 2>&1
    }
     
    case "$1" in
        start)
            rh_status_q && exit 0
            $1
            ;;
        stop)
            rh_status_q || exit 0
            $1
            ;;
        restart|configtest)
            $1
            ;;
        reload)
            rh_status_q || exit 7
            $1
            ;;
        force-reload)
            force_reload
            ;;
        status)
            rh_status
            ;;
        condrestart|try-restart)
            rh_status_q || exit 0
                ;;
        *)
            echo $"Usage: $0 {start|stop|status|restart|condrestart|try-restart|reload|force-reload|configtest}"
            exit 2
    esac
    
  3. 修改nginx文件的执行权限

    chmod +x nginx

  4. 添加该文件到系统服务中去

    chkconfig --add nginx

    查看是否添加成功

    chkconfig --list nginx

  5. 启动,停止,重新装载
    service nginx start|stop|reload

注意:修改路径,而且必须是在/etc/init.d、下面touch或者vi来新建

3.Nginx配置解析与location

3.1 Nginx配置解析

工作模式与连接数上限

events
{
#参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
use epoll;
#单个进程最大连接数(最大连接数=连接数*进程数)
worker_connections 65535;
}

event下的一些配置及其意义

#单个后台worker process进程的最大并发链接数    
worker_connections  1024;

    # 并发总数是 worker_processes 和 worker_connections 的乘积
    # 即 max_clients = worker_processes * worker_connections
    # 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4  为什么
    # 为什么上面反向代理要除以4,应该说是一个经验值
    # 根据以上条件,正常情况下的Nginx Server可以应付的最大连接数为:4 * 8000 = 32000
    # worker_connections 值的设置跟物理内存大小有关
    # 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数
	# 而系统可以打开的最大文件数和内存大小成正比,一般1GB内存的机器上可以打开的文件数大约是10万左右
    # 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
    # $ cat /proc/sys/fs/file-max
    # 输出 34336
    # 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内
    # 所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
    # 使得并发总数小于操作系统可以打开的最大文件数目
    # 其实质也就是根据主机的物理CPU和内存进行配置
    # 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
    # ulimit -SHn 65535


nginx.conf配置文件

#定义Nginx运行的用户和用户组
user www www;

#nginx进程数,建议设置为等于CPU总核心数。
worker_processes 8;

#全局错误日志定义类型,[ debug | info | notice | warn | error | crit ]
error_log /var/log/nginx/error.log info;

#进程文件
pid /var/run/nginx.pid;

#一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀,所以建议与ulimit -n的值保持一致。
worker_rlimit_nofile 65535;


http下的一些配置及其意义

#设定http服务器
http
{
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型
#charset utf-8; #默认编码
server_names_hash_bucket_size 128; #服务器名字的hash表大小
client_header_buffer_size 32k; #上传文件大小限制
large_client_header_buffers 4 64k; #设定请求缓
client_max_body_size 8m; #设定请求缓
sendfile on; #开启高效文件传输模式,sendfile指令指定nginx是否调用sendfile函数来输出文件,对于普通应用设为 on,如果用来进行下载等应用磁盘IO重负载应用,可设置为off,以平衡磁盘与网络I/O处理速度,降低系统的负载。注意:如果图片显示不正常把这个改成off。
autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on; #防止网络阻塞
tcp_nodelay on; #防止网络阻塞
keepalive_timeout 120; #长连接超时时间,单位是秒


gzip的一些配置及其意义

#gzip模块设置
gzip on; #开启gzip压缩输出
gzip_min_length 1k; #最小压缩文件大小
gzip_buffers 4 16k; #压缩缓冲区
gzip_http_version 1.0; #压缩版本(默认1.1,前端如果是squid2.5请使用1.0)
gzip_comp_level 2; #压缩等级
gzip_types text/plain application/x-javascript text/css application/xml;
#压缩类型,默认就已经包含text/html,所以下面就不用再写了,写上去也不会有问题,但是会有一个warn。
gzip_vary on;
#limit_zone crawler $binary_remote_addr 10m; #开启限制IP连接数的时候需要使用


虚拟主机一些配置及其意义

#虚拟主机的配置
server
{
#监听端口
listen 80;
#域名可以有多个,用空格隔开
server_name www.ha97.com ha97.com;
index index.html index.htm index.jsp;
root /data/www/ha97;
location ~ .*\.(php|php5)?$
{
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.jsp;
include fastcgi.conf;
}


文件代码

#运行用户
user nobody;
#启动进程,通常设置成和cpu(核心)的数量相等
worker_processes  1;

#全局错误日志及PID文件
#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/nginx.pid;

#工作模式及连接数上限
events {
    #epoll是多路复用IO(I/O Multiplexing)中的一种方式,
    #仅用于linux2.6以上内核,可以大大提高nginx的性能
    #参考事件模型,use [ kqueue | rtsig | epoll | /dev/poll | select | poll ]; epoll模型是Linux 2.6以上版本内核中的高性能网络I/O模型,如果跑在FreeBSD上面,就用kqueue模型。
    use   epoll; 

    #单个后台worker process进程的最大并发链接数    
    #单个进程最大连接数(最大连接数=连接数*进程数)
    worker_connections  1024;

    # 并发总数是 worker_processes 和 worker_connections 的乘积
    # 即 max_clients = worker_processes * worker_connections
    # 在设置了反向代理的情况下,max_clients = worker_processes * worker_connections / 4  为什么
    # 为什么上面反向代理要除以4,应该说是一个经验值
    # 根据以上条件,正常情况下的Nginx Server可以应付的最大连接数为:4 * 8000 = 32000
    # worker_connections 值的设置跟物理内存大小有关
    # 因为并发受IO约束,max_clients的值须小于系统可以打开的最大文件数
    # 而系统可以打开的最大文件数和内存大小成正比,一般1GB内存的机器上可以打开的文件数大约是10万左右
    # 我们来看看360M内存的VPS可以打开的文件句柄数是多少:
    # $ cat /proc/sys/fs/file-max
    # 输出 34336
    # 32000 < 34336,即并发连接总数小于系统可以打开的文件句柄总数,这样就在操作系统可以承受的范围之内
    # 所以,worker_connections 的值需根据 worker_processes 进程数目和系统可以打开的最大文件总数进行适当地进行设置
    # 使得并发总数小于操作系统可以打开的最大文件数目
    # 其实质也就是根据主机的物理CPU和内存进行配置
    # 当然,理论上的并发总数可能会和实际有所偏差,因为主机还有其他的工作进程需要消耗系统资源。
    # ulimit -SHn 65535

}


http {
    #设定mime类型,类型由mime.type文件定义
    include    mime.types;
    default_type  application/octet-stream;
    #设定日志格式
    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;

    #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,
    #对于普通应用,必须设为 on,
    #如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,
    #以平衡磁盘与网络I/O处理速度,降低系统的uptime.
    sendfile     on;
    #tcp_nopush     on;

    #连接超时时间
    #keepalive_timeout  0;
    keepalive_timeout  65;
    tcp_nodelay     on;

    #开启gzip压缩
    gzip  on;
    gzip_disable "MSIE [1-6].";

    #设定请求缓冲
    client_header_buffer_size    128k;
    large_client_header_buffers  4 128k;


    #设定虚拟主机配置
    server {
        #侦听80端口
        listen    80;
        #定义使用 www.nginx.cn访问
        server_name  www.nginx.cn;

        #定义服务器的默认网站根目录位置
        root html;

        #设定本虚拟主机的访问日志
        access_log  logs/nginx.access.log  main;

        #默认请求
        location / {
            
            #定义首页索引文件的名称
            index index.php index.html index.htm;   

        }

        # 定义错误提示页面
        error_page   500 502 503 504 /50x.html;
        location = /50x.html {
        }

        #静态文件,nginx自己处理
        location ~ ^/(images|javascript|js|css|flash|media|static)/ {
            
            #过期30天,静态文件不怎么更新,过期可以设大一点,
            #如果频繁更新,则可以设置得小一点。
            expires 30d;
        }

        #PHP 脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
        location ~ .php$ {
            fastcgi_pass 127.0.0.1:9000;
            fastcgi_index index.php;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include fastcgi_params;
        }

        #禁止访问 .htxxx 文件
            location ~ /.ht {
            deny all;
        }

    }
}

3.2 虚拟主机

nginx 收到请求头:判定ip,port,hosts决定server

什么是虚拟主机

虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供www服务,这样就可以实现一台主机对外提供多个web服务,每个虚拟主机之间是独立的,互不影响的

1560154207849

通过nginx可以实现虚拟主机的配置,nginx支持三种类型的虚拟主机配置,

  1. 基于ip的虚拟主机, (一块主机绑定多个ip地址)
  2. 基于域名的虚拟主机(servername)
  3. 基于端口的虚拟主机(listen如果不写ip端口模式)

示例基于虚拟机ip的配置,这里需要配置多个ip

server
{
    listen 192.168.20.20:80;
    server_name www.linuxidc.com;
    root /data/www;
}
server
{
    listen 192.168.20.21:80;
    server_name www.linuxidc.com;
    root /data/www;
}


nginx.conf下的配置

http{
server{
	#表示一个虚拟主机
}
}

3.3 location

nginx 收到请求头:判定ip,port,hosts决定server

nginx location匹配:用客户端的uri匹配location的uri

  • 先普通
    • 顺序无关
    • 最大前缀
    • 匹配规则简单
    • 打断:
      ^~
      完全匹配
  • 再正则
    • 不完全匹配
    • 正则特殊性:一条URI可以和多条location匹配上
    • 有顺序的
    • 先匹配,先应用,即时退出匹配

location配置文件介绍

location / {//定位,把特殊的路径或文件再次定位
       root html;  #根目录定位,可以使用相对路径,此处所说的根目录为/usr/local/nginx目录(也就是安装目录),html也是相对于/usr/local/nginx目录,也可使用绝对路径定位,比如你的项目在/var/www/html/目录下,那你就可以改为root /var/www/html/
            index  index.html index.htm;  #相当于默认页面
        }


location语法

语法

location [=|~|~*|^~] patt { }  
location [ = | ~ | ~* | ^~ ] uri { ... }
//中括号中为修饰符,可以不写任何参数,此时称为一般匹配,也可以写参数

因此,大类型可以分为三种:

location = patt {} [精准匹配]

location patt{} [普通匹配]

location ~ patt{} [正则匹配]

location 映射

location [ = | ~ | ~* | ^~ ] uri { … }

  1. 普通匹配

    注意:当普通 location 前面指定了“ ^~ ”,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配;

    location URI {}:
    	对当前路径及子路径下的所有对象都生效;
    location ^~ URI {}:
    	不使用正则表达式
    
    
  2. 精准匹配

    location = URI {}: 必须执行一个具体文件路径(不能使用目录)
    	精确匹配指定的路径,不包括子路径,因此,只对当前资源生效;
    
    
  3. 正则匹配

    location ~ URI {}:
    location ~* URI {}:
    模式匹配URI,此处的URI可使用正则表达式,区分字符大小写,*不区分字符大小写;

优先级:= 大于 ^~ 大于 | 大于 /|/dir/ *

多个location配置的情况下匹配顺序

首先匹配 =,其次匹配^~, 其次是按文件中顺序的正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

  1. 先进行精准匹配,如果命中立即返回结果并结束解析的过程;
  2. 精准匹配未命中判断普通匹配,如果命中多个会记录下"最长的"(最详细的URI)命中结果,但不会结束解析;
    • 当普通 location 前面指定了“ ^~ ”,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配;
    • 当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则
  3. 继续判断正则匹配,按照正则匹配设置的规则正则表达式进行匹配,如果有多个正则匹配由上到下进行匹配,一旦匹配成功一个会立即返回结果并结束解析.

ps:普通匹配的前后顺序是无所谓的,因为记录的是最长(最精准)的结果,而正则匹配是按从上到下匹配的,这个需要注意

注意

location 的执行逻辑跟 location 的编辑顺序无关。

矫正:这句话不全对,“普通 location ”的匹配规则是“最大前缀”,因此“普通 location ”的确与 location 编辑顺序无关;

但是“正则 location ”的匹配规则是“顺序匹配,且只要匹配到第一个就停止后面的匹配”;

“普通location ”与“正则 location ”之间的匹配顺序是?

先匹配普通 location ,再“考虑”匹配正则 location 。

注意这里的“考虑”是“可能”的意思,也就是说匹配完“普通 location ”后,有的时候需要继续匹配“正则 location ”,有的时候则不需要继续匹配“正则 location ”。两种情况下,不需要继续匹配正则 location :

  1. 当普通 location 前面指定了“ ^~ ”,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配;
  2. 当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则
location = / {
    [ configuration A ]
}

location / {
    [ configuration B ]
}

location /documents/ {
    [ configuration C ]
}

location ^~ /images/ {
    [ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ { 
    [ configuration E ] 
} 

请求“/”匹配配置A, 请求“/index.html”匹配配置B, 请求“/documents/document.html”匹配配置C, 请求“/images/1.gif”匹配配置D, 请求“/documents/1.jpg”匹配配置E。

img

例子,有如下匹配规则:

location = / {  
   #规则A  
}  
location = /login {  
   #规则B  
}  
location ^~ /static/ {  
   #规则C  
}  
location ~ \.(gif|jpg|png|js|css)$ {  
   #规则D  
}  
location ~* \.png$ {  
   #规则E  
}  
location !~ \.xhtml$ {  
   #规则F  
}  
location !~* \.xhtml$ {  
   #规则G  
}  
location / {  
   #规则H  
}  

那么产生的效果如下:

访问根目录/, 比如http://localhost/ 将匹配规则A

访问 http://localhost/login 将匹配规则B,http://localhost/register 则匹配规则H

访问 http://localhost/static/a.html 将匹配规则C

访问 http://localhost/a.gif, http://localhost/b.jpg 将匹配规则D和规则E,但是规则D顺序优先,规则E不起作用,而 http://localhost/static/c.png 则优先匹配到 规则C

访问 http://localhost/a.PNG 则匹配规则E, 而不会匹配规则D,因为规则E不区分大小写。

访问 http://localhost/a.xhtml 不会匹配规则F和规则G,http://localhost/a.XHTML不会匹配规则G,因为不区分大小写。规则F,规则G属于排除法,符合匹配规则但是不会匹配到,所以想想看实际应用中哪里会用到。

访问 http://localhost/category/id/1111 则最终匹配到规则H,因为以上规则都不匹配,这个时候应该是nginx转发请求给后端应用服务器,比如FastCGI(php),tomcat(jsp),nginx作为方向代理服务器存在。

所以实际使用中,通常至少有三个匹配规则定义,如下:

#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理,官网如是说。  
#这里是直接转发给后端应用服务器了,也可以是一个静态首页  
# 第一个必选规则  
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/;  
}  
   
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器  
#非静态文件请求就默认是动态请求,自己根据实际把握  
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了  
location / {  
    proxy_pass http://tomcat:8080/  
}  

3.4 请求头

  • host:决策server负责处理
  • uri:决策location
  • 反向代理:proxy_pass ip:port[uri];

Nginx中 location、proxy_pass 后面的url加与不加 / 的区别

客户端请求:/ooxx/a.html

Location的url:/ooxx/

  • proxy_pass的URI:http://node01
    • 将会被代理到http://node01/ooxx/a.html这个url
  • proxy_pass的URI:http://node01/
    • 将会被代理到http://node01/a.html

一、首先是location进行的是模糊匹配

1)没有/时,location /abc/def可以匹配/abc/defghi请求,也可以匹配/abc/def/ghi

2)而有/时,location /abc/def/不能匹配/abc/defghi请求,只能匹配/abc/def/anything这样的请求

二、proxy_pass的代理地址规则

在nginx中配置proxy_pass时,当在后面的url加上了/,相当于是绝对根路径,则nginx不会把location中匹配的路径部分代理走;

如果没有/,则会把匹配的路径部分也给代理走。

如:客户端发出请求 /ooxx/a.html,location中的url为/ooxx/ ,location中匹配的路径为/ooxx,且在proxy_pass的url后面加上了/(http://node01/),则nginx不会把location中匹配的路径/ooxx给代理走,最后代理走的路径为http://node01/a.html

例子:
下面四种情况分别用 http://192.168.1.4**/proxy/test.html** 进行访问。

第一种(常用的配置)

location  /proxy/ {
  proxy_pass http://127.0.0.1:81/;
}

结论:会被代理到 http://127.0.0.1:81**/test.html** 这个url

第二种(相对于第一种,最后少一个 /

location  /proxy/ {
  proxy_pass http://127.0.0.1:81;
}

结论:会被代理到http://127.0.0.1:81**/proxy/test.html** 这个url

第三种 (相对于第一种,转发到了 /ftlynx/上)

location  /proxy/ {
  proxy_pass http://127.0.0.1:81/ftlynx/;
}

结论:会被代理到http://127.0.0.1:81**/ftlynx/test.html** 这个url。

第四种(相对于第三种,转发到了 /ftlynx上 )

location  /proxy/ {
  proxy_pass http://127.0.0.1:81/ftlynx;
}

结论:会被代理到http://127.0.0.1:81**/ftlynx/test.html** 这个url ???

posted @ 2019-06-11 22:22  陈小哥cw  阅读(397)  评论(0编辑  收藏  举报