Nginx+Tomcat实现动静态请求分离

       工作中经常会碰到使用tomcat作为java容器的项目,虽然tomcat是一个不错的java容器,但处理静态资源请求就不是它的强项了,如果网站的访问量预计会逐渐增大,那么就需要做一下网站的动静资源请求分离了,这里用到的静态服务器是nginx,高并发、低消耗是它的优点。
使用Nginx+Tomcat的的优点如下:
1、提高网站负载量,尤其是在网站静态资源较多时,更能体现其优势。
2、屏蔽后端服务器,因为Nginx是一款反向代理,使后端服务器更安全。
3、可以提供负载均衡功能,横向扩展WEB负载能力。

Nginx安装,上篇文章已经详细讲述,详见[Nginx源码安装],本文不在赘述。
Tomcat安装 本文使用tomcat8.0 和JDK 1.8

1、安装JDK

yum install java-1.8.0-openjdk.x86_64

2、下载tomcat8.0

下载URL:http://mirrors.cnnic.cn/apache/tomcat/tomcat-8/v8.0.24/bin/apache-tomcat-8.0.24.tar.gz

tar -zxvf apache-tomcat-8.0.24.tar.gz -C /usr/local/
useradd tomcat   #使用tomcat用户管理
passwd tomcat
chown -R tomcat:tomcat /usr/local/apache-tomcat-8.0.24
cd /usr/local/apache-tomcat-8.0.24/bin
./startup.sh      ###这里不做过多配置,稍后会有文章做tomcat配置及优化的详细讲解。

3、进入正题,开始配置Nginx和Tomcat的动静态分离。

vi /usr/local/nginx/nginx.conf

#user  nobody;
worker_processes  1;
error_log  logs/error.log;
pid        logs/nginx.pid;

events {
    worker_connections  10240;
}

http {
    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        on;
    keepalive_timeout  65;  
##Keep-Alive功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive功能避免了建立或者重新建立连接。
##优势:
##在请求大量小文件的时候,长连接的有效使用可以减少重建连接的开销.
##缺点:
##当长连接时间过长,比如60s,即使是浏览器没有任何请求,服务器仍然会维护着该浏览器的连接,一旦用户很多,对apache而言,就是需要
##维护大量的空闲进程.而对使用线程的轻量级web服务器如nginx,会由于超时时间过长而使资源无效占##有而引发的损失,已超过了由于
##重复连接而造成的损失..
    gzip  on;  #打开压缩选项;
    gzip_min_length 1k;
    gzip_buffers    4 16k;
    gzip_http_version 1.0;
    gzip_comp_level 2;
    gzip_types text/plain application/x-javascript text/css application/xml;
    gzip_vary on;
    server {
        listen       80;
        server_name  localhost;
        access_log  logs/host.access.log  main;
        location ~* .(gif|jpg|png|bmp|swf|js|css|htm)$   # ~*不区分大小写这些后缀名的请求由nginx处理;
        {
        root /usr/local/webapps/testClient;  ##静态资源目录指向tomcat部署的程序包,这样可以简化部署,不用管理两个地
                                             ##方的文件,这个位置可以根据需求自由指定;    
        expires 30d;   #使用expires缓存模块,缓存到客户端30天
        }
        location ~* ^/testClient/.*$ {   #不区分大小写,以/testClient/开始的字符请求,除了上边的交由nginx处理的,其
                                         ##他都由tomcat处理;
        index index.jsp;
        proxy_pass http://127.0.0.1:8080;   #来自jsp请求交给tomcat处理
        proxy_redirect off; ##如果需要修改从被代理服务器传来的应答头中的"Location"和"Refresh"字段,可以用这个指令设置。
        proxy_set_header Host $host;    #后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
        proxy_set_header X-Real-IP $remote_addr;##其中这个X-real-ip是一个自定义的变量名,名字可以随意取,这样做完之后,
                                                ##用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取
                                                ##:request.getAttribute("X-real-ip");
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        client_max_body_size 10m;   #允许客户端请求的最大单文件字节数
        client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数
        proxy_connect_timeout 90;   #nginx跟后端服务器连接超时时间(代理连接超时)
        proxy_read_timeout 90;      #连接成功后,后端服务器响应时间(代理接收超时)
        proxy_buffer_size 4k;       #设置代理服务器(nginx)保存用户头信息的缓冲区大小
        proxy_buffers 6 32k;        #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
        proxy_busy_buffers_size 64k;#高负荷下缓冲大小(proxy_buffers*2)
        proxy_temp_file_write_size 64k; #设定缓存文件夹大小,大于这个值,将从upstream服务器传
        }
        error_page  404              /404.html;

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

配置完成,根据两条规则实现了动静态分离.
第一条,如果是gif|jpg|png|bmp|swf|js|css|htm 结尾的请求由nginx处理。
第二条,如果是/testClient/开头的,剩余的所有请求都发送到tomcat处理,这里的testClient 是我在tomcat部署的工程名称,如果有需要
可以将工程的上下文改成 / 这样就可以把location ~* ^/testClient/.*$  改成location ~* .*$
可根据你的需求定制更多的规则实现更复杂的需求,只要搞明白规则制定方法即可。
重启nginx服务 使配置生效

server nginx restart  ##在你建立了/etc/init.d/nginx 脚本的前提下执行,可参考前文[Nginx源码安装]

4、如何验证
验证方法很简单,就是先将静态资源的目录改为其他路径(上文中设置为同一路径),然后请求静态资源,如果能够请求道更改路径后的静态资源,就证明规则生效,实现了动静态分离。

5、扩展知识
1、关于一些对location认识的误区
 location 的匹配顺序是“先匹配正则,再匹配普通”。

矫正: location 的匹配顺序其实是“先匹配普通,再匹配正则”。我这么说,大家一定会反驳我,因为按“先匹配普通,再匹配正则”解释不了大家平时习惯的按“先匹配正则,再匹配普通”的实践经验。这里我只能暂时解释下,造成这种误解的原因是:正则匹配会覆盖普通匹配(实际的规则,比这复杂,后面会详细解释)。

location 的执行逻辑跟 location 的编辑顺序无关(本文已验证,如果调换规则1、2的顺序,效果不同)。

矫正:这句话不全对,“普通 location ”的匹配规则是“最大前缀”,因此“普通 location ”的确与 location 编辑顺序无关;但是“正则 location ”的匹配规则是“顺序匹配,且只要匹配到第一个就停止后面的匹配”;“普通location ”与“正则 location ”之间的匹配顺序是?先匹配普通 location ,再“考虑”匹配正则 location 。注意这里的“考虑”是“可能”的意思,也就是说匹配完“普通 location ”后,有的时候需要继续匹配“正则 location ”,有的时候则不需要继续匹配“正则 location ”。两种情况下,不需要继续匹配正则 location :( 1 )当普通 location 前面指定了“ ^~ ”,特别告诉 Nginx 本条普通 location 一旦匹配上,则不需要继续正则匹配;( 2 )当普通location 恰好严格匹配上,不是最大前缀匹配,则不再继续匹配正则。

总结一句话:  “正则 location 匹配让步普通 location 的严格精确匹配结果;但覆盖普通 location 的最大前缀匹配结果”

2、nginx location介绍
Nginx 中的 Location 指令 是NginxHttpCoreModule中重要指令。Location 指令,是用来为匹配的 URI 进行配置,URI 即语法中的”/uri/”,可以是字符串或正则表达式。但如果要使用正则表达式,则必须指定前缀。

nginx location语法

基本语法:location [=|~|~*|^~] /uri/ { … }

= 严格匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。
~ 为区分大小写匹配(可用正则表达式)
~* 为不区分大小写匹配(可用正则表达式)
!~和!~*分别为区分大小写不匹配及不区分大小写不匹配
^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式。

Location语法语法:location [=|~|~*|^~] /uri/ { … }
注:
1、~   为区分大小写匹配
2、~* 为不区分大小写匹配
3、!~和!~*分别为区分大小写不匹配及不区分大小写不匹配

示例一:

location  / { }

匹配任何查询,因为所有请求都以 / 开头。但是正则表达式规则将被优先和查询匹配。

示例二:

 代码如下 复制代码
location =/ {}

仅仅匹配/

示例三:

 代码如下 复制代码
location ~* .(gif|jpg|jpeg)$ {
rewrite .(gif|jpg)$ /logo.png;

注:不区分大小写匹配任何以gif,jpg,jpeg结尾的文件
nginx location应用实例

 代码如下 复制代码
location = / {
 # 只匹配 / 查询。
 
}location / {
 # 匹配任何查询,因为所有请求都已 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配。
 
}location ^~ /images/ {
 # 匹配任何已 /images/ 开头的任何查询并且停止搜索。任何正则表达式将不会被测试。
 
}location ~* .(gif|jpg|jpeg)$ {
 # 匹配任何已 gif、jpg 或 jpeg 结尾的请求。
 
}location ~* .(gif|jpg|swf)$ {
  valid_referers none blocked start.igrow.cn sta.igrow.cn;
  if ($invalid_referer) {
  #防盗链
  rewrite ^/ http://$host/logo.png;
  }
}
location ~* .(js|css|jpg|jpeg|gif|png|swf)$ {
if (-f $request_filename) {
   #根据文件类型设置过期时间
   expires    1h;
   break;
}
}
location ~* .(txt|doc)${
 #禁止访问某个目录
    root /data/www/wwwroot/linuxtone/test;
    deny all;
}

 

更多内容请参考官方WIKI http://wiki.nginx.org/

发表评论