1. 程式人生 > >Nginx+Tomcat搭建叢集,Spring Session+Redis實現Session共享

Nginx+Tomcat搭建叢集,Spring Session+Redis實現Session共享

小夥伴們好久不見!最近略忙,部落格寫的有點少,嗯,要加把勁。OK,今天給大家帶來一個JavaWeb中常用的架構搭建,即Nginx+Tomcat搭建服務叢集,然後通過Spring Session+Redis實現Session共享。
閱讀本文需要有如下知識點:
1.Nginx的安裝、配置
2.Spring+SpringMVC基本配置
3.Redis快取的使用
Nginx和Redis我打算後期寫幾篇部落格來介紹,這裡小夥伴如果對這兩個概念不懂的話可以先自行百度,對於Spring+SpringMVC的使用如果小夥伴有疑問,可以移步這裡Spring&SpringMVC框架

建立Maven專案,新增依賴

使用IntelliJ IDEA建立Maven專案,並新增相關依賴,依賴如下:

<dependencies>
        <!-- Jedis -->
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency
>
<!-- Spring Data Redis --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.8.4.RELEASE</version> </dependency> <!-- Spring Session -->
<dependency> <groupId>org.springframework.session</groupId> <artifactId>spring-session</artifactId> <version>1.3.1.RELEASE</version> </dependency> <!-- Apache Commons Pool --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.4.2</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-framework.version}</version> </dependency> </dependencies>

這裡要新增的依賴略多,不過大致可以分為如下三類:

1.Redis的Java客戶端,這個通過Java程式碼來操作Redis
2.Spring Data Redis,這個用來簡化Redis操作
3.Spring Session,這個用來進行Session的管理
4.Spring

搭建Spring+SpringMVC環境

首先在resources資料夾下建立spring+springmvc的配置檔案:
這裡寫圖片描述
然後在web.xml檔案中配置spring和springmvc,如下:

<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <servlet>
        <servlet-name>springmvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

然後在applicationContext.xml檔案中簡單的配置一下spring,如下:

<context:component-scan base-package="org.sang" use-default-filters="false">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

配置Spring容器要掃描的註解。
然後在spring-servlet.xml中配置SpringMVC容器要掃描的註解,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <mvc:annotation-driven/>

    <context:component-scan base-package="org.sang" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

</beans>

spring-servlet.xml的配置相對要簡單一些。
OK,至此,Spring+SpringMVC的環境就搭建成功了。

配置Spring Session和Redis

Session一直是我們做叢集時一個比較頭疼的問題,之前有一個GitHub上的開源控制元件tomcat-redis-session-manager,但是這個東西目前只支援到Tomcat7,不是最佳選項,我們也可以使用Nginx提供的ip_tables,將同一個請求ip定位到同一臺伺服器上,但是這樣沒有辦法充分利用服務叢集的效能,Spring Session的出現可以很好的幫助我們解決這些問題,它具有如下特點:

1.Spring Session提供了redis、jvm的map、mongo、gemfire、hazelcast、jdbc等多種儲存session的容器的方式。
2.同一個瀏覽器同一個網站,支援多個session。
3.不依賴於cookie。可通過header來傳遞sessionID
4.WebSocket和spring-session結合,同步生命週期管理。
5.使用簡單

OK,接下來我們來看看怎麼配置我們的Spring Session,首先在web.xml檔案中新增過濾器:

<filter>
        <filter-name>springSessionRepositoryFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSessionRepositoryFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

這裡使用了Spring Web提供的代理過濾器,將攔截到的請求全部交給一個名為springSessionRepositoryFilter的過濾器進行處理。OK,然後在applicationContext.xml中配置Spring Session和Redis,如下:

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>
    <bean class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <property name="hostName" value="192.168.248.128"/>
        <property name="port" value="6379"/>
        <property name="database" value="0"/>
    </bean>

hostName即為redis的地址,port為redis的服務埠。

OK,寫完這一切就OK了,我們來寫一個簡單的jsp頁面測試一下,測試前記得啟動你的redis服務哦。

測試

index.jsp頁面如下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/setsession">
    <input type="text" name="name"><input type="submit" value="提交">
</form>
<form action="/getsession">
    <input type="submit" value="獲取">
</form>
</body>
</html>

該頁面我儘量做得簡單,有兩個按鈕,第一個向session中存資料,第二個按鈕從session中取資料,對應的Controller如下:

@Controller
public class HelloController {
    @RequestMapping("/setsession")
    @ResponseBody
    public void setSession(HttpSession session, String name) {
        session.setAttribute("name", name);
    }

    @RequestMapping(value = "/getsession",produces = "text/html;charset=utf-8")
    @ResponseBody
    public String getSession(HttpSession session, HttpServletRequest req) {
        return session.getAttribute("name").toString()+"-----"+req.getServletContext().getRealPath("/");
    }
}

當我向httpsession中寫資料時,這些資料會自動儲存到redis快取/資料庫中。在返回session資料時我加上了專案部署路徑,是為了在部署到叢集上之後區分這個請求是由哪臺伺服器處理的。啟動專案,頁面如下:
這裡寫圖片描述
點選提交,會將資料儲存到redis 中,如下:
這裡寫圖片描述
然後再回到起始頁面,點選獲取按鈕,即可以拿到Session中的值,如下:
這裡寫圖片描述
OK,很簡單吧!
至此,我們的Spring Session+Redis實現Session共享這個功能就完成了。接下來我們來看看如何為這個簡單的web專案搭建叢集。

搭建叢集的準備工作

1.下載Nginx(地址http://nginx.org/),我這裡使用的Nginx版本是nginx-1.12.0
2.下載Tomcat,我這裡使用的Tomcat版本是apache-tomcat-8.5.12

網路拓撲圖如下:
這裡寫圖片描述
將下載的Tomcat複製成兩份,如下:
這裡寫圖片描述
修改Tomcat的配置檔案(conf/server.xml),重新設定埠號,每一個Tomcat的server.xml都需要修改三處,如下:
這裡寫圖片描述
要修改的地方有三處,我將給預設的埠號前面都加1,然後第二個Tomcat我給這三個地方的埠號前面都加2,這樣方便我一會在同一臺機器上跑多個Tomcat。
OK,做好這一切之後,可以先啟動這兩個Tomcat,看看能不能正常訪問。

部署專案

OK,兩臺Tomcat都配置好之後,我們將剛才的專案拷貝到tomcat的webapps目錄下,給兩個Tomcat都拷貝。這裡就不贅述了。

配置Nginx

下載Nginx,解壓後,配置conf/nginx.conf檔案,如下:
這裡寫圖片描述
配置完成後,啟動nginx。再測試。

測試

向session中存資料:
這裡寫圖片描述
從session中取資料:
多取幾次,你會看到請求是由不同的伺服器處理的,如下:
這裡寫圖片描述
這裡寫圖片描述

OK,至此,我們的所有工作就做完啦!有問題歡迎留言交流。專案下載地址:

更多JavaEE資料,請關注公眾號:
這裡寫圖片描述

以上。