设为首页 收藏本站
查看: 1069|回复: 0

[经验分享] Tomcat集群环境下session共享方案梳理(1)

[复制链接]

尚未签到

发表于 2017-12-26 15:00:19 | 显示全部楼层 |阅读模式
  对于web应用集群的技术实现而言,最大的难点就是:如何能在集群中的多个节点之间保持数据的一致性,会话(Session)信息是这些数据中最重要的一块。要实现这一点, 大体上有两种方式:
  一种是把所有Session数据放到一台服务器上或者数据库中,集群中的所有节点通过访问这台Session服务器来获取数据;
  另一种就是在集群中的所有节点间进行Session数据的同步拷贝,任何一个节点均保存了所有的Session数据。
  Tomcat集群session同步方案有以下几种方式:
  1)使用tomcat自带的cluster方式,多个tomcat间自动实时复制session信息,配置起来很简单。但这个方案的效率比较低,在大并发下表现并不好。
  2)利用nginx的基于访问ip的hash路由策略,保证访问的ip始终被路由到同一个tomcat上,这个配置更简单。但如果应用是某一个局域网大量用户同时登录,这样负载均衡就没什么作用了。
  3)利用nginx插件实现tomcat集群和session同步,nginx-upstream-jvm-route-0.1.tar.gz,是一个Nginx的扩展模块,用来实现基于Cookie的Session Sticky的功能。
  4)利用memcached实现(MSM工具)。memcached存储session,并把多个tomcat的session集中管理,前端在利用nginx负载均衡和动静态资源分离,在兼顾系统水平扩展的同时又能保证较高的性能。
  5)利用redis实现。使用redis不仅仅可以将缓存的session持久化,还因为它支持的单个对象比较大,而且数据类型丰富,不只是缓存 session,还可以做其他用途,可以一举几得。
  6)利用filter方法实现。这种方法比较推荐,因为它的服务器使用范围比较多,不仅限于tomcat ,而且实现的原理比较简单容易控制。
  7)利用terracotta服务器共享session。这种方式配置比较复杂。
  在Tomcat集群中,当一个节点出现故障,虽然有高可用集群来负责故障转移,但用户的session信息如何保持呢?
  下面介绍第4种方案,session复制同步使用MSM(Memcache-Session-Manager),即利用MSM+Memcached做Session共享。
  MSM介绍:(详细介绍可以参考:http://www.cnblogs.com/kevingrace/p/6401025.html)
  MSM是一个高可用的Tomcat Session共享解决方案,除了可以从本机内存快速读取Session信息(仅针对黏性Session)外,还可使用Memcached存取Session,以实现高可用。
  传统tomcat集群,会话复制随着结点数增多,扩展性成为瓶颈。MSM使用memcached完成统一管理tomcat会话,避免tomcat结点间过多会话复制。
  MSM利用Value(Tomcat 阀)对Request进行跟踪。Request请求到来时,从memcached加载session,Request请求结束时,将tomcat session更新至memcached,以达到session共享之目的, 支持sticky和non-sticky模式:
  sticky :
  no-sticky:
  在进行环境部署之前,要对cookie和session的工作机制非常了解,如果不了解其中的原理且只是机械性地去按照参考文档部署,那么这是毫无意义的。
  a)cookie是怎么工作的?
  加入我们创建了一个名字为login的Cookie来包含访问者的信息,创建Cookie时,服务器端的Header如下面所示,这里假设访问者的注册名是“wangshibo”,同时还对所创建的Cookie的属性如path、domain、expires等进行了指定。
  

Set-Cookie:login=wangshibo;path=/;domain=msn.com;  
expires=Monday,01-Mar-99 00:00:01 GMT
  

  

  上面这个Header会自动在浏览器端计算机的Cookie文件中添加一条记录。浏览器将变量名为“login”的Cookie赋值为“wangshibo”。
  注意,在实际传递过程中这个Cookie的值是经过了URLEncode方法的URL编码操作的。 这个含有Cookie值的HTTP Header被保存到浏览器的Cookie文件后,Header就通知浏览器将Cookie通过请求以忽略路径的方式返回到服务器,完成浏览器的认证操作。
  此外,我们使用了Cookie的一些属性来限定该Cookie的使用。例如Domain属性能够在浏览器端对Cookie发送进行限定,具体到上面的例子,该Cookie只能传到指定的服务器上,而决不会跑到其他的Web站点上去。Expires属性则指定了该Cookie保存的时间期限,例如上面的Cookie在浏览器上只保存到1999年3月1日1秒。 当然,如果浏览器上Cookie太多,超过了系统所允许的范围,浏览器将自动对它进行删除。至于属性Path,用来指定Cookie将被发送到服务器的哪一个目录路径下。
  说明:浏览器创建了一个Cookie后,对于每一个针对该网站的请求,都会在Header中带着这个Cookie;不过,对于其他网站的请求Cookie是绝对不会跟着发送的。而且浏览器会这样一直发送,直到Cookie过期为止。
  b)session是如何工作的?

  由于http是无状态的协议,你访问了页面A,然后再访问B页面,http无法确定这2个访问来自一个人,因此要用cookie或session来跟踪用户,根据授权和用户身份来 显示不同的页面。比如用户A登陆了,那么能看到自己的个人信息,而B没登陆,无法看到个人信息。还有A可能在购物,把商品放入购物车,此时B也有这个过程, 你无法确定A,B的身份和购物信息,所以需要一个session>  cookie是服务器发给客户端并保持在客户端的一个文件,里面包含了用户的访问信息(账户密码等),可以手动删除或设置有效期,在下次访问的时候,会返给服务器。

  注意:cookie可以被禁用,所以要想其他办法,这就是session。cookie数据存放在客户的浏览器上,session数据放在服务器上。cookie同时也是session>
  比如:你去商场购物,商场会给你办一张会员卡,下次你来出示该卡,会有打折优惠,该卡可以自己保存(cookie),或是商场代为保管,由于会员太多,个人需要保存卡号信息(session>  为什么要持久化session(共享session)?
  因为:在客户端每个用户的Session对象存在Servlet容器中,如果Tomcat服务器重启或者宕机的话,那么该session就会丢失,而客户端的操作会由于session丢失而造成数据丢失;如果当前用户访问量巨大,每个用户的Session里存放大量数据的话,那么就很占用服务器大量的内存,进而致使服务器性能受到影响。
  可以使用数据库持久化session,分为物理数据库和内存数据库。物理数据库备份session,由于其性能原因,不推荐;内存数据库可以使用redis和memcached,这里介绍memcached的方法。
  MSM工作原理:
  a)Sticky Session(黏性) 模式下的工作原理:
  Tomcat本地Session为主Session,Memcached 中的Session为备Session。
  安装在Tomcat上的MSM使用本机内存保存Session,当一个请求执行完毕之后,如果对应的Session在本地不存在(即某用户的第一次请求),则将该Session复制一份至Memcached;当该Session的下一个请求到达时,会使用Tomcat的本地Session,请求处理结束之后,Session的变化会同步更新到 Memcached,保证数据一致。
  当集群中的一个Tomcat挂掉,下一次请求会被路由到其他Tomcat上。负责处理此此请求的Tomcat并不清楚Session信息,于是从Memcached查找该Session,更新该Session并将其保存至本机。此次请求结束,Session被修改,送回Memcached备份。
  b)Non-sticky Session (非黏性)模式下的工作原理(记住:多台tomcat集群或多个tomcat实例时需要选择Non-Sticky模式,即sticky="false"):
  Tomcat本地Session为中转Session,Memcached为主备Session。
  收到请求,加载备Session至本地容器,若备Session加载失败则从主Session加载;
  请求处理结束之后,Session的变化会同步更新到Memcached,并清除Tomcat本地Session。
  ------------------------------------------------------------------------------------------------------------
  废话不多说了,下面直接看nginx+memcached+tomcat实现session共享的集群操作记录::
  一、集群实验环境信息
  

主机            端口    开源软件  
192.168.1.118   80      nginx(nginx-1.8.1)
  
192.168.1.118   8081    tomcat1(版本为tomcat7)
  
192.168.1.118   8091    tomcat2
  
192.168.1.118   11211   memcached(memcached-1.4.34)
  
192.168.1.118   11212   memcached(memcached-1.4.34)
  

  
服务器系统均是centos6.8
  

  
我这里是在一台测试服务器(192.168.1.118/110.110.115.118)上操作的,即nginx、memcached、tomcat均是部署在同一台服务器上,只是为了测试。
  
如果在生产环境下,ngixn、tocmat、memcached应该是部署到不同的服务器上。
  

  
为什么在两个tomcat实例前要放一个nginx?
  
1)nginx可以作为两个tomcat的负载均衡,均衡两个tomat负载压力,负载均衡也可以使得客户端访问可以使用统一的url,如果没有nginx,那么访问tomcat1必须要用http://localhost:8081/,而访问tomcat2需要用http://localhost:8091/
  
2)nginx处理静态资源的性能比tomcat好很多
  

  实验拓扑图:
   DSC0000.png
  二、nginx安装
  

1)安装依赖包  
[iyunv@linux-node3 ~]# yum -y install gcc gcc-c++
  

  
2)安装pcre库
  
[iyunv@linux-node3 ~]# cd /usr/local/src/
  
[iyunv@linux-node3 src]# wget https://jaist.dl.sourceforge.net/project/pcre/pcre/8.37/pcre-8.37.tar.gz
  
[iyunv@linux-node3 src]# tar -zvxf pcre-8.37.tar.gz
  
[iyunv@linux-node3 src]# cd pcre-8.37
  
[iyunv@linux-node3 pcre-8.37]# ./configure && make && make install
  

  
3)安装zlib库
  
[iyunv@linux-node3 src]# wget http://www.zlib.net/zlib-1.2.11.tar.gz
  
[iyunv@linux-node3 src]# tar -zvxf zlib-1.2.11.tar.gz
  
[iyunv@linux-node3 zlib-1.2.11]# ./configure && make && make install
  

  
4)安装openssl
  
[iyunv@linux-node3 src]# wget http://www.openssl.org/source/openssl-1.0.1c.tar.gz
  
[iyunv@linux-node3 src]# tar -zvxf openssl-1.0.1c.tar.gz && cd openssl-1.0.1c && ./config && make && make install
  

  
5)安装nginx
  
特别注意要指定prce zlib openssl原码包位置
  
[iyunv@linux-node3 src]# wget http://nginx.org/download/nginx-1.8.1.tar.gz
  
[iyunv@linux-node3 src]# tar -zvxf nginx-1.8.1.tar.gz
  
[iyunv@linux-node3 src]# cd nginx-1.8.1
  
[iyunv@linux-node3 nginx-1.8.1]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.37 --with-zlib=/usr/local/src/zlib-1.2.11  --with-openssl=/usr/local/src/openssl-1.0.1c
  
[iyunv@linux-node3 nginx-1.8.1]# make && make install
  

  
6)安装成功后配置nginx
  
[iyunv@linux-node3 nginx-1.8.1]# vim /usr/local/nginx/conf/nginx.conf
  
#user  nobody;
  
worker_processes  8;
  

  
#error_log  logs/error.log;
  
#error_log  logs/error.log  notice;
  
#error_log  logs/error.log  info;
  

  
#pid        logs/nginx.pid;
  

  
worker_rlimit_nofile 65535;
  
events {
  use epoll;
  worker_connections  65535;
  
}
  

  
http {
  include       mime.types;
  default_type  application/octet-stream;
  charset utf-8;
  ######
  ## set access log format
  ######
  log_format  main  '$http_x_forwarded_for $remote_addr $remote_user [$time_local] "$request" '
  '$status $body_bytes_sent "$http_referer" '
  '"$http_user_agent" "$http_cookie" $host $request_time';
  

  #######
  ## http setting
  #######
  sendfile       on;
  tcp_nopush     on;
  tcp_nodelay    on;
  keepalive_timeout  65;
  fastcgi_connect_timeout 30000;
  fastcgi_send_timeout 30000;
  fastcgi_read_timeout 30000;
  fastcgi_buffer_size 256k;
  fastcgi_buffers 8 256k;
  fastcgi_busy_buffers_size 256k;
  fastcgi_temp_file_write_size 256k;
  fastcgi_intercept_errors on;
  

  ##cache##
  client_header_timeout 60s;
  client_body_timeout 60s;
  client_max_body_size 10m;
  client_body_buffer_size 1m;
  proxy_connect_timeout 5;
  proxy_read_timeout 60;
  proxy_send_timeout 5;
  proxy_buffer_size 64k;
  proxy_buffers 4 128k;
  proxy_busy_buffers_size 128k;
  proxy_temp_file_write_size 1m;
  proxy_temp_path /home/temp_dir;
  proxy_cache_path /home/cache levels=1:2 keys_zone=cache_one:200m inactive=1d max_size=30g;
  ##end##
  

  gzip  on;
  gzip_min_length  1k;
  gzip_buffers     4 16k;
  gzip_http_version 1.1;
  gzip_comp_level 9;
  gzip_types       text/plain application/x-javascript text/css application/xml text/javascript application/x-httpd-php;
  gzip_vary on;
  

  ## includes vhosts
  include vhosts/*.conf;
  
}
  

  
[iyunv@linux-node3 nginx-1.8.1]# cd /usr/local/nginx/conf/
  
[iyunv@linux-node3 conf]# mkdir vhosts
  
[iyunv@linux-node3 conf]# cd vhosts/
  
[iyunv@linux-node3 vhosts]# vim test.conf
  upstream tomcat-lb {
  server 127.0.0.1:8081;
  server 127.0.0.1:8091;
  }
  server {
  listen  80;
  server_name www.wangshibo.com;
  location / {
  proxy_pass http://tomcat-lb;
  proxy_set_header  X-Real-IP $remote_addr;
  proxy_set_header  REMOTE-HOST $remote_addr;
  proxy_set_header  Host $host;
  proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
  }
  location ~ .*\.(gif|jpg|png|htm|html|css|ico|flv|swf)(.*) {
  proxy_pass http://tomcat-lb;
  proxy_redirect off;
  proxy_set_header Host $host;
  proxy_cache cache_one;
  proxy_cache_valid 200 302 1h;
  proxy_cache_valid 301 1d;
  proxy_cache_valid any 10m;
  expires 30d;
  proxy_cache_key $host$uri$is_args$args;
  }
  
}
  

  

  三、memcached安装
  

[iyunv@linux-node3 src]# yum -y install libevent libevent-devel  
[iyunv@linux-node3 src]# wget http://memcached.org/files/memcached-1.4.34.tar.gz
  
[iyunv@linux-node3 src]# tar -zvxf memcached-1.4.34.tar.gz
  
[iyunv@linux-node3 src]# cd memcached-1.4.34
  
[iyunv@linux-node3 memcached-1.4.34]# ./configure --prefix=/usr/local/memcached
  
[iyunv@linux-node3 memcached-1.4.34]# make && make install
  
启动memcached,端口11211可以根据自己需要修改不同端口
  
[iyunv@linux-node3 memcached-1.4.34]# /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11211 -c 1024 -P /var/lib/memcached.11211pid
  
[iyunv@linux-node3 memcached-1.4.34]# /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11212 -c 1024 -P /var/lib/memcached.11212pid
  
[iyunv@linux-node3 memcached-1.4.34]# ps -ef|grep memcached
  
root     44007     1  0 14:21 ?        00:00:00 /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11211 -c 1024 -P /var/lib/memcached.11211pid
  
root     44018     1  0 14:21 ?        00:00:00 /usr/local/memcached/bin/memcached -d -m 512 -u root -p 11212 -c 1024 -P /var/lib/memcached.11212pid
  
root     44038 21647  0 14:22 pts/2    00:00:00 grep  memcached
  
测试一下memcached连接,如下说明成功(输入quit退出)
  
[iyunv@linux-node3 ~]# telnet 192.168.1.118 11211
  
Trying 192.168.1.118...
  
Connected to 192.168.1.118.
  
Escape character is '^]'.
  

  
[iyunv@linux-node3 ~]# telnet 192.168.1.118 11212
  
Trying 192.168.1.118...
  
Connected to 192.168.1.118.
  
Escape character is '^]'.
  

  四、安装jdk
  

查看CentOS自带JDK是否已安装  
[iyunv@linux-node3 ~]# yum list installed |grep java
  
[iyunv@linux-node3 ~]#
  

  
若有自带安装的JDK,如何卸载CentOS系统自带Java环境?
  
卸载JDK相关文件输入:yum -y remove java-1.7.0-openjdk*。
  
卸载tzdata-java输入:yum -y remove tzdata-java.noarch。
  
当结果显示为Complete!即卸载完毕。
  
注:"*"表示卸载掉java 1.7.0的所有openjdk相关文件。
  

  
查看yum库中的java安装包
  
[iyunv@linux-node3 ~]# yum -y list java*
  
........
  
java-1.5.0-gcj.x86_64                                                      1.5.0.0-29.1.el6                                             base
  
java-1.5.0-gcj-devel.x86_64                                                1.5.0.0-29.1.el6                                             base
  
java-1.5.0-gcj-javadoc.x86_64                                              1.5.0.0-29.1.el6                                             base
  
java-1.5.0-gcj-src.x86_64                                                  1.5.0.0-29.1.el6                                             base
  
java-1.6.0-openjdk.x86_64                                                  1:1.6.0.41-1.13.13.1.el6_8                                   updates
  
java-1.6.0-openjdk-demo.x86_64                                             1:1.6.0.41-1.13.13.1.el6_8                                   updates
  
java-1.6.0-openjdk-devel.x86_64                                            1:1.6.0.41-1.13.13.1.el6_8                                   updates
  
java-1.6.0-openjdk-javadoc.x86_64                                          1:1.6.0.41-1.13.13.1.el6_8                                   updates
  
java-1.6.0-openjdk-src.x86_64                                              1:1.6.0.41-1.13.13.1.el6_8                                   updates
  
java-1.7.0-openjdk.x86_64                                                  1:1.7.0.131-2.6.9.0.el6_8                                    updates
  
java-1.7.0-openjdk-demo.x86_64                                             1:1.7.0.131-2.6.9.0.el6_8                                    updates
  
java-1.7.0-openjdk-devel.x86_64                                            1:1.7.0.131-2.6.9.0.el6_8                                    updates
  
java-1.7.0-openjdk-javadoc.noarch                                          1:1.7.0.131-2.6.9.0.el6_8                                    updates
  
java-1.7.0-openjdk-src.x86_64                                              1:1.7.0.131-2.6.9.0.el6_8                                    updates
  
java-1.8.0-openjdk.x86_64                                                  1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-debug.x86_64                                            1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-demo.x86_64                                             1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-demo-debug.x86_64                                       1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-devel.x86_64                                            1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-devel-debug.x86_64                                      1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-headless.x86_64                                         1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-headless-debug.x86_64                                   1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-javadoc.noarch                                          1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-javadoc-debug.noarch                                    1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-src.x86_64                                              1:1.8.0.121-0.b13.el6_8                                      updates
  
java-1.8.0-openjdk-src-debug.x86_64                                        1:1.8.0.121-0.b13.el6_8                                      updates
  
........
  

  
以yum库中java-1.7.0为例
  
注:"*"表示将java-1.7.0的所有相关Java程序都安装上。
  
[iyunv@linux-node3 ~]# yum -y install java-1.7.0-openjdk*
  

  
查看刚安装的Java版本信息。
  
输入:java -version 可查看Java版本;
  
输入:javac 可查看Java的编译器命令用法
  

  
[iyunv@linux-node3 ~]# java -version
  
java version "1.7.0_131"
  
OpenJDK Runtime Environment (rhel-2.6.9.0.el6_8-x86_64 u131-b00)
  
OpenJDK 64-Bit Server VM (build 24.131-b00, mixed mode)
  

  
[iyunv@linux-node3 ~]# which java
  
/usr/bin/java
  
[iyunv@linux-node3 ~]# ll /usr/bin/java
  
lrwxrwxrwx. 1 root root 22 Feb 14 22:25 /usr/bin/java -> /etc/alternatives/java
  
[iyunv@linux-node3 ~]# ll /etc/alternatives/java
  
lrwxrwxrwx. 1 root root 46 Feb 14 22:25 /etc/alternatives/java -> /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
  
[iyunv@linux-node3 ~]# cd /usr/lib/jvm
  
[iyunv@linux-node3 jvm]# ll
  
total 4
  
lrwxrwxrwx. 1 root root   26 Feb 14 22:25 java -> /etc/alternatives/java_sdk
  
lrwxrwxrwx. 1 root root   32 Feb 14 22:25 java-1.7.0 -> /etc/alternatives/java_sdk_1.7.0
  
drwxr-xr-x. 9 root root 4096 Feb 14 22:25 java-1.7.0-openjdk-1.7.0.131.x86_64
  
lrwxrwxrwx. 1 root root   35 Feb 14 22:25 java-1.7.0-openjdk.x86_64 -> java-1.7.0-openjdk-1.7.0.131.x86_64
  
lrwxrwxrwx. 1 root root   34 Feb 14 22:25 java-openjdk -> /etc/alternatives/java_sdk_openjdk
  
lrwxrwxrwx. 1 root root   21 Feb 14 22:25 jre -> /etc/alternatives/jre
  
lrwxrwxrwx. 1 root root   27 Feb 14 22:25 jre-1.7.0 -> /etc/alternatives/jre_1.7.0
  
lrwxrwxrwx. 1 root root   39 Feb 14 22:25 jre-1.7.0-openjdk.x86_64 -> java-1.7.0-openjdk-1.7.0.131.x86_64/jre
  
lrwxrwxrwx. 1 root root   29 Feb 14 22:25 jre-openjdk -> /etc/alternatives/jre_openjdk
  

  
由上可知,java的home目录是/usr/lib/jvm/java-1.7.0-openjdk.x86_64
  

  
设置java的环境变量
  
[iyunv@115 ~]# vim /etc/profile
  
.......
  
export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk.x86_64

  
export>  
export PATH=$PATH:$JAVA_HOME/bin
  

  
[iyunv@linux-node3 jvm]# source /etc/profile
  

  

  五、安装与配置tomcat
  1)安装tomcat
[iyunv@linux-node3 src]# wget http://apache.fayea.com/tomcat/tomcat-7/v7.0.75/bin/apache-tomcat-7.0.75.tar.gz

[iyunv@linux-node3 src]# tar -zvxf apache-tomcat-7.0.75.tar.gz

[iyunv@linux-node3 src]# mv apache-tomcat-7.0.75 /usr/local/tomcat1

  2)添加memcached和msm(Memcached_Session_Manager)的依赖jar包,如下:
  

asm-3.2.jar  
kryo-1.03.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
  
reflectasm-0.9.jar
  
spymemcached-2.7.3.jar
  

  注意:memcached-session-manager-tc7-1.7.0.jar中的tc7为tomcat的版本号。一定要注意:不同版本号的tomcat,对应的msm包也不同。此处为tomcat7的jar包
  上面依赖包下载地址:https://pan.baidu.com/s/1eRRncpO
  提取密码:y56i
  ---------------------------------------------------------------------------------------------------------------------------------
  msm相关版本的jar包下载地址:http://repo1.maven.org/maven2/de/javakaffee/msm/
  spymemcached相关版本下载地址:http://repo1.maven.org/maven2/net/spy/spymemcached
  ---------------------------------------------------------------------------------------------------------------------------------
  把依赖包下载后全部上传到tomcat1和tomcat2的安装路径下的lib/ 目录下
  3)配置tomcat
  

这里我的tomcat1的服务端口用的是8081,所以需要将tomcat1的server.xml中默认的8080改成8081  
[iyunv@linux-node3 ~]# cd /usr/local/tomcat1/conf/
  
[iyunv@linux-node3 conf]# cp server.xml server.xml.bak
  
[iyunv@linux-node3 conf]# vim server.xml
  
.......
  <Connector port="8081" protocol="HTTP/1.1"
  connectionTimeout="20000"
  redirectPort="8443" />
  
......
  <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat1">
  
......
  

  
注意:启有Engine标签中的jvmRoute属性,启用的目的就是为了区分session是在哪个节点上生成的
  
这个Engine name是非必选 ,只有选择了sticky模式才加入jvmRoute属性。这里为了实验效果,我们暂且选择这个设置项。
  
不同的tomcat实例jvmRoute取值不能相同。
  
例:8081端口的tomcat实例jvmRoute=tomcat1,8091端口的tomcat实例jvmRoute=tomcat2
  

  接下来进行序列化tomcat配置,修改conf/context.xml文件。
  序列化tomcat配置的方法有很多种:java默认序列化tomcat配置、javolution序列化tomcat配置、xstream序列化tomcat配置、flexjson序列化tomcat配置和kryo序列化tomcat配置。官网介绍说 使用kryo 序列化tomcat的效率最高,所以这里只介绍kryo序列化。
  在No-Stick模式和Stick模式下context.xml文件配置也有所不同(一般用的是No-Stick模式)
  a)No-Stick模式(记住:多台tomcat集群或多个tomcat实例时 需要选择Non-Sticky模式,即sticky="false")
  

[iyunv@linux-node3 ~]# cd /usr/local/tomcat1/conf/  
[iyunv@linux-node3 conf]# cp context.xml context.xml.bak
  
[iyunv@linux-node3 conf]# vim context.xml   //在<Context>和</Context>之间添加下面内容

  <Manager>  memcachedNodes="n1:192.168.1.118:11211 n2:192.168.1.118:11212"
  lockingMode="auto"
  sticky="false"
  requestUriIgnorePattern= ".*\.(png|gif|jpg|css|js)$"
  sessionBackupAsync= "true"
  sessionBackupTimeout= "1800000"
  copyCollectionsForSerialization="true"
  transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
  />
  

  
然后将congtext.xml文件拷贝到tomcat2的相同路径下
  

  b)Stick模式。故障转移配置节点(failoverNodes),不能使用在non-sticky sessions模式,多个使用空格或逗号分开,配置某个节点为备份节点,当其他节点都不可用时才会存储到备份节点,适用于sticky模式(即一台tomcat,多台memcached)。
  

[iyunv@linux-node3 ~]# cd /usr/local/tomcat1/conf/  
[iyunv@linux-node3 conf]# cp context.xml context.xml.bak
  
[iyunv@linux-node3 conf]# vim context.xml   //在<Context>和</Context>之间添加下面内容
  
<Manager>  memcachedNodes="n1:192.168.1.118:11211 n2:192.168.1.118:11212"
  sticky="true"
  failoverNodes="n2"
  requestUriIgnorePattern=".*\.(png|gif|jpg|css|js|swf|flv)$"
  transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
  copyCollectionsForSerialization="true"
  />
  
然后将congtext.xml文件拷贝到tomcat2的相同路径下,并将failoverNodes后面的参数改为n1
  

  --------------------------------------------------------------------------------------------------------------
  注意:这里实验环境是开启了两个memcached端口,如果开启一个memcached端口也可以的,比如只开启11211端口,则No-Stick模式的配置如下:
  

   <Manager>memcachedNodes="n1:192.168.1.118:11211"
  sticky="false"
  requestUriIgnorePattern= ".*\.(png|gif|jpg|css|js)$"
  sessionBackupAsync= "true"
  sessionBackupTimeout= "1800000"
  copyCollectionsForSerialization="false"
  transcoderFactoryClass="de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory"
  />
  

  --------------------------------------------------------------------------------------------------------------
  六、配置tomcat集群
  

[iyunv@linux-node3 ~]# cd /usr/local/  
[iyunv@linux-node3 local]# cp -r tomcat1 tomcat2
  

  
修改server.xml文件里的相应端口,防止tomcat1和tomcat2端口冲突
  
[iyunv@linux-node3 local]# vim tomcat2/conf/server.xml
  
.......
  <Server port="8006" shutdown="SHUTDOWN">       //把8005修改成8006
  
......
  <Connector port="8091" protocol="HTTP/1.1"     //把8081修改成8091根据自己来配置,修改后的8090与nginx配置一样
  connectionTimeout="20000"
  redirectPort="8443" />
  
.....
  <Connector port="8010" protocol="AJP/1.3" redirectPort="8443" />    //把8009修改成8010
  
.....
  <Engine name="Catalina" defaultHost="localhost" jvmRoute="tomcat2">   //把tomcat1改为tomcat2
  

  七、启动tomcat集群
  

[iyunv@linux-node3 ~]# /usr/local/tomcat1/bin/startup.sh  
Using CATALINA_BASE:   /usr/local/tomcat1
  
Using CATALINA_HOME:   /usr/local/tomcat1
  
Using CATALINA_TMPDIR: /usr/local/tomcat1/temp
  
Using JRE_HOME:        /usr/lib/jvm/java-1.7.0-openjdk.x86_64

  
Using>  
Tomcat started.
  
[iyunv@linux-node3 ~]# /usr/local/tomcat2/bin/startup.sh
  
Using CATALINA_BASE:   /usr/local/tomcat2
  
Using CATALINA_HOME:   /usr/local/tomcat2
  
Using CATALINA_TMPDIR: /usr/local/tomcat2/temp
  
Using JRE_HOME:        /usr/lib/jvm/java-1.7.0-openjdk.x86_64

  
Using>  
Tomcat started.
  
[iyunv@linux-node3 ~]# ps -ef|grep tomcat
  
root     29224     1 49 02:21 pts/2    00:00:04 /usr/lib/jvm/java-1.7.0-openjdk.x86_64/bin/java -Djava.util.logging.config.file=/usr/local/tomcat1/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -classpath /usr/local/tomcat1/bin/bootstrap.jar:/usr/local/tomcat1/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat1 -Dcatalina.home=/usr/local/tomcat1 -Djava.io.tmpdir=/usr/local/tomcat1/temp org.apache.catalina.startup.Bootstrap start
  
root     29250     1 87 02:21 pts/2    00:00:04 /usr/lib/jvm/java-1.7.0-openjdk.x86_64/bin/java -Djava.util.logging.config.file=/usr/local/tomcat2/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djdk.tls.ephemeralDHKeySize=2048 -Djava.protocol.handler.pkgs=org.apache.catalina.webresources -classpath /usr/local/tomcat2/bin/bootstrap.jar:/usr/local/tomcat2/bin/tomcat-juli.jar -Dcatalina.base=/usr/local/tomcat2 -Dcatalina.home=/usr/local/tomcat2 -Djava.io.tmpdir=/usr/local/tomcat2/temp org.apache.catalina.startup.Bootstrap start
  
root     29278 29157  0 02:21 pts/2    00:00:00 grep tomcat
  
[iyunv@linux-node3 ~]# lsof -i:8080

  
COMMAND   PID USER   FD   TYPE DEVICE>  
java    29224 root   55u  IPv6 383017      0t0  TCP *:webcache (LISTEN)
  
[iyunv@linux-node3 ~]# lsof -i:8090

  
COMMAND   PID USER   FD   TYPE DEVICE>  
java    29250 root   55u  IPv6 383056      0t0  TCP *:8090 (LISTEN)
  

  

  八、启动nginx
  

[iyunv@linux-node3 ~]# /usr/local/nginx/sbin/nginx  
[iyunv@linux-node3 ~]# ps -ef|grep nginx
  
root     29282     1  0 02:23 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginx
  
nobody   29283 29282  2 02:23 ?        00:00:00 nginx: worker process
  
nobody   29284 29282  1 02:23 ?        00:00:00 nginx: worker process
  
nobody   29285 29282  2 02:23 ?        00:00:00 nginx: worker process
  
nobody   29286 29282  2 02:23 ?        00:00:00 nginx: worker process
  
nobody   29287 29282  1 02:23 ?        00:00:00 nginx: worker process
  
nobody   29288 29282  2 02:23 ?        00:00:00 nginx: worker process
  
nobody   29289 29282  3 02:23 ?        00:00:00 nginx: worker process
  
nobody   29290 29282  1 02:23 ?        00:00:00 nginx: worker process
  
nobody   29291 29282  0 02:23 ?        00:00:00 nginx: cache manager process
  
nobody   29292 29282  0 02:23 ?        00:00:00 nginx: cache loader process
  
root     29294 29157  0 02:23 pts/2    00:00:00 grep nginx
  
[iyunv@linux-node3 ~]# lsof -i:80

  
COMMAND   PID   USER   FD   TYPE DEVICE>  
nginx   29282   root    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29283 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29284 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29285 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29286 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29287 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29288 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29289 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  
nginx   29290 nobody    6u  IPv4 383819      0t0  TCP *:http (LISTEN)
  

  

  九、测试session是否共享
  

[iyunv@linux-node3 ~]# cd /usr/local/tomcat1/webapps/ROOT/  
[iyunv@linux-node3 ROOT]# mkdir tomcat-session
  
[iyunv@linux-node3 ROOT]# cd tomcat-session/
  
[iyunv@linux-node3 tomcat-session]# vim index.jsp
  
<%@ page contentType="text/html; " %>
  
<%@ page import="java.util.*" %>
  
<html><head><title>Cluster Test</title></head>
  
<body>
  
<%
  //HttpSession session = request.getSession(true);
  System.out.println(session.getId());

  out.println("<br> SESSION>  
%>
  
</body>
  

  

  
将上面的tomcat-session拷贝到tomcat2的同路径下
  
[iyunv@linux-node3 tomcat-session]# cp -r ../tomcat-session /usr/local/tomcat2/webapps/ROOT/
  

  本机绑定hosts进行访问测试:
  110.110.115.118 www.wangshibo.com
  测试步骤(服务器上iptables防火墙开通相应web端口)

  a)访问http://www.wangshibo.com/tomcat-session,显示出Session>
  b)按F5刷新多次,看看Session>
  c)关闭其中一个tomcat实例,观察页面的Session>  响应速度:
  MSM在Session管理时,Tomcat中会保持本地Session,往Memcached中的同步是异步完成的,所以访问速度和普通模式没什么区别。
  唯一有区别的是,tomcat实例关闭后的首次访问时,响应速度会变慢,但是持续一小段时间后续访问速度恢复正常。
  -------------------------------------------------扩展------------------------------------------------------
  以上介绍了nginx+tomcat+memcached实现session共享集群的操作记录,下面再追加一些需要注意的东西:
  

上面采用了效率最高的kryo序列化tomcat配置,当然还有其他四种序列化tomcat的配置方法,分别是:  
a)java默认序列化tomcat配置,conf/context.xml添加:

  
<Manager>  memcachedNodes="n1:192.168.100.208:11211 n2:192.168.100.208:11311"
  lockingMode="auto"
  sticky="false"
  requestUriIgnorePattern= ".*\.(png|gif|jpg|css|js)$"
  sessionBackupAsync= "false"
  sessionBackupTimeout= "100"
  transcoderFactoryClass="de.javakaffee.web.msm.JavaSerializationTranscoderFactory"
  />
  

  
lib下需要增加的jar包:
  
spymemcached-2.10.3.jar
  
memcached-session-manager-1.7.0.jar
  
memcached-session-manager-tc7-1.7.0.jar
  

  
b)javolution序列化tomcat配置,conf/context.xml添加:

  
<Manager>  memcachedNodes="n1:192.168.100.208:11211 n2:192.168.100.208:11311"
  lockingMode="auto"
  sticky="false"
  requestUriIgnorePattern= ".*\.(png|gif|jpg|css|js)$"
  sessionBackupAsync= "false"
  sessionBackupTimeout= "100"
  copyCollectionsForSerialization="true"
  transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
  />
  

  
lib下需要增加的jar包:
  
msm-javolution-serializer-cglib-1.3.0.jar
  
msm-javolution-serializer-jodatime-1.3.0.jar
  
spymemcached-2.10.3.jar
  
javolution-5.4.3.1.jar
  
msm-javolution-serializer-1.7.0.jar
  
memcached-session-manager-1.7.0.jar
  
memcached-session-manager-tc7-1.7.0.jar
  

  
c)xstream序列化tomcat配置,conf/context.xml添加:

  
<Manager>  memcachedNodes="n1:192.168.100.208:11211 n2:192.168.100.208:11311"
  lockingMode="auto"
  sticky="false"
  requestUriIgnorePattern= ".*\.(png|gif|jpg|css|js)$"
  sessionBackupAsync= "false"
  sessionBackupTimeout= "100"
  transcoderFactoryClass="de.javakaffee.web.msm.serializer.xstream.XStreamTranscoderFactory"
  />
  

  
lib下需要增加的jar包:
  
xmlpull-1.1.3.1.jar
  
xpp3_min-1.1.4c.jar
  
xstream-1.4.6.jar
  
msm-xstream-serializer-1.7.0.jar
  
spymemcached-2.10.3.jar
  
memcached-session-manager-1.7.0.jar
  
memcached-session-manager-tc7-1.7.0.jar
  

  
d)flexjson序列化tomcat配置,conf/context.xml添加:

  
<Manager>  memcachedNodes="n1:192.168.100.208:11211 n2:192.168.100.208:11311"
  lockingMode="auto"
  sticky="false"
  requestUriIgnorePattern= ".*\.(png|gif|jpg|css|js)$"
  sessionBackupAsync= "false"
  sessionBackupTimeout= "100"
  transcoderFactoryClass="de.javakaffee.web.msm.serializer.json.JSONTranscoderFactory"
  />
  

  
lib增加jar包
  
flexjson-3.1.jar
  
msm-flexjson-serializer-1.7.0.jar
  
spymemcached-2.10.3.jar
  
memcached-session-manager-1.7.0.jar
  
memcached-session-manager-tc7-1.7.0.jar
  

  

  序列化tomcat配置中有关Manager各参数说明:
  

a)className  
这个是必选项。可配置为:
  
de.javakaffee.web.msm.MemcachedBackupSessionManager
  
或者
  
de.javakaffee.web.msm.DummyMemcachedBackupSessionManager
  
其中DummyMemcachedBackupSessionManager可用于测试环境,不需要真实存在memcached
  
b)memcachedNodes
  
这个是必选项。memcached的节点信息(多个节点使用空格或逗号分开),格式如:
  
memcachedNodes="n1:app01:11211,n2:app02:11211"。
  
c)failoverNodes
  
这个是可选项,不能使用在non-sticky sessions模式。
  
故障转移配置节点,多个使用空格或逗号分开,配置某个节点为备份节点,当其他节点都不可用时才会存储到备份节点,官方建议配置为和tomcat同服务器的节点。
  
理由如下:
  
假如有两台服务器m1,m2,其中m1部署tomcat和memcached节点n1,m2部署memcached节点n2。
  
如果配置tomcat的failoverNodes值为n2或者不配置,则当服务器m1挂掉后n1和tomcat中保存的session会丢失,而n2中未保存或者只保存了部分session,这就造成
  
部分用户状态丢失;
  
如果配置tomcat的failoverNodes值为n1,则当m1挂掉后因为n2中保存了所有的session,所以重启tomcat的时候用户状态不会丢失。
  
为什么n2中保存了所有的session? 因为failoverNodes配置的值是n1,只有当n2节点不可用时才会把session存储到n1,所以这个时候n1中是没有保存任何session的。
  

  
d)lockingMode
  
这个是可选项,默认none,只对non-sticky有效。
  
当配置成node时,表示从来不加锁
  
当配置成all时,表示当请求时对Session锁定,直到请求结束
  
当配置成auto时,表示对只读的request不加锁,对非只读的request加锁
  

  
e)requestUriIgnorePattern
  
这个是可选项,制定忽略那些请求的session操作,一般制定静态资源如css,js一类的。
  

  
f)sessionBackupAsync
  
这个是可选项,默认true,是否异步的方式存储到memcached。
  

  
j)sessionBackupTimeout
  
这个是可选项,默认100毫秒,异步存储session的超时时间。即web工程对session的修改更新到memcache上的时间。
  

  
h)copyCollectionsForSerialization
  
这个是可选项,默认false。
  

  
i)transcoderFactoryClass
  
这个是可选项,默认值de.javakaffee.web.msm.JavaSerializationTranscoderFactory,制定序列化和反序列化数据到memcached的工厂类。
  

  
j)operationTimeout
  
这个是可选项,默认1000毫秒,memcached的操作超时时间。
  

  
k)backupThreadCount
  
这个是可选项,默认是cpu核心数,异步存储session的线程数。
  

  
l)storageKeyPrefix
  
这个是可选项,默认值webappVersion,存储到memcached的前缀,主要是为了区分多个webapp共享session的情况。可选值:静态字符串、host、context、webappVersion,多个使用逗号分割。 、
  

  
m)sessionAttributeFilter
  
这个是可选项,通过正则表达式确定那些session中的属性应该被存储到memcached。例子如:sessionAttributeFilter="^(userName|sessionHistory)$"。
  

  再说下stick和non-stick的工作流程:
  

Sticky 模式:  
tomcat session为主session,memcached为备session。Request请求到来时,从memcached加载备session到tomcat (仅当tomcat jvmroute发生变化时,否则直接取tomcat session);Request请求结束时,将tomcat session更新至memcached,以达到主备同步之目的。
  

  
Non-Sticky模式:
  
tomcat session为中转session,memcached1为主session,memcached2为备session。Request请求到来时,从memcached 2加载备session到tomcat,(当容器中还是没有session则从memcached1加载主session到tomcat, 这种情况是只有一个memcached节点,或者有memcached1出错时), Request请求结束时,将tomcat session更新至主memcached1和备memcached2,并且清除tomcat session 。以达到主备同步之目的。 多台tomcat集群时 需要选择Non-Sticky模式,即sticky="false"
  

  

  需要清除的是:
  

1)如果部署后,发现调试不成功,即session不共享,一般都是由于memcached-session-manager-1.7.0.jar、memcached-session-manager-tc7-1.7.0.jar和msm-kryo-serializer-1.7.0.jar这三个jar包出问题。所以版本也很重要。  
2)服务器之间的时间戳一致也非常重要,因为时间不一致将直接导致session过期。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-428278-1-1.html 上篇帖子: Tomcat从内存、并发、缓存方面优化方法 下篇帖子: Tomcat之jvm及连接数设置
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表