nginx代理tomcat导致css或js加载失败

Web服务器经常会使用nginx作前置路由,在使用nginx配置Web服务器负载均衡、动静分离,会碰到设置反向代理后导致前端资源无法加载的问题

nginx反向代理的tomcat服务器导致前端资源css或js加载失败大概可以分为:端口丢失、真实ip或端口获取错误、js或者css太大加载失败等情形

端口丢失

之前笔者也有文章单独介绍,可参考http://flyflyfish.com/2018/02/24/nginx%E8%BD%AC%E5%8F%91%E4%B8%A2%E5%A4%B1%E7%AB%AF%E5%8F%A3%E9%97%AE%E9%A2%98/

反向代理获取真实ip(域名)、端口、协议

nginx反向代理后,servlet应用通过request.getRemoteAddr()取到的IP是nginx的IP,并非客户端的真实IP;通过request.getRequestUrl()获取的ip(域名)、端口、协议都是nginx对应的参数。

  • 比如nginx的配置:
http {
    upstream backend {
        server 127.0.0.1:8080;
        #server backend1.example.com wight=5;
        #server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;

        #server backup1.example.com backup;
    }

    server {
        listen 80;
        server_name your.domain.com;

        location /test {
            proxy_pass http://backend/test;
        }
        ...
    }
}

在浏览器打开http://your.domain.com/test访问servlet应用,获取客户端IP和URL:

log.info("RemoteAddr:{}, URL:{}", request.getRemoteAddr(), request.getRequestURL());
//输出结果
RemoteAddr:127.0.0.1, URL:http://127.0.0.1:8080/test
  • 针对tomcat+nginx的解决方案:

nginx添加如下配置,:

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

如果不知道如何添加,可参考nginx转发丢失端口的问题。添加完后,输出结果如下:

//输出结果
RemoteAddr:127.0.0.1, URL:http://浏览器的ip地址/test

发现RemoteAddr仍然获取不正确,解决方案如下:

  • 方案一:通过request.getHeader("X-Forwrad-For")request.getHeader("X-Real-IP")获取到nginx配置的Header。

  • 方案二: 配置tomcat,通过Servlet APIrequest.getRemoteAddr()方法获取客户端的IP。Tomcat的server.xml,在Host元素内最后加入:

<Valve className="org.apache.catalina.valves.RemoteIpValve" />

JS或css无法完全加载

nginx的代理缓存区,默认较小导致部分文件出现加载不全的问题,比较典型的如jQuery框架,可以通过配置调整nginx的缓存区即可。

最终完整配置如下:

http {
    # http_proxy 
    proxy_buffer_size 128k;
    proxy_buffers 32 128k;
    proxy_busy_buffers_size 128k;

    upstream backend {
        server 127.0.0.1:8080;
    }

    server {
        listen 80;
        server_name your.domain.com;

        location /test {
            proxy_pass http://backend/test;
            # proxy_params
            proxy_set_header Host $http_host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        ...
    }
    ...
}

关于nginx的http_proxy模块参数含义:

未分类

参考链接:

  • https://lanjingling.github.io/2015/10/28/nginx-tomcat-cluster/

  • http://www.zving.com/c/2014-03-19/257610.shtml

  • http://blog.csdn.net/xiao__gui/article/details/73733797

  • https://www.jianshu.com/p/5c7d718f15d2

web网站性能优化:nginx开启GZIP压缩网页,JS,CSS

提高web网站性能优化,nginx开启GZIP压缩网页,JS,CSS,从而可以节约大量的带宽,提高传输效率,但是会消耗cpu资源,自己可以权衡一下,总体来说开启是值得的。

在nginx的nginx.conf的 http { } 里添加如下配置

nginx开启的配置:

gzipon;  #开启gzip
gzip_min_length 1024;  #低于1kb的资源不压缩,
gzip_comp_level 3; #压缩级别【1-9】,越大压缩率越高,同时消耗cpu资源也越多,建议设置在4左右。
gzip_types text/plainapplication/javascriptapplication/x-javascripttext/javascripttext/xmltext/css;  #需要压缩哪些响应类型的资源,多个空格隔开。不建议压缩图片,下面会讲为什么。
gzip_disable "MSIE [1-6].";  #配置禁用gzip条件,支持正则。此处表示ie6及以下不启用gzip(因为ie低版本不支持)
gzip_vary on;  #是否添加“Vary: Accept-Encoding”响应头

保存并重启nginx,刷新页面(为了避免缓存,请强制刷新)预览器上就能看到效果了。

火狐预览器:

未分类

谷歌预览器:

未分类

再去站长之家检查Seo:

未分类

可以看到压缩率100%,可怕,震惊!

注意几点:

(1)在gzip_http_version的默认值是1.1,就是说对HTTP/1.1协议的请求才会进行gzip压缩。
如果使用了proxy_pass进行反向代理,那么nginx和后端的upstream server之间是用HTTP/1.0协议通信的。
如果使用nginx通过反向代理做Cache Server,前端的nginx没有开启gzip,且后端的nginx上未设置gzip_http_version为1.0,那么Cache的url将不会被gzip压缩。

(2)gzip_min_length :从上图可以看到最后一个js大小不到1K所以是不压缩的,倒数第二个js来源第三方所以也不进行压缩。
设置允许压缩的页面最小字节数,页面字节数从header头中的Content-Length中进行获取。默认值是0,不管页面多大都压缩。建议设置成大于1k的字节数,小于1k可能会越压越大。 即: gzip_min_length 1024。

(3)gzip虽然好用,但是一下类型的资源不建议启用。图片类型,因为图片如jpg、png本身就会有压缩,所以就算开启gzip后,压缩前和压缩后大小没有多大区别,所以开启了反而会白白的浪费资源。

大文件,因为会消耗大量的cpu资源,且不一定有明显的效果。