• 关于反向代理

    Nginx能够作为一个反向代理来终结来自客户端的请求,并且向上游服务器打开一个新连接。新连接代表客户端向上游服务器发送请求。代理到上游服务器的配置中,最重要的是proxy_pass指令。该指令有一个参数,URL请求将会被转换,带有URI部分的proxy_pass指令将会使用该URI代替客户端request_uri部分。

location /uri {
    proxy_pass http://localhost:8080/newuri;
}


    实例:

[root@master vhost]# cat proxy.conf
server {
    listen 80;
    server_name localhost.myserver.com;
    access_log /usr/local/nginx/logs/proxy_access.log normal;
    location /test {
        proxy_pass http://localhost:8080/index;
    }
}
[root@master vhost]# cat localhost_myserver_com.conf
server {
    listen 8080;
    server_name localhost.myserver.com;
    access_log /usr/local/nginx/logs/localhost_access.log normal;
    location / {
        root /usr/local/nginx/html;
    }
}

    此时,在localhost_access.log中记录的请求发生了改变:

[root@master logs]# tail -1 proxy_access.log
192.168.1.38 - - 2019-03-28T04:02:58-04:00 "GET http://localhost.myserver.com/test.html HTTP/1.1"200 249 393 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36""-" 0.001 0.001
[root@master logs]#
[root@master logs]# tail -1 localhost_access.log
127.0.0.1 - - 2019-03-28T04:02:58-04:00 "GET http://localhost.myserver.com/index.html HTTP/1.0"200 205 414 "-" "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Safari/537.36""-" 0.001 -

    这个规则有两个例外情况:

        如果location定义了一个正则表达式,或者在location中有rewrite规则改变了URI时,在proxy_pass指定URI部分是不被允许的。



  • 向上游服务器传递客户端真实IP

location / {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://192.168.1.202:8080;
    }



  • upstream模块

    upstream模块经常与proxy搭配使用。upstream模块启用新的配置区段,定义了一组上游服务器。这些服务器可能被设置了不同的权重(权重越高的服务器将被Nginx分配更多的连接),也可能是不同的类型(TCP或UNIX域),也可能出于对服务器的维护而标记为down。

 

  使用指定的负载均衡算法

    Nginx默认会采用轮询算法,如果想切换为ip_hash或least_conn,只需要在upstream开始位置指定负载均衡算法

upstream nginxservers {
    least_conn;
    server 192.168.1.201:8080;
    server 192.168.1.202:8080;
    keepalive 32;
}

    向上游服务器保持活动连接

    Nginx服务器将会为每一个worker进程保持同上游服务器的连接。在Nginx需要同上游服务器持续保持一定数量的打开连接时,连接缓存非常有用。Nginx将会使用HTTP/1.1协议的持久连接机制维护这些打开的连接。

    在下面的例子中,Nginx起初仅需要为每一个worker进程打开32个TCP连接,然后通过不发送close的Connection头保持这些连接。

    使用proxy_http_version指定使用HTTP/1.1协议同上游服务器进行通信。

    使用proxy_set_header指令清除了Connection头的内容。

    在业务高峰期,Nginx会打开超过32个TCP连接,当高峰期结束,Nginx将关闭最近最少使用的连接,使连接数回落到32。

upstream nginxservers {
    server 192.168.1.201:8080;
    server 192.168.1.202:8080;
    keepalive 32;
}
server {
    listen 80;
    server_name localhost.myserver.com;
    access_log /usr/local/nginx/logs/proxy_access.log normal;
    location / {
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://nginxservers;
    }
}


    使用Memcached作为上游服务器

upstream memcaches {
    server 192.168.1.201:11211;
    server 192.168.1.202:11211;
}
server {
    location / {
        set $memcached_key "$uri?$args";
        memcached_pass memcaches;
        error_page 404 = @appserver;
    }
    location @appserver {
        proxy_pass http://127.0.0.1:8080;
    }
}


    使用FastCGI作为上游服务器

upstream fastcgis {
    server 192.168.1.201:9000;
    server 192.168.1.202:9000;
}
server {
    location / {
        fastcgi_pass fastcgis;
    }
}

    Nginx通过uwsgi模块提供基于Python的上游服务器的连接,配置类似于FastCGI模块,使用uwsgi_pass指令指定上游服务器。



  • 使用错误文件处理上游服务器问题

    有一些上游服务器无法响应请求的情况,此时,可以让Nginx从本地返回一个文件。

server {
    listen 80;
    server_name localhost.myserver.com;
    access_log /usr/local/nginx/logs/proxy_access.log normal;
    location / {
        proxy_pass http://nginxservers;
        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/local/nginx/html;
        }
    }
}

   或者在上游服务器无法响应请求时,想将请求转发至另一组定义好的后备服务器(fallback)。

server {
    listen 80;
    server_name localhost.myserver.com;
    access_log /usr/local/nginx/logs/proxy_access.log normal;
    location / {
        proxy_pass http://nginxservers;
        error_page 500 502 503 504 = @fallback;
    }
    location @fallback {
        proxy_pass http://localhost:8080;
    }
}



  • 使用SSL对流量进行加密:

    使用OpenSSL生成SSL证书

# openssl req -newkey rsa:2048 -nodes -out localhost.myserver.com -keyout localhost.myserver.com.key
    ---- 命令执行时提示输入公司名、邮件等信息,直接回车即可;
    ---- 完成以上命令会得到证书签名请求(Certificate Signing Requests),保存在“localhost.myserver.com”文件中;
    ---- 证书签名由证书颁发机构授予。或者也可以自己签名,自己的签名不能用在公网服务器上
# openssl x509 -req -days 365 -in localhost.myserver.com -signkey localhost.myserver.com.key -out localhost.myserver.com.pem
Signature ok
subject=/C=XX/L=Default City/O=Default Company Ltd
Getting Private key


    对客户端和反向代理之间的流量进行加密

server {
    listen 443 default ssl;
    server_name localhost.myserver.com;
    ssl_prefer_server_ciphers on;
    ssl_protocols SSLv2 SSLv3 TLSv1;
    ssl_ciphers AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL;
    ssl_session_timeout 5m;
    ssl_session_cache shared:WEB:10m;
    ssl_certificate /usr/local/nginx/ssl_key/localhost.myserver.com.pem;
    ssl_certificate_key /usr/local/nginx/ssl_key/localhost.myserver.com.key;
    location / {
        access_log /usr/local/nginx/logs/ssl.log normal;
        proxy_set_header X-Forwarded-For-Proto $scheme;
        proxy_pass http://127.0.0.1:8080;
    }
}

    首先使用listen指令的ssl参数激活了SSL模块。

    然后指定了希望客户端使用服务器密码,以及协议类型和使用的认证方法;

    ssl_session_cache指令被设定为shared,第二部分和第三部分分别是缓存的名称和大小;

    然后指明证书和key的路径,要保证文件能被Nginx使用的用户访问。

    最后设置X-Forwarded-For-Proto头的值为$scheme,告诉上游服务器原始请求使用的是http还是https。


    对反向代理和上游服务器之间的流量进行加密

server {
    ……
    location / {
        ……
        proxy_pass https://127.0.0.1:8080;
    }
}

    要保证上游服务器也启用了SSL模块,这里的上游服务器使用Nginx提供服务,设置方法同“对客户端和反向代理之间的流量进行加密”。