nginx+tomcat+msm實現seesion共享

說明

上一章節 nginx+tomcat+redis負載均衡,實現session共享,本次我們使用另一種方式來實現session會話共享,以及實現一套線上運行的環境,

重定提示

本次將重點列於 memcache、ansible 以及keepalived功能的實現上

實驗環境

jdk:  8u141
tomcat:  8.5.30  * 2 
nginx:  1.12.1    * 2
keepalived:  yum
memcache:    yum   * 2   
ansible: yum
IP地址: 192.168.172.129-134   總六臺  第一次手動加簡單的ansible,第二次直接用ansible其它的(學習中)     

軟件下載:
memcached-session-manager

需要下載的包[memcached-session-manager-tc8-2.3.0、spymemcached-2.12.3、memcached-session-manager-2.3.0、msm-javolution-serializer-2.1.1,javolution-5.4.3.1] 

java 需要下載的包jdk-8u141-linux-x64

拓撲圖

nginx+tomcat+msm實現seesion共享

拓撲-實驗說明

  1、keepalived實現Nginx負載均衡高可用, keepalived實現服務高可用將在本章節實現它;
  2、nginx反向代理tomcat服務器,我們這裏反代將不在使用ip地址的方式,直接使用主機名來實現,當tomcatA掛掉之後直接上線tomcatB替代但主機名不變,使用docker network方式;
  3、session保持我們將直接使用memcacehd的方式來實現,本章將重點來強調它,以及最後與redis的對比;
  4、有木有招人的收了我吧,名稱即我Q可隨時加我,北京地區。
  5、如果想實現數據庫的預熱功能以及KEY對應memcached的功能,那就需要跟開發對接一下了。
  6、兩兩安裝,安裝一:使用ansible+腳本方式,安裝二:使用ansible+playbooks方式

memcache說明

memcache特點

  Memcached是一個開源的,高性能的內存綬存軟件,memcached作爲高速運行的分佈式緩存服務器,具有以下的特點。

  • 1、完全基於內存緩存
  • 2、節點是完全獨立的
  • 3、緩存的數據都是以kv的形式存在
  • 4、無持久化機制,一旦重啓服務器,這部分數據將全部丟失
  • 5、當內存緩存的數據容量超過設定的內存值時,就自動使用Lru算法刪除過期的kv對
  • 6、memcache會對設定的內存進行分塊,再把塊分組,然後提供服務
  • 7、cs架構
  • 8、memcached不互相通信的分佈式,實現爲一致性Hash取模, ( 3臺mem每次存儲只存一臺 N%3,取也是一樣 )

memcace教程
  Memcached簡潔而強大。它的簡潔設計便於快速開發,減輕開發難度,解決了大數據量緩存的很多問題。它的API兼容大部分流行的開發語言。
  一般的使用目的是,通過緩存數據庫查詢結果,減少數據庫訪問次數,以提高動態Web應用的速度、提高可擴展性。
nginx+tomcat+msm實現seesion共享

相關提問

1、Memcached是什麼,有什麼作用?
  Memcached是一個開源的,高性能的內存綬存軟件
  作用:通過事先規劃好的內存空間中臨時緩存數據庫中的各類數據,以達到減輕數據庫的直接併發訪問,從而提升數據庫的訪問性能。

2、memcache內存管理機制
  memcache利用slab allocation機制來分配和管理內存,大概原理,先按照預定的大小,將分配memcache的內存分割成特定長度的內存塊,再將塊分組,這些內存塊不會釋放,可以重複利用。
  Slab Allocator的缺點: 由於分配的是固定的長度,因爲無法有效的利用分配內存

3、memcache與redis有哪些區別
  數據類型:redis比memcache支持更多的數據類型,數據特性,如set list
  性能:memcache是完全基於內存的,而redis是支持持久化的 redis的緩存是比不上memcached的, 但memcached重啓之後數據就會完全丟失
  持久化: memcache一旦重啓,數據將全部丟失,redis有多種機制比如,主從,哨兵+主從,集羣的方式

4、Memcached服務分佈式集羣如何實現?
  Memcached集羣和web服務集羣是不一樣的,所有Memcached的數據總和纔是數據庫的數據。每臺Memcached都是部分數據。

MSM工作原理

  session保持的方式:在Tomcat實現負載均衡後,客戶端的請求會被調度至不同的服務器,session信息往往保存在其中一臺服務器的內存中,若之後的請求被調度至其他的服務器上,則客戶端無法訪問到之前的session信息。解決這一問題的方式有3種:

  session綁定:在調度時,將同一個客戶端的請求始終調度至同一臺服務器;可以在前端的代理服務器上配置相應的參數實現,但是這種方式會影響負載均衡的效果,並且其中的一臺服務器故障了,其上的session信息也會全部丟失。

  session複製:將多臺服務器上的session信息實時進行同步;通過同步session實現,即每一個會話的session信息存在於所有的服務器上,這個不適用於大型的集羣環境

  session服務器,將所有服務器上的session信息都存放至session服務器;將session信息集中存放至一臺專用的服務器上,服務器在處理請求時會首先將session信息從memcache同步至本地,然後進行處理

  粘性模式(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備份。

  非黏性模式:Tomcat本地Session爲中轉Session,Memcached爲主備Session;收到請求,加載備Session至本地容器,若備Session加載失敗則從主Session加載;請求處理結束之後,Session的變化會同步更新到Memcached,並清除Tomcat本地Session

ansible+腳本安裝

安裝方式一: ansible+腳本

1.1、IP地址分配說明

nginx+tomcat+msm實現seesion共享

1.2、機器互信

nginx2上操作
yum -y install ansible

# Host ]# vim /etc/ansible/hosts 最後添加所有主機
[all]
192.168.175.129    虛機問題 地址從  129 改爲 125
192.168.175.130
192.168.175.131
192.168.175.132
192.168.175.133
192.168.175.134

[nginx]
192.168.175.129
192.168.175.130

[tomcat]
192.168.175.131
192.168.175.132

[mem]
192.168.175.133
192.168.175.134

# 直接免交互輸入
Host ]# ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa  
Host]#  cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
Host]#  scp ~/.ssh/authorized_keys [email protected]:/root/.ssh/

進行測試
Host]# ansible all -a date
192.168.175.129 | SUCCESS | rc=0 >>
2018年 05月 05日 星期六 23:40:34 CST
.......  成功

1.3、nginx安裝

Host ]# ansible nginx -m copy -a  "src=nginx dest=/tmp"
192.168.175.129 | SUCCESS => {
    "changed": true, 
    "dest": "/tmp/", 
    "src": "/root/nginx"
}
....

mkdir]# mkdir nginx  # 安裝目錄以及軟件都放至這個目錄下
需要下載的軟件包: 

nginx+tomcat+msm實現seesion共享

nginx]# cat install.sh 
#!/bin/bash
#
#   Name: nginx 安裝
#   Version Number:1.01
#   Language:bash shell  
#   Date:2018年05月05日 23:09:21
#   Author:xiong

filepath=$(cd $(dirname "$0");pwd)
nginx_version="1.13.5"

yum -y install gcc gcc-c++ install gd gd-devel perl-ExtUtils-Embed wget unzip tar make 
cd ${filepath}
tar xf nginx-${nginx_version}.tar.gz
tar xf openssl-1.1.0h.tar.gz
unzip pcre-8.42.zip

# 配置nginx,爲了以後便於理解,分開搞
groupadd -g 1000 nginx && useradd -g 1000 -u 1000 nginx 
cd ${filepath}/nginx-${nginx_version} 
./configure --prefix=/usr/local/nginx  --user=nginx --with-select_module --with-http_ssl_module --with-http_realip_module --with-http_image_filter_module --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_auth_request_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_perl_module --with-stream --with-stream_ssl_module --with-stream_realip_module --with-pcre=${filepath}/pcre-8.42 --with-openssl=${filepath}/openssl-1.1.0h
cd ${filepath}/nginx-${nginx_version}
make && make install 
chown nginx.nginx /usr/local/nginx -R 
echo "export PATH=/usr/local/nginx/sbin:\$PATH" >> /etc/profile.d/nginx.sh
source /etc/profile.d/nginx.sh
cd ../

cp -i nginx /etc/init.d
rm -rf /etc/init.d/nginx
chmod +x /etc/init.d/nginx
/etc/init.d/nginx start

啓動腳本
nginx]# cat nginx
#!/bin/sh
#
# nginx - this script starts and stops the nginx daemon
#
# chkconfig:   - 85 15
# description:  Nginx is an HTTP(S) server, HTTP(S) reverse \
#               proxy and IMAP/POP3 proxy server
# processname: nginx
# config:      /usr/local/nginx/conf/nginx.conf

# Source function library.
. /etc/rc.d/init.d/functions

# Source networking configuration.
. /etc/sysconfig/network

Nginx_path="/usr/local/nginx"
Nginx_conf=${Nginx_path}/conf/nginx.conf
Nginx_bin=${Nginx_path}/sbin/nginx

status(){
    /usr/bin/ps -ef | grep nginx | grep master &>/dev/null
    [ $? -eq 0 ] && echo "Nginx 正在運行" || echo "Nginx 已關閉"
}

start(){
    status
    ${Nginx_bin} -c ${Nginx_conf}
    [ $? -eq 0 ] && echo "Nginx 啓動完成" || echo "Nginx 啓動失敗" ${Nginx_bin} -t
}

stop(){
    status
    ${Nginx_bin} -s stop
    [ $? -eq 0 ] && echo "Nginx 已關閉" || echo "Nginx關閉失敗,請手動kill進程" ps -ef | grep nginx
}

reload(){
    ${Nginx_bin} -s reload
}

restart(){
    stop
    start
}

case $1 in
start)
    start ;;
stop)
    stop ;;
status)
    status ;;
reload)
    reload ;;
restart)
    restart ;;
*)
   echo "使用方法 service nginx ( start | stop | status | reload | restart )";;
esac

安裝:  運行命令
ansible nginx -m copy -a "src=nginx dest=/tmp"
ansible nginx -m shell -a "bash /tmp/nginx/install.sh"

如果想直接使用nginx 命令,需要關閉連接重新打開一下,因爲source可能不生效。

1.4、tomcat安裝

需要下載的軟件: jdk-8u141-linux-x64.rpm, apache-tomcat-8.5.30.tar.gz

注意:每個安裝都是不同的目錄
#!/bin/bash
#
#   Name: tomcat 安裝
#   Version Number:1.01
#   Language:bash shell  
#   Date:2018年05月06日 00:20:28  
#   Author:xiong

filepath=$(cd $(dirname "0");pwd)
file_abs_path=${filepath}/tomcat

# 定義tomcat_jdk的版本
tomcat_version=8.5.30
jdk_version=8u141

# 定義tomcat_jdk名稱
tomcat_name=apache-tomcat-${tomcat_version}.tar.gz
jdk_name=jdk-${jdk_version}-linux-x64.rpm

if [ ! -d /usr/java/default ];then
 rpm -ivh ${file_abs_path}/${jdk_name}
 echo -e "export JAVA_HOME=/usr/java/default\nexport PATH=\${JAVA_HOME}/bin:\$PATH" >> /etc/profile.d/java.sh
 echo -e "export JRE_HOME=/usr/java/default\nexport PATH=\${JRE_HOME}/bin:\$PATH" >> /etc/profile.d/java.sh
 source /etc/profile.d/java.sh
else
  echo "jdk 已安裝"
fi
if [ ! -d /usr/local/apache-tomcat-8.5.30 ] ;then
        tar xf ${file_abs_path}/${tomcat_name} -C /usr/local/
        ln -sv /usr/local/apache-tomcat-8.5.30 /usr/local/tomcat
        echo -e "export CATALINA_HOME=/usr/local/tomcat\nexport PATH=\${CATALINA_HOME}/bin:\$PATH" >> /etc/profile.d/tomcat.sh

        source ${filepath}/tomcat/start.sh
else
        echo "tomcat 已安裝"
fi

/usr/local/tomcat/bin/catalina.sh start

安裝:  安裝前先 cd .. 退到上一級
ansible tomcat -m copy -a "src=tomcat dest=/root"
ansible tomcat -m shell -a "bash /root/tomcat/install.sh"

1.5、keepalived+memcached安裝

ansible mem -m yum -a "name=memcached state=present"
ansible nginx -m yum -a "name=keepalived state=present"

2、配置

2.1、tomcat+mem實現session共享

需要下載的包[memcached-session-manager-tc8-2.3.0、spymemcached-2.12.3、memcached-session-manager-2.3.0、msm-javolution-serializer-2.1.1,javolution-5.4.3.1]

Host] # mkdir lib
tomcat]# ls lib/
javolution-5.4.3.1.jar               memcached-session-manager-tc8-2.3.0.jar  spymemcached-2.12.3.jar
memcached-session-manager-2.3.0.jar  msm-javolution-serializer-2.1.1.jar

# 複製到tomcat的lib目錄下
[root@docker2 tomcat]# ansible tomcat -m copy -a "src=lib dest=/usr/local/tomcat/"

配置server.xml文件
      <Host name="localhost"  appBase="webapps"
            unpackWARs="true" autoDeploy="true">
          <Context path="/test" docBase="/usr/local/tomcat/webapps/test" reloadable="true">
             <Manager className="de.javakaffee.web.msm.MemcachedBackupSessionManager"
               memcachedNodes="n1:192.168.175.131:11211,n2:192.168.175.132:11211"
               failoverNodes="n1"
               requestUriIgnorePattern=".*\.(ico|png|gif|jpg|css|js)$"
               transcoderFactoryClass="de.javakaffee.web.msm.serializer.javolution.JavolutionTranscoderFactory"
             />
            </Context>

其它的都不動 就新加一個
Host]# ansible tomcat -m copy -a "src=server.xml dest=/usr/local/tomcat/conf"

注意:兩個tomcat都需要增加,我們這先用來做測試
Host] # mkdir test 
vim index.jsp
<%@ page language="java" %>
<html>
 <head><title>TomcatA</title></head>
 <body>
   <h1><font color="red">TomcatA.</font></h1>
   <table align="centre" border="1">
     <tr>
       <td>Session ID</td>
   <% session.setAttribute("TomcatA","TomcatA"); %>
       <td><%= session.getId() %></td>
     </tr>
     <tr>
       <td>Created on</td>
       <td><%= session.getCreationTime() %></td>
    </tr>
   </table>
 </body>
</html>

最後啓動:
Host]# ansible tomcat -m shell -a "/usr/local/tomcat/bin/catalina.sh stop"
Host]# ansible tomcat -m shell -a "/usr/local/tomcat/bin/catalina.sh start"
Host]# ansible tomcat -m shell -a "ss -tnl"

2.2、使用Nginx反向代理tomcat

nginx改nginx.conf文件  兩個機器相同的配置
#user  nobody;
user nginx;
worker_processes  auto;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
#
pid        /var/run/nginx.pid;

events {
    worker_connections  51200;
}

http {
    include       mime.types;
    include       conf.d/*.conf;
    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;
    client_header_timeout 600s;
    client_body_timeout 600s;
    client_max_body_size 100m;               #允許客戶端請求的最大單個文件字節數
    client_body_buffer_size 256k;            #緩衝區代理緩衝請求的最大字節數,可以理解爲先保存到本地再傳給用戶

    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;
    server_tokens off;

    tcp_nopush     on;

    keepalive_timeout  65;

    upstream tom {
        server 192.168.175.131:8080;
        server 192.168.175.132:8080;
    }

    server {
        listen 80;
        server_name 127.0.0.1;
        location / {
            proxy_pass http://tom;
        }
    }

}

效果
nginx+tomcat+msm實現seesion共享
nginx+tomcat+msm實現seesion共享

兩臺機器訪問可見session ID是不一致的,分別打開的瀏覽器,tomcat將它當成了是兩個客戶端。
nginx+tomcat+msm實現seesion共享

日誌可以說明問題,兩個客戶 當然必須得是兩個session了
nginx+tomcat+msm實現seesion共享

2.3、keepalived負載均衡

關於keepalived的配置請查看keepalived實現服務高可用
,具體配置不做講解

! Configuration File for keepalived

global_defs {
   notification_email {
     [email protected]
     [email protected]
     [email protected]
   }
   router_id LVS_DEVEL
   vrrp_skip_check_adv_addr
   vrrp_strict
   vrrp_garp_interval 0
   vrrp_gna_interval 0
}
vrrp_script chk_http_port {
        script "/etc/keepalived/check_nginx.sh"
        interval 1
        weight -15
        fall 3
}

從這裏開始纔開始改變配置
vrrp_instance VI_1 {
    state MASTER     # 從改爲BACKUP
    interface ens38    # 這裏是你的接口地址
    virtual_router_id 51    # 路由ID兩個保持一致,如果修改了組播地址也需要保持一致
    priority 100    # 優先級 從改爲90

從這裏開始 兩個配置都是一樣的
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass xiooo
    }
    virtual_ipaddress {
        192.168.175.100
    }
    track_script {
        chk_http_port
    }
}

virtual_server 192.168.175.100 80 {
    delay_loop 60
    lb_algo rr
    lb_kind DR
    persistence_timeout 50
    protocol TCP

    real_server 192.168.175.130 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              digest 7f9c8adff625e7583b27dca2ceff7753
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
    real_server 192.168.175.125 80 {
        weight 1
        HTTP_GET {
            url {
              path /
              digest 864f178b239923100aa96d2087de374e
            }
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

keepalived]# cat check_nginx.sh 
#!/bin/bash
#
count=`ps -C nginx --no-heading | wc -l`
time=`date "+%Y-%m-%d %H-%M"`

if [ ${count} == 0 ];then

        echo "${time} -  keepalived fail " > /tmp/keepalive_status.txt
        /usr/bin/systemctl stop keepalived
else
        echo "${time} - keepalive ok" > /tmp/keepalive_status.txt
fi

最後啓動兩個keepalived
虛擬地址爲 192.168.175.100
nginx+tomcat+msm實現seesion共享
抓包以及其它的請看上面鏈接的文章,我這就不重複造輪子了。
如果想ping通VIP的話 需要在 keepalived.conf中
# vrrp_strict 註釋它。

最後直接使用瀏覽器就能訪問看到效果了,

nginx+tomcat+msm實現seesion共享
nginx+tomcat+msm實現seesion共享

最後日誌應該是每個機器輪詢,我這虛擬機有點問題,在真機上是好的。
最後附上所有的配置文件下載鏈接: 密碼:6o3a

ansible+playbook安裝

這裏使用ansible playbook安裝方式 待更新

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章