nginx为web服务做反向代理时,会监听80端口,收到客户端请求后会重新解封装,按照自己的模式再次封装报文发给后端web服务器,响应报文返回客户端时亦是如此

使用的模块:ngx_http_proxy_module

官方文档:http://nginx.org/en/docs/http/ngx_http_proxy_module.html#example

示例:

location / {
    proxy_pass        //指定upstrem server地址,将请求报文发给哪台web服务器 
    proxy_set_header Host      $host;   //记录客户端请求时的请求头部中的主机名,记录这个主机名是为了实现虚拟主机映射
    proxy_set_header X-Real-IP $remote_addr;//客户端经过代理服务器时源ip会封装为代理服务器的ip,使用X-Real-IP记录她原来的ip,用于日志
}

location  /uri {

        proxy_pass http://back_server:port/newuri;

        rewrite

}

1.这里的/uri会映射到newuri目录

2.但是如果是模式匹配,如~* /uri 那么这里的uri将补在newuri之后,此时back_server:port/后不能带任何路径

3.如果使用了url重定向,那么后面的newurl将失效,会把重定向后的结果直接补在back_server:port/后面进行响应

例子:

location / {
    #root   html;
    #proxy_pass http://192.168.3.139/;
    index  index.html index.htm;
        }

location /forum/ {
    proxy_pass http://192.168.3.139/bbs/;#访问forum就会映射到后端主机/bbs目录下
    #proxy_pass http://192.168.3.139/; #将url的forum映射到根目录而不是补到后面
    index  index.html index.htm;
        }
#下面的例子中\.(jpg|png|gif)只是一种模式,不会像上面一样做url映射
    location ~* \.(jpg|png|gif)$ {
    proxy_pass http://192.168.3.139;#模式匹配这种情况http://192.168.3.139后面什么也不能带
        }

记录客户端真实ip

location / {
    #root   html;
    proxy_pass http://192.168.3.139/;
    index  index.html index.htm;
    proxy_set_header Host $host;
    proxy_set_header x-Real-IP $remote_addr;
         }

编辑后端主机http.conf

wKioL1YeZYbwS_VoAABvWLpwH9w084.jpg

访问后查看后端主机日志:

wKiom1YeZjbjI9laAADHuxW5Bjo401.jpg

proxy_set_header:报文从代理服务器到后端服务器时,重新构建了请求报文,我们可以使用set_header来设定其请求首部

proxy_set_header Host $host;

当后端web服务器上也配置有多个虚拟主机配置在同一个ip上时,向后端发送请求时在报文中应该有主机名来区分每个虚拟主机。在每个server模块中设置,区分每个虚拟主机。

proxy_set_header X-Real-IP $remote_addr;

如果后端Web服务器上的程序需要获取用户IP,从该Header头中获取 

proxy_set_header X-Forward-For $proxy_add_x_forwarded_for; 当nginx代理是多级的,记录下经过的各个代理服务器

缓存:

proxy_cache:缓存基于键值存储,存储格式由以下定义,键存储在内存中,值存储在文件系统上

proxy_cache_path    path    [levels=levels]    [use_temp_path=on|off]    keys_zone=name:size    [inactive=time]    [max_size=size]

max_size指定缓存最大多少空间

inactive=time 缓存条目在多长时间未访问就被标记为非活动,下一次轮询调度就删除

proxy_cache zone  定义在location段中,与上面proxy_cache_path定义的keys_zone=name:size中的name匹配,调用这段空间调用了就可以使用此处的缓存了

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;#只能在http上下文中定义,可定义多组,在server上下文中调用
file names in a cache will look like this:
/data/nginx/cache/c/29/b7f54b2df7773722d382f4809d65029c

定义了缓存目录在文件系统上的路径,这个路径属主属组必须是允许nginx进程的用户的属主属组

level定义了层级数,后面表示每个一级子目录只能以1个字符命名,2表示每个二级子目录只能以2个字符命名。keys_zone定义在内存空间中存储的键占据的空间大小和这段空间的名字

proxy_cache_methods    GET |    HEAD |    POST    ...:

定义仅在客户端使用哪些方法时才缓存,默认是GET和HEAD

proxy_cache_min_uses 1;
定义响应了客户端多少次请求才缓存,默认为1,缓存比较繁忙时可以定义多一点

proxy_cache_purge string缓存修建,请求哪一个内容就删除哪一个内容,可以实现手动管理缓存

proxy_cache_revalidate on|off   当缓存过期了,会发送探针包到后端问是否我的缓存内容和你的不一致,如果不一致,用后端真实数据覆盖我的缓存,如果一致,继续用这段缓存

proxy_cache_bypass string: 设置在何种情形下nginx将不从cache取数据的;
例子:$cookie_nocache $arg_nocache  $http_authorization---->有cookie不缓存,参数中明显有nocache的不缓存,有http授权信息的不缓存

proxy_cache_path /data/nginx/cache keys_zone=cache_zone:10m;

map $request_method $purge_method {
    PURGE   1;
    default 0;
}

server {
    ...
    location / {
        proxy_pass http://backend;
        proxy_cache cache_zone;
        proxy_cache_key $uri;
        proxy_cache_purge $purge_method;
    }
}

proxy_connect_timeout:连接后端的超时时间(超时了是否用缓存)

proxy_cache_use_stale error |    timeout |    invalid_header |    updating |    http_500 |    http_502 |    http_503 |    http_504 |    http_403 |    http_404 |    off

是否使用过期缓存响应用户请求,后面的参数指定在什么场景中使用过期缓存

proxy_cache_valid [code ...] time;按照响应码定义缓存有效时长

proxy_cache_valid 200 302 10m;
proxy_cache_valid 404      1m;

开启缓存功能:

编辑nginx.conf
proxy_cache_path /cache/nginx/ levels=1:1 keys_zone=mycache:32m;
chown -R nginx.nginx /cache/nginx
调用:
location /forum/ {
    proxy_cache mycache;
    proxy_cache_valid 200 1h;
    proxy_cache_valid 301 302 10m;
    proxy_cache_use_stale error timeout invalid_header http_500;
    proxy_pass http://192.168.3.139/bbs/;
    index  index.html index.htm;
        }

请求后查看缓存目录发现出现了缓存内容

wKiom1YecWGxXGjmAABPgQoIvyU115.jpg

proxy_http_version 1.0 | 1.1,默认1.0,1.1在长连接中使用,可以控制客户端到代理服务器使用1.1的长连接从缓存中取数据,代理服务器到后端http服务器则使用1.0短连接,从而节省了需要提供保持连接的服务器资源

proxy_hide_header:隐藏由proxy响应给客户端时指定的首部

proxy_read_timeout和proxy_connect_timeout不同,这个是等待后端响应报文的超时时间,proxy_connect_timeout是代理想后端发送连接请求的超时时间

ngx_stream_upstream_module

官方文档:http://nginx.org/en/docs/http/ngx_http_upstream_module.htm

配置代理后端多个主机:

nginx.conf文件

upstream upservers {
    #ip_hash此处可以指定使用ip_hash负载均衡算法实现同一客户端访问时一直调度在同一服务器上
    server 192.168.3.139;  #注意地址后面使用weight可以指定调度时权重,还可以使用down参数,当做临时维护时令前端健康监测监测到此主机down
    server 192.168.3.140 max_fails=2 fail_timeout=1 backup;backup设置备用服务器(sorry server),一旦有好的服务器上线,他就失效,一般设置代理服务器自己为备用服务器
        } 
location /forum/ {
    proxy_pass http://upservers/;
    index  index.html index.htm;
        }

重启nginx测试,发现轮询调度后端服务器

健康监测相关:nginx自带后端健康监测功能

  • fail_timeout=time访问失败后多久后不再调度此服务器

  • max_fails=number 最多访问失败两次就不再调度此服务器


session使用ip地址绑定使用ip_hash会破坏负载均衡,大量做了SNAT的用户被识别为同一个而发送到后端同一台服务器。所以我们应该基于应用层做基于cookie的绑定

基于sticky实现session绑定:
    cookie:携带cookie信息作为自己的标识符

upstream backend {
    server backend1.example.com;
    server backend2.example.com;

    sticky cookie srv_id expires=1h domain=.example.com path=/;
}

    route:客户端携带去往后端服务器的路由作为自己的标识符

map $cookie_jsessionid $route_cookie {
    ~.+\.(?P<route>\w+)$ $route;
}

map $request_uri $route_uri {
    ~jsessionid=.+\.(?P<route>\w+)$ $route;
}

upstream backend {
    server backend1.example.com route=a;
    server backend2.example.com route=b;

    sticky route $route_cookie $route_uri;
}

    learn ():根据客户端和服务器的交互信息

Syntax:
sticky cookie name [expires=time] [domain=domain] [httponly] [secure] [path=path];
sticky route $variable ...;
sticky learn create=$variable lookup=$variable zone=name:size [timeout=time];

least_conn: 调度方法,最少连接;相当于wlc中的wlc算法,根据后端服务器承载的请求连接数量作出调度决策

keepalive 5:激活nginx和后端upstream server之间使用持久连接的时长,一般后端是缓存服务器时应设置为长连接,但后面是http服务器时不建议开启长连接

health_check 参数:间断性向后端upstream server发送健康探测指令,可以通过应用层模拟做请求资源进行健康监测,使用healthcheck时建议关闭访问日志,否则会产生大量IO

location / {
    proxy_pass http://backend;
    health_check;
}

比server上下文自带的健康监测功能更好用

http {
    server {
    ...
        location / {
            proxy_pass http://backend;
            health_check match=welcome;
        }
    }

    match welcome {
        status 200;
        header Content-Type = text/html;
        body ~ "Welcome to nginx!";
    }
}

自定义响应头部信息,在server上下文中定义

add_header X-Via $server_addr;
add_header X-Cache $upstream_cache_status;

开启缓存:

location /forum/ {
            proxy_cache mycache;
            proxy_cache_valid 200 1h;
            proxy_cache_valid 301 302 10m;
            proxy_cache_use_stale error timeout invalid_header http_500;
            proxy_pass http://upservers/;
            index  index.html index.htm;
        }

测试:缓存命中,经由的服务器指也记录了下来

wKiom1YfxWrA7woRAAEpQQu6zFc988.jpgngx_http_fastcgi_module:实现与应用程序服务器的交互,根据用户请求资源后缀名判断是否发送给后端应用程序服务器

location / {
    fastcgi_pass  localhost:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /home/www/scripts/php$fastcgi_script_name;
    fastcgi_param QUERY_STRING    $query_string;
    fastcgi_param REQUEST_METHOD  $request_method;
    fastcgi_param CONTENT_TYPE    $content_type;
    fastcgi_param CONTENT_LENGTH  $content_length;
}

在后端服务器上安装fpm,yum install php-fpm  启动:systemctl start php-fpm

配置文件:

[root@node3 yum.repos.d]# rpm -ql php-fpm
/etc/logrotate.d/php-fpm
/etc/php-fpm.conf
/etc/php-fpm.d
/etc/php-fpm.d/www.conf
/etc/sysconfig/php-fpm
/run/php-fpm
/usr/lib/systemd/system/php-fpm.service
/usr/lib/tmpfiles.d/php-fpm.conf
/usr/sbin/php-fpm
对于php服务器在远程服务器上这种情况下
listen = 127.0.0.1:9000
listen.allowed_clients = 127.0.0.1这两项保证前端web可以连接php服务器
配置nginx.conf文件:
        location ~ \.php$ {
            root           /usr/local/html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi_params;
        }
在index指令下添加php页面
location / {
    index  index.php index.html index.htm;
        }
修改fastcgi_params文件为
        fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
        fastcgi_param  SERVER_SOFTWARE    nginx;
        fastcgi_param  QUERY_STRING       $query_string;
        fastcgi_param  REQUEST_METHOD     $request_method;
        fastcgi_param  CONTENT_TYPE       $content_type;
        fastcgi_param  CONTENT_LENGTH     $content_length;
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
        fastcgi_param  REQUEST_URI        $request_uri;
        fastcgi_param  DOCUMENT_URI       $document_uri;
        fastcgi_param  DOCUMENT_ROOT      $document_root;
        fastcgi_param  SERVER_PROTOCOL    $server_protocol;
        fastcgi_param  REMOTE_ADDR        $remote_addr;
        fastcgi_param  REMOTE_PORT        $remote_port;
        fastcgi_param  SERVER_ADDR        $server_addr;
        fastcgi_param  SERVER_PORT        $server_port;
        fastcgi_param  SERVER_NAME        $server_name;

配置数据库:yum install php-mysql 启动即可

重载nginx服务并且测试

wKiom1Yq79jxJJK_AAG7sCW3XZ8173.jpg

fastcgi缓存

定义:
fastcgi_cache_path /cache/fastcgi/ levels=1:1 keys_zone=fcgicache:32m inactive 3m max_size=1g;
调用:
location ~ \.php$ {
            root           /usr/local/html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi_params;
            fastcgi_cache fcgicache; #使用off参数可以暂时关闭缓存功能
            fastcgi_cache_valid 200 10m; #缓存时长必须得定义
            fastcgi_cache_valid 302 10m;
            fastcgi_cache_valid any 10m;

        }