ubuntu下使用nginx+memcache搭建tomcat集群

2016/7/15 posted in  linux

tomcat 集群

当前tomcat集群,用得比较多的几种方法就是apache+tomcat、nginx+memcache+tomcat以及Hyproxy+tomcat。

做对比的也比较多,总得来说,apache的方式已经用得比较少了。其中在nginx 和 hyproxy的对比比较多。起始Hybroxy出来的时间比较晚,很多东西也做得比较完善了,可以使用。由于前面都是使用的nginx,所以这里先用这个来搭建并做一下相关记录。

大概原理

nginx+memcache+tomcat集群的大概原理是使用nginx做负载分担,多个tomcat在后端做服务集群。然后使用memcache在里面做session的共享。
同时memcache还可以做后端mysql的缓存,不过这个就需要单独拿出来做了,在这里不涉及。

安装

安装nginx、tomcat、memcache在这里就不过多涉及了。

配置nginx的负载均衡

nginx的主备也不在这里过多描述了,可以参考前面的博。

配置nginx的负载均衡:

    upstream myClusterServer1 {
        server 192.168.11.135:8080 weight=5;
        server 192.168.11.136:8080 weight=5;
        server 192.168.11.137:8080 weight=5;
    }
    server {
        listen       80;
        server_name  localhost;
        #charset koi8-r;
        charset utf-8;
        #access_log  logs/host.access.log  main;
        location / {
            root   html;
            index  index.html index.htm;
            proxy_pass   http://myClusterServer1;
            proxy_redirect    off;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            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;
            proxy_send_timeout   90;
            proxy_read_timeout   90;
            proxy_buffer_size   4k;
            proxy_buffers   4 32k;
            proxy_busy_buffers_size   64k;
            proxy_temp_file_write_size  64k;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
        root   html;
        }
    }

这里整理了三台主机的负载均衡

配置完成后进行/usr/local/nginx/sbin/nginx -s reload 重启nginx即可

此时访问测试工程就可以发现,负载分担已经起作用了。

配置memcached

启动memcached

/usr/bin/memcached -m 64 -d -u memcache -p 11211 -l 192.168.11.141

不要使用默认的启动,默认的启动会绑定到127.0.0.1上,这样其他服务是不能访问的

在第二台上配置启动:

/usr/bin/memcached -m 64 -d -u memcache -p 11211 -l 192.168.11.142

启动完成后就可以进行memcache共享了

tomcat配置

配置测试工程

测试工程中加一个jsp文件就可以了

    <html> 
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
        <title>Tomcat+memcached共享session测试</title> 
    </head>
    <body>
    SessionID:<%=session.getId()%>
    <BR>  
    SessionIP:<%=request.getServerName()%>
    <BR>  
    SessionPort:<%=request.getServerPort()%>
          <BR>
    <%  
    out.println("This is Tomcat Server 8081.");
    %>
    </body> 
    </html>
配置tomcat目录

使用memcache需要使用的jar包有

asm-3.2.jar
commons-codec-1.5.jar
couchbase-client-1.4.0.jar
httpcore-4.3.jar
httpcore-nio-4.3.jar
javolution-5.4.3.1.jar
jettison-1.3.jar
kryo-1.04.jar
kryo-serializers-0.10.jar
memcached-session-manager-1.7.0.jar
memcached-session-manager-tc7-1.7.0.jar
minlog-1.2.jar
msm-kryo-serializer-1.6.3.jar
netty-3.5.5.Final.jar
reflectasm-0.9.jar
spymemcached-2.11.1.jar

这些包不要放到工程里面,而是放到tomcat的lib目录中,ubuntu中在/usr/share/tomcat7/lib/中,mac在 /Library/tomcat/apache-tomcat-7.0.42/中。 否则可能会出现类无法找到的问题。

配置tomcat配置文件

配置context.xml ,这个文件在/var/lib/tomcat7/webapps/conf

    <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager" 
        memcachedNodes="n1:192.168.11.141:11211 n2:192.168.11.142:11211"
        sticky="false"
        requestUriIgnorePattern=".*\.(png|gif|jpg|css|js|ico|jpeg)$"
        sessionBackupAsync="false"
        sessionBackupTimeout="100"
        transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"/>

配置server.xml ,这个文件同样在/var/lib/tomcat7/webapps/conf

Engine中添加

    <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcatRoute1">

配置多个memcache节点中间加空格,session会在多个memcache节点中共享,就算某个memcache挂掉也可以从另外的节点继续获取session。

完成

这些都配置完成后,可以再通过负载均衡来访问,可以看到相关的session访问也一样了。如果没有配的时候,每次访问到不同的节点上会新增一个新的session。

问题

大多数走到这一步都完了,但是存在一些问题。现在nginx、tomcat、memcache、mysql都集群了,对于nginx、memcache、mysql挂掉之后都可以由其他的拉起来。

简单的tomcat服务down机等,可以通过nginx的配置 proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90;来进行完成。后面也会详细说明一下这些配置

但是现在如果某一台tomcat异常,但是请求未挂掉的时候,(比如内存溢出等),实际上是不能提供服务的,但是nginx还是会将映射找到这台挂掉的tomcat上,这是这个请求无法达成,后面所有的到这个服务器的请求都将出错。所以必须有检查错误的剔除机制。 —— 想到的简单解决方案是在当前本机上或者在核心上监控,如果这台服务器的服务无法提供,就直接把tomcat给停掉。

90秒是否过长了,对于某些服务可能需要降低错误时间。

参考

可以参考的几个网站:

http://www.cnblogs.com/phirothing/archive/2013/12/05/3459814.html —— 这个写的比较清晰,适合配置使用

http://www.2cto.com/os/201109/104650.html ——写得不是那么清晰,但是是在ubuntu下面的

http://blog.csdn.net/zht666/article/details/38515147 —— 有些写的比价细,但是有些有bug

nginx的一些超时配置

client_header_timeout

语法 client_header_timeout time

默认值 60s

上下文 http server

说明 指定等待client发送一个请求头的超时时间(例如:GET / HTTP/1.1).仅当在一次read中,没有收到请求头,才会算成超时。如果在超时时间内,client没发送任何东西,nginx返回HTTP状态码408(“Request timed out”)

client_body_timeout

语法 client_body_timeout time

默认值 60s

上下文 http server location

说明 该指令设置请求体(request body)的读超时时间。仅当在一次readstep中,没有得到请求体,就会设为超时。超时后,nginx返回HTTP状态码408(“Request timed out”)

keepalive_timeout

语法 keepalive_timeout timeout [ header_timeout ]

默认值 75s

上下文 http server location

说明 第一个参数指定了与client的keep-alive连接超时时间。服务器将会在这个时间后关闭连接。可选的第二个参数指定了在响应头Keep-Alive: timeout=time中的time值。这个头能够让一些浏览器主动关闭连接,这样服务器就不必要去关闭连接了。没有这个参数,nginx不会发送Keep-Alive响应头(尽管并不是由这个头来决定连接是否“keep-alive”)
两个参数的值可并不相同
注意不同浏览器怎么处理“keep-alive”头
MSIE和Opera忽略掉"Keep-Alive: timeout=" header.
MSIE保持连接大约60-65秒,然后发送TCP RST
Opera永久保持长连接
Mozilla keeps the connection alive for N plus about 1-10 seconds.
Konqueror保持长连接N秒

lingering_timeout

语法 lingering_timeout time

默认值 5s

上下文 http server location

说明 lingering_close生效后,在关闭连接前,会检测是否有用户发送的数据到达服务器,如果超过lingering_timeout时间后还没有数据可读,就直接关闭连接;否则,必须在读取完连接缓冲区上的数据并丢弃掉后才会关闭连接。

resolver_timeout

语法 resolver_timeout time

默认值 30s

上下文 http server location

说明 该指令设置DNS解析超时时间

proxy_connect_timeout

语法 proxy_connect_timeout time

默认值 60s

上下文 http server location

说明 该指令设置与upstream server的连接超时时间,有必要记住,这个超时不能超过75秒。
这个不是等待后端返回页面的时间,那是由proxy_read_timeout声明的。如果你的upstream服务器起来了,但是hanging住了(例如,没有足够的线程处理请求,所以把你的请求放到请求池里稍后处理),那么这个声明是没有用的,由于与upstream服务器的连接已经建立了。

proxy_read_timeout

语法 proxy_read_timeout time

默认值 60s

上下文 http server location

说明 该指令设置与代理服务器的读超时时间。它决定了nginx会等待多长时间来获得请求的响应。这个时间不是获得整个response的时间,而是两次reading操作的时间。

proxy_send_timeout

语法 proxy_send_timeout time

默认值 60s

上下文 http server location

说明 这个指定设置了发送请求给upstream服务器的超时时间。超时设置不是为了整个发送期间,而是在两次write操作期间。如果超时后,upstream没有收到新的数据,nginx会关闭连接

proxy_upstream_fail_timeout(fail_timeout)

语法 server address [fail_timeout=30s]

默认值 10s

上下文 upstream

说明 Upstream模块下 server指令的参数,设置了某一个upstream后端失败了指定次数(max_fails)后,该后端不可操作的时间,默认为10秒