nginx作为反向代理服务器的时候,如果端口设置的特殊,在重定向的时候可能遇到问题。当然可以通过在代码中redirect一个绝对地址来规避这些端口问题,但是对代码有侵入,也不优雅。还可以修改后端tomcat的proxyPort="xxx",xxx就是nginx的端口解决,这个值不设置就是默认,http对应80,https对应443。

在nginx处,都可以通过设置Host来解决,可以重定向到你想要的任何位置(ip和端口)。

proxy_set_header Host  $host:$server_port;

通过proxy_redirect指令也能处理部分情况。

proxy_redirect     http://host http://host:81;


nginx使用alias命令进行静态页面转发的时候,如果是.../xxxx1/xxxx2这种会被重定向到.../xxxx1/xxxx2/,nginx运行在8080,防火墙出口是80,重定向的时候就出现问题。它重定向到了nginx的8080端口。

有两种解决方式:

  1. 如果版本大于等于1.11.8,可以设置absolute_redirect off这样重定向的页面就是相对页面,浏览器自动会加上ip和端口。
  2. 如果版本小于1.11.8,可以设置port_in_redirect off这样在重定向的时候就没有端口,也即默认端口。
  3. 两个指令各有用处,看自己的nginx版本选用一种即可。

因为版本用的是1.16.1,可以使用absolute_redirect off;来解决。

但是如果防火墙出口端口不是80,那就最好升级nginx使用absolute_redirect了。注意这种被重定向的页面都会有缓存,所以测试的时候注意清空缓存。

在某些极端的网络环境下,比如防火墙出口端口为80,nginx运行在8080,有一部分人通过外网80访问,有一部分人通过内网8080访问,此时就可以利用nginx的if指令判断$host,指定不同的Host,实现完美的重定向。

为什么proxy反向代理和静态页面处理重定向的问题方法不一致呢?因为反向代理后端是动态服务器,动态服务器在redirect的时候其实是通过拿到Host和Port组装一个地址进行重定向,所以设置好$Host就行;而对于静态页面,没办法动态处理,所以nginx提供了port_in_redirect和absolute_redirect等指令来处理重定向。一点愚见,不知理解是否准确。

另外,nginx是可以通过不同域名但是相同端口运行的,相当于虚拟主机,使用不同的域名访问可以访问到不同的server。

nginx可以非常简单地实现http强制跳转https,目前总结了四种方法:

1. 利用rewrite指令

server {
    listen 80;
    server_name domain.com;
    rewrite ^(.*) https://$server_name$1 permanent;
}
server {
    listen 443 ssl;
    server_name domain.com;
    ssl on;
    ssl_certificate     /etc/nginx/ssl/domain.com.crt;
    ssl_certificate_key /etc/nginx/ssl/domain.com.crt;
    # other
}

2. 利用return httpcode指令

server {
    listen 80;
    server_name domain.com;
    return 301 https://$server_name$request_uri;
}
server {
    listen 443 ssl;
    server_name domain.com;
    ....
}

3. 利用error_page指令,只允许HTTP来访问时,用HTTP访问会让Nginx报497错误,然后利用error_page将链接重定向至HTTPS上。使用error_page指令时,将http和https的监听配置写在同一个server块中,对应的其他配置也需要在该server配置块中完成。 需要注意的是,此时需要将error_page指令语句写在最后,否则不能生效。

server {
    listen 80;
    listen 443 ssl;
    server_name domain.com;
    ssl on;
    ssl_certificate     /etc/nginx/ssl/domain.com.crt; 
    ssl_certificate_key /etc/nginx/ssl/domain.com.crt;
    # other
    error_page 497 https://$server_name$request_uri;
}

4. 利用页面meta标签重定向

# index.html
<html>  
    <meta http-equiv="refresh" content="0;url=https://domain.com/">
</html>
server {
    listen 80;
    server_name docs.lvrui.io;
    
    location / {
        # 将 index.html 文件放到下面的目录下
        root /var/www/html/refresh/;
    }
}

server {
    listen 443 ssl;
    server_name domain.com;
    index index.html index.htm;
    access_log  /var/log/nginx/docs.log  main;
    ssl on;
    ssl_certificate /etc/ssl/docs.20150509.cn.crt;
    ssl_certificate_key  /etc/ssl/docs.20150509.cn.key;
    error_page 404 /404.html;
    location / {
        root /var/www/html/docs;
    }
}

nginx的平滑升级:

编译新版本: ./configure(编译参数,可以通过./sbin/nginx -V获取) , make,千万不要make install

备份:cp sbin/nginx sbin/nginxold

升级:make upgrade,此时还未完成升级,./sbin/nginx -V还是原来的nginx版本

make install完成升级

由于nginx可以完成平滑升级,所以nginx的版本一般不要放在带有版本号的目录,以免升级后造成混淆。

{nginx}/sbin/nginx -T 可以dump出来nginx当前加载的配置,这个在误删nginx配置的时候可以起死回生,救人一命。

另外,不管是什么重要的配置,数据库数据,代码等,备份是很重要的!!!