LNMT羣集基於Redis實現Session共享

博文大綱:
一、Redis概述
二、如何保持session會話
三、部署LNMT羣集基於Redis實現Session共享
(1)搭建Nginx服務器配置爲反向搭理
(2)配置Tomcat服務器
(3)配置Redis緩存服務器
(4)配置Tomcat服務器可以連接Redis服務器
(5)安裝部署Mysql數據庫
(6)配置Tomcat連接MySQL數據庫

一、Redis概述

Redis是完全開源免費的、高性能的key-value數據庫,它所支持的、存儲的value類型相對更多。與Memcached一樣 ,爲了保證效率,數據都是緩存在內存中的。區別就是redis會週期性的將更新的數據寫入磁盤或者把修改文件寫入追加的記錄文件,並且在此基礎上實現master-slave(主從同步)!

Redis的出現,很大程度補償了Memcached這類key/value存儲的不足,在部分場合可以對關係數據庫起到很好的補充作用。

Redis和Memcached的區別:
1)Redis不僅僅支持簡單的k/v類型的數據,同時還提供list、set、zset、hash等數據結構的存儲;
2)Redis支持數據的備份,及master-slave模式的數據備份;
3)Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啓時可以再次加載進行使用;

在Redis中,並不是所有的數據都一直存儲在內存中的。這就是和Memcached相比一個最大的區別。Redis只會緩存所有的key的信息,如果Redis發現內存的使用量超過了某個閾值,將觸發swap的操作,Redis會根據自己的算法計算出哪些key對應的value需要swap到磁盤。然後再將這些key對應的value持久化到磁盤中,同時在內存中清除。這種特性使得Redis可以保持超過其機器本身內存大小的數據。當然,機器本身的內存必須要能夠保持所有的key,因爲這些數據是不會進行swap操作的。

當從Redis中讀取數據的時候,如果讀取的key對應的value不在內存中,那麼Redis就需要從swap文件中加載相應數據,然後再返回給請求方。

Memcached和Redis的比較

(1)網絡IO模型

Memcached是多線程,非阻塞IO複用的網絡模型。分爲監聽主線程和worker子線程,監聽線程監聽網絡連接,接收請求後,將連接描述字傳遞給worker線程,進行讀寫IO,網絡層使用libevent封裝的事件庫,多線程可以發揮多核作用;

Redis使用單線程的IO複用模型,自己封裝一個簡單的AeEvent事件處理框架,主要實現了epoll、kqueue和select,對於單純只有IO操作來說,單線程可以將速度優勢發揮到最大,但是Redis也提供了一些簡單的計算功能,比如排序、聚合等,對於這些操作,單線程模型實際會嚴重影響整體吞吐量,CPU計算過程中,整個IO調度都是被阻塞的;

(2)內存管理方面

Memcached使用預分配的內存池的方式,使用slab和大小不同的chunk來管理內存,value根據大小選擇合適的chunk存儲;

Redis使用現場申請內存的方式來存儲數據;

(3)存儲方式及其他方面

Memcached基本只支持簡單的key-value存儲,不支持持久化和複製等功能,Redis除key/value之外,還支持list、set、sortedset、hash等衆多數據結構;

二、如何保持session會話

目前,爲了使web能適應大規模的訪問,需要實現應用的集羣部署。集羣最有效的方案就是負載均衡,而實現負載均衡用戶每一個請求都有可能分配懂啊不固定的服務器上,這樣我們首先要解決session的統一來保證無論用戶的請求被轉發到哪個服務器上都能保證用戶的正常使用,即需要實現session的共享機制。

在集羣系統下實現session統一的方案:

(1)請求精確定位(sessionsticky)

類似於基於訪問的IP的hash策略,即當前用戶的請求都集中定位到一臺服務器中,這樣單臺服務器保存了用戶的session登錄信息,如果宕機,則等同於單點部署,會丟失,會話不復制;

(2)session複製共享(sessionreplication)

比如Tomcat自帶session共享,主要是指集羣環境下,多臺應用服務器之間同步session,使session保持一致,對外透明。如果其中一臺服務器發生故障,根據負載均衡的原理,調度其會遍歷尋找可用節點 ,分發請求,由於session已同步,故能保證用戶的session信息不會丟失,會話複製;

缺陷:

session複製帶來的性能損失會快速增加.特別是當session中保存了較大的對象,而且對象變化較快時, 性能下降更加顯著,會消耗系統性能。這種特性使得web應用的水平擴展受到了限制。Session內容通過廣播同步給成員,會造成網絡流量瓶頸,即便是內網瓶頸。在大併發下表現並理想!

(3)基於memcache/redis緩存的 session 共享

使用cacheDB存取session信息,應用服務器接受新請求將session信息保存在cache DB中,當應用服務器發生故障時,調度器會遍歷尋找可用節點,分發請求,當應用服務器發現session不在本機內存時,則去cache DB中查找,如果找到則複製到本機,這樣實現session共享和高可用。

三、部署LNMT羣集基於Redis實現Session共享

1)案例環境

LNMT羣集基於Redis實現Session共享

2)準備環境

LNMT羣集基於Redis實現Session共享

3)案例實施

(1)搭建Nginx服務器配置爲反向搭理

配置Nginx服務可能過於簡單,如果想要對nginx服務有深入的瞭解,可以參考博文:Nginx初步優化深度優化Nginx(一)Nginx深度優化(二)這三篇博文對Nginx服務有詳細的介紹,包括nginx的優化!

下載Nginx軟件包

[root@Nginx ~]# yum -y install pcre-devel zlib-devel openssl-devel
//安裝nginx服務所需依賴
[root@Nginx ~]# tar zxf nginx-1.14.0.tar.gz -C /usr/src
[root@Nginx ~]# cd /usr/src/nginx-1.14.0/
[root@Nginx nginx-1.14.0]# ./configure && make && make install
//解壓、編譯、安裝(由於本次案例不要nginx過多的功能,所以什麼參數都不加了)
[root@Nginx ~]# ln -s /usr/local/nginx/sbin/nginx  /usr/local/sbin
//創建符號鏈接
[root@Nginx ~]# vim /usr/local/nginx/conf/nginx.conf
//編輯Nginx的配置文件
 20         upstream backend_tomcat {             
 21         server 192.168.1.5:8080 weight=1 max_fails=2 fail_timeout=10s;
 22         server 192.168.1.6:8080 weight=1 max_fails=2 fail_timeout=10s;
 23         }
//在nginx配置文件的http模塊中添加後端服務器羣組(前面爲行號)
 47         location / {
 48         proxy_pass http://backend_tomcat;            //定義轉發後端那個服務器羣組
 49         proxy_redirect off;
 50         proxy_set_header Host $host;
 51         proxy_set_header X-Real-IP $remote_addr;
 52         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 53         proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
 54         }
//編寫location規則,可以基於原本的location進行修改!
[root@Nginx ~]# nginx -t                     //檢查Nginx服務的配置文件
[root@Nginx ~]# nginx                        //啓動nginx服務

(2)配置Tomcat服務器

下載Tomcat軟件包

TomcatA服務器:

[root@TomcatA ~]# tar zxf apache-tomcat-8.5.35.tar.gz -C /usr/src
[root@TomcatA ~]#  mv /usr/src/apache-tomcat-8.5.35 /usr/local/tomcat
[root@TomcatA ~]# vim /usr/local/tomcat/conf/server.xml
150  <Context docBase="/web/webapp1" path="" reloadable="true"/>
//定義虛擬目錄,網頁根目錄是/web/webapp1,這行內容必須寫在Host模塊中才會生效(前面爲行號)
[root@TomcatA ~]# mkdir -p /web/webapp1         //創建網頁根目錄
[root@TomcatA ~]# vim /web/webapp1/index.jsp      //創建測試頁面
<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<html>
<head>
<title>tomcat-1</title>          //主要就是在這個標題這裏區分兩臺tomcat,第二臺自行修改
</head>
<body>
<h1><font color="red">Session serviced by tomcat</font></h1>
<table aligh="center" border="1">
<tr>
<td>Session ID</td>
<td><%=session.getId() %></td>
<% session.setAttribute("abc","abc");%>
</tr>
<tr>
<td>Created on</td>
<td><%= session.getCreationTime() %></td>
</tr>
</table>
</body>
<html>
[root@TomcatA ~]# /usr/local/tomcat/bin/startup.sh          //啓動tomcat服務

TomcatB服務器
TomcatB服務器與TomcatA服務器的配置一模一樣,注意自行修改測試標題內容,避免無法分辨!

配置完成後,客戶端測試訪問:
LNMT羣集基於Redis實現Session共享
LNMT羣集基於Redis實現Session共享

很顯然,這種情況在實際工作中是絕對不允許的,那麼就需要使用——Redis緩存服務器!

(3)配置Redis緩存服務器

下載Redis軟件包其中包括了Tomcat連接Redis、Mysql所需的jar包!

[root@Redis ~]# tar zxf redis-4.0.14.tar.gz -C /usr/src
[root@Redis ~]# mv /usr/src/redis-4.0.14/ /usr/local/redis
[root@Redis ~]# cd /usr/local/redis/
[root@Redis redis]# make && make install         //編譯安裝redis
[root@Redis redis]# cd utils/
[root@Redis utils]# ./install_server.sh                //對redis服務執行初始化腳本,保持默認回車即可
[root@Redis ~]# vim /etc/redis/6379.conf               //編寫redis主配置文件
  70 bind 192.168.1.7                  //修改其監聽爲網卡IP,也可以修改爲0.0.0.0
     502 requirepass 123.com              //添加redis服務的密碼爲123.com
[root@Redis ~]# vim /etc/init.d/redis_6379              //修改redis服務的腳本,以便使用腳本啓動
 43             $CLIEXEC -a 123.com -p $REDISPORT shutdown
//在原本的基礎上添加“-a”並指定密碼
[root@Redis ~]# /etc/init.d/redis_6379 restart     //初選警告信息可以忽略
[root@Redis ~]# netstat -anpt | grep redis            //確認redis服務已經正在運行
tcp        0      0 192.168.1.7:6379        0.0.0.0:*               LISTEN      5400/redis-server 1 

至此redis服務器已經配置完成!

(4)配置Tomcat服務器可以連接Redis服務器

TomcatA服務器

[root@TomcatA ~]# cd /usr/local/tomcat/lib/          //此目錄就是tomcat服務專用於存放jar包的位置
//將剛纔redis軟件包中的所有jar包上傳到此目錄中
[root@TomcatA ~]# vim /usr/local/tomcat/conf/context.xml 
 30 <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
 31 <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
 32 host="192.168.1.7"            //指定redis服務器IP地址
 33 password="123.com"        //指定連接redis服務器的密碼
 34 port="6379"                       //指定redis服務器開放的端口
 35 database="0"                    //是否允許寫入Redi數據庫,0爲允許
 36 maxInactiveInterval="60" />        //指定session會話時間的失效時間
 37 </Context>                                 //必須寫在這個標籤之上
[root@TomcatA ~]# /usr/local/tomcat/bin/shutdown.sh
[root@TomcatA ~]# /usr/local/tomcat/bin/startup.sh       //重新啓動tomcat服務

TomcatB服務器

此服務器操作與TomcatA服務器的操作一致,這裏就不介紹了!

配置完成後,客戶端進行訪問測試:
LNMT羣集基於Redis實現Session共享
LNMT羣集基於Redis實現Session共享

並且可以在Redis服務器上查詢到其對應的鍵、值:

[root@Redis ~]# redis-cli -h 192.168.1.7 -a 123.com
//登錄redis服務器,
192.168.1.7:6379> KEYS *
1) "B82B4C0D2390ECD8C9A86ACF1687ED456BnQWK"
//這個鍵就是瀏覽器訪問的session鍵(其對應的值,可以自行查詢,都是亂碼,也看不懂)

(5)安裝部署Mysql數據庫

由於編譯安裝Mysql數據庫太浪費時間,所以提供了Mysql數據庫一鍵安裝腳本
對編譯安裝Mysql數據庫感興趣的可以參考博文編譯安裝MySQL數據庫系統

[root@localhost ~]# ls
anaconda-ks.cfg       mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz
initial-setup-ks.cfg  mysql.sh
[root@localhost ~]# sh mysql.sh                //執行mysql安裝腳本
Starting MySQL. SUCCESS! 
mysql: [Warning] Using a password on the command line interface can be insecure.
//出現以上信息則表示mysql數據庫安裝完成!

(6)配置Tomcat連接MySQL數據庫

TomcatA服務器

[root@TomcatA ~]# mv /usr/local/tomcat/webapps/ROOT /web/webapp1/
//將原本的Tomcat的配置文件複製到Tomcat服務的網頁根目錄下

客戶端訪問:
LNMT羣集基於Redis實現Session共享
LNMT羣集基於Redis實現Session共享
LNMT羣集基於Redis實現Session共享
根據以下的配置步驟沒有問題!

接下來將步驟詳細寫出。

Mysql服務器

[root@localhost ~]# mysql -u root -p123        //登錄mysql數據庫,腳本提供的默認密碼是123
mysql> grant all on *.* to javauser@'192.168.1.%' identified by '123.com';
//授權用戶
mysql> create database javatest;            //創建數據庫
mysql> use javatest;
mysql> create table testdata (
id int not null auto_increment primary key,
foo varchar(25),
bar int);              //創建表
mysql> insert into testdata values(null, 'hello', 12345);
mysql> insert into testdata values(null, 'lzj', 88888);
mysql> insert into testdata values(null, 'xjj', 66666);      //隨便插入一些數據進行測試
mysql> select * from testdata;
+----+-------+-------+
| id | foo   | bar   |
+----+-------+-------+
|  1 | hello | 12345 |
|  2 | lzj   | 88888 |
|  3 | xjj   | 66666 |
+----+-------+-------+

TomcatA服務器

[root@TomcatA ~]# vim /usr/local/tomcat/conf/context.xml 
 37 <Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
 38                maxTotal="100" maxIdle="30" maxWaitMillis="10000"
 39                username="javauser" 
 40                 password="123.com" 
 41                 driverClassName="com.mysql.jdbc.Driver"
 //指定其使用的用戶名、密碼
 42                url="jdbc:mysql://192.168.1.8:3306/javatest"/>          //指定mysql數據庫的IP地址端口號
 43 </Context>                   //同樣以上操作必須在這個標籤中
[root@TomcatA ~]# mkdir /web/webapp1/WEB-INF       //創建目錄
[root@TomcatA ~]# vim /web/webapp1/WEB-INF/web.xml        //創建測試網頁
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
  <description>MySQL Test App</description>
  <resource-ref>
      <description>DB Connection</description>
      <res-ref-name>jdbc/TestDB</res-ref-name>
      <res-type>javax.sql.DataSource</res-type>
      <res-auth>Container</res-auth>
  </resource-ref>
</web-app>

[root@TomcatA ~]# vim /web/webapp1/mysql.jsp
//創建測試連接數據庫的腳本
<%@ page language="java" import="java.sql.*" pageEncoding="GB2312"%>
<html>
<head>
<title>MySQL-1</title>                  //注意根據標籤來區分
</head>
<body>
connect MySQL<br>
<%
String driverClass="com.mysql.jdbc.Driver";                   
String url="jdbc:mysql://192.168.1.8:3306/javatest";         //指定msyql數據庫IP地址、端口號
String username = "javauser";               //連接數據庫的用戶
String password = "123.com";Class.forName(driverClass);            //用戶的密碼
Connection conn=DriverManager.getConnection(url, username, password);
Statement stmt=conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from testdata");
while(rs.next()){
out.println("<br>foo:"+rs.getString(2)+"bar:"+rs.getString(3));
}
rs.close();
stmt.close();
conn.close();
%>
</body>
</html>
[root@TomcatA ~]# /usr/local/tomcat/bin/shutdown.sh 
[root@TomcatA ~]# /usr/local/tomcat/bin/startup.sh       //重新啓動Tomcat服務

同樣的方法將TomcatB服務器進行配置,這裏就略過了!

客戶端訪問測試:
LNMT羣集基於Redis實現Session共享
LNMT羣集基於Redis實現Session共享

注意:本次環境中,Redis僅僅只是保存Session信息而已,不會像Memcached一樣,緩存後端服務器的數據的。

——————————————本篇博文到此結束,感謝閱讀————————————————

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