nginx系列(二)session共享

session共享之redis

介绍

nginx在解决session的时候有好几种方案

  • ip_hash
  • 存放redis
  • session换coolie
  • 单独设置一个session服务器
  • tomcat自带的cluster方式

考虑到目前自己所工作的项目中,有以下特性

  1. 经常停服务

  2. 需要多台服务器分担压力

  3. 项目从统一用户(SSO)进行单点登录

  4. redis可以进行推上去

    单点登录中的token是实时的,仅仅用来登录时候双方校验,校验过后就不在使用,也没有提供接口进行二次校验token的正确性。

    测试环境中由于redis已经搭建,但是由于种种原因为上线,正好借此机会进行推上去。

根据上述情况,决定采用redis进行存储session,保证session共享。

在写博客之前,博主在开发的测试环境进行试验,最后实现了该功能。

使用redis的话现在需要 tomcat-redis-session-manager.jar包,目前该链接仅仅支持到tomcat7,点击链接进行下载 tomcat-redis-session-manager

编译

通过上面下载的内容,但是上面没有jar包,此时需要我们进行编辑为jar包。

编译工具使用的为gradle,类似于maven的一样就行配置环境变量。

首先解压后,修改其中的build.gradle文件,修改后内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'signing'

group = 'com.orangefunction'
version = '2.0.0'

repositories {
mavenCentral()
}

compileJava {
// 指定jdk版本
sourceCompatibility = 1.8
targetCompatibility = 1.8
}

dependencies {
compile group: 'org.apache.tomcat', name: 'tomcat-catalina', version: '7.0.70'
compile group: 'redis.clients', name: 'jedis', version: '2.8.1'
compile group: 'org.apache.commons', name: 'commons-pool2', version: '2.2'
//compile group: 'commons-codec', name: 'commons-codec', version: '1.9'

testCompile group: 'junit', name: 'junit', version: '4.+'
testCompile 'org.hamcrest:hamcrest-core:1.3'
testCompile 'org.hamcrest:hamcrest-library:1.3'
testCompile 'org.mockito:mockito-all:1.9.5'
testCompile group: 'org.apache.tomcat', name: 'tomcat-coyote', version: '7.0.70'
}

task javadocJar(type: Jar, dependsOn: javadoc) {
classifier = 'javadoc'
from 'build/docs/javadoc'
}

task sourcesJar(type: Jar) {
from sourceSets.main.allSource
classifier = 'sources'
}

artifacts {
archives jar

archives javadocJar
archives sourcesJar
}

// 要进行注释掉
//signing {
//sign configurations.archives
//}

uploadArchives {
repositories {
mavenDeployer {
beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }

// 注释掉
// repository(url: "https://oss.sonatype.org/service/local/staging/deploy/maven2/") {
// authentication(userName: sonatypeUsername, password: sonatypePassword)
//}
//repository(url: "https://oss.sonatype.org/content/repositories/snapshots") {
// authentication(userName: sonatypeUsername, password: sonatypePassword)
//}

pom.project {
name 'tomcat-redis-session-manager'
packaging 'jar'
description 'Tomcat Redis Session Manager is a Tomcat extension to store sessions in Redis'
url 'https://github.com/jcoleman/tomcat-redis-session-manager'

issueManagement {
url 'https://github.com:jcoleman/tomcat-redis-session-manager/issues'
system 'GitHub Issues'
}

scm {
url 'https://github.com:jcoleman/tomcat-redis-session-manager'
connection 'scm:git:git://github.com/jcoleman/tomcat-redis-session-manager.git'
developerConnection 'scm:git:git@github.com:jcoleman/tomcat-redis-session-manager.git'
}

licenses {
license {
name 'MIT'
url 'http://opensource.org/licenses/MIT'
distribution 'repo'
}
}

developers {
developer {
id 'jcoleman'
name 'James Coleman'
email 'jtc331@gmail.com'
url 'https://github.com/jcoleman'
}
}
}
}
}
}

然后我们可以更改java与依赖包的版本,上述为本人编译成功后的文件,大家可以直接进行复制替换。

在tomcat-redis-session-manager-1.2-tomcat-7下进行编译,命令为

1
gradle build

编译后在build /lib 下会生成jar包 tomcat-redis-session-manager-master-2.0.0.jar

注意:上述依赖的包一定要与我们实际的tomcat版本一直,jdk版本一直,而且上面用到的包的版本,会在下面配置中进行使用。

配置

首先说明需要的包:

  • tomcat-redis-session-manager-master-2.0.0.jar
  • jedis-2.8.1.jar
  • commons-pool2-2.2.jar

操作步骤(每台服务器都要进行操作)

  1. 将上述的包放在tomcat目录下的lib中

    保证上述包与编译包的版本一致

  2. 修改context配置文件(tomcat下conf目录中的context.xml)

    1
    2
    3
    4
    5
    6
    <Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
    <Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
    host="192.168.2.163"
    port="6379"
    database="0"
    maxInactiveInterval="60" />

    其中要保证value与manager标签中的className保持一致(可以解压jar包,得到路径)

  3. 分别启动tomcat

    博主是在两台服务器上进行搭建的,此时要进行启动,并正常访问(此时nginx为启动)

  4. 开启nginx并访问

    启动nginx,可以参考上篇博客,结果如下图

tomcat中session同步

在有些时候我们需要进行用tomcat自带的session同步,比较简答以及不需要redis;

介绍 Cluster

tomcat自带的session同步是根据组播的形式的,大家加入一个组来进行实现session同步。

当时由于是内网环境进行搭建,在上述为成功的刺激下尝试使用这种方式,很遗憾,家里在tomcat8的基础上进行搭建起来了,但是tomcat7未成功。下面讲的是在tomct8的基础上进行的。

配置 Cluster

此时与上述redis实现redis共享不一致,此时修改的conf下的server.xml,直接上代码,在

下面增加,也就是在Engine 标签中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"
channelSendOptions="8">

<Manager className="org.apache.catalina.ha.session.DeltaManager"
expireSessionsOnShutdown="false"
notifyListenersOnReplication="true"/>

<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Membership className="org.apache.catalina.tribes.membership.McastService"
<!-- 该地址不能修改,用于组播,当配置相同的address 与 端口时候就会组成一下组,session在组内进行传播 -->
address="228.0.0.4"
port="45564"
frequency="500"
dropTime="3000"/>
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"
<!-- 该地址可以修改为aotu,如果报错的话也可以修改为ip地址,但是注意的是如果是同一个服务器上的两个tomcat,需要修改端口号保证端口号不能重复 -->
address="auto"
port="4000"
autoBind="100"
selectorTimeout="5000"
maxThreads="6"/>

<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
</Sender>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.TcpFailureDetector"/>
<Interceptor className="org.apache.catalina.tribes.group.interceptors.MessageDispatchInterceptor"/>
</Channel>

<Valve className="org.apache.catalina.ha.tcp.ReplicationValve"
filter=""/>
<Valve className="org.apache.catalina.ha.session.JvmRouteBinderValve"/>

<Deployer className="org.apache.catalina.ha.deploy.FarmWarDeployer"
tempDir="/tmp/war-temp/"
deployDir="/tmp/war-deploy/"
watchDir="/tmp/war-listen/"
watchEnabled="false"/>

<ClusterListener className="org.apache.catalina.ha.session.ClusterSessionListener"/>
</Cluster>

上面的代码要在两个tomcat上进行添加

此时在项目中的web.xml上增加标签

1
<distributable/>

启动中看到部分日志:

1
2
3
4
5
6
7
8
10-Jul-2019 08:16:01.090 INFO [main] org.apache.catalina.ha.tcp.SimpleTcpCluster.startInternal Cluster is about to start
10-Jul-2019 08:16:01.108 INFO [main] org.apache.catalina.tribes.transport.ReceiverBase.bind Receiver Server Socket bound to:[/192.168.2.163:4000]
10-Jul-2019 08:16:01.125 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.setupSocket Setting cluster mcast soTimeout to [500]
10-Jul-2019 08:16:01.132 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Sleeping for [1000] milliseconds to establish cluster membership, start level:[4]
10-Jul-2019 08:16:02.133 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Done sleeping, membership established, start level:[4]
10-Jul-2019 08:16:02.139 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Sleeping for [1000] milliseconds to establish cluster membership, start level:[8]
10-Jul-2019 08:16:03.140 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Done sleeping, membership established, start level:[8]
10-Jul-2019 08:16:03.144 SEVERE [main] org.apache.catalina.ha.deploy.FarmWarDeployer.start FarmWarDeployer can only work as host cluster subelement!

另外一台启动日志

1
2
3
4
5
6
7
8
9
10
10-Jul-2019 08:19:32.360 INFO [main] org.apache.catalina.ha.tcp.SimpleTcpCluster.startInternal Cluster is about to start
10-Jul-2019 08:19:32.374 INFO [main] org.apache.catalina.tribes.transport.ReceiverBase.bind Receiver Server Socket bound to:[/192.168.2.228:4000]
10-Jul-2019 08:19:32.398 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.setupSocket Setting cluster mcast soTimeout to [500]
10-Jul-2019 08:19:32.426 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Sleeping for [1000] milliseconds to establish cluster membership, start level:[4]
10-Jul-2019 08:19:32.460 INFO [Membership-MemberAdded.] org.apache.catalina.ha.tcp.SimpleTcpCluster.memberAdded Replication member added:[org.apache.catalina.tribes.membership.MemberImpl[tcp://{192, 168, 2, 163}:4000,{192, 168, 2, 163},4000, alive=211314, securePort=-1, UDP Port=-1, id={80 -3 -97 73 -77 -63 65 -56 -69 32 -65 -51 -106 61 -81 79 }, payload={}, command={}, domain={}, ]]
10-Jul-2019 08:19:33.428 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Done sleeping, membership established, start level:[4]
10-Jul-2019 08:19:33.461 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Sleeping for [1000] milliseconds to establish cluster membership, start level:[8]
10-Jul-2019 08:19:33.628 INFO [Tribes-Task-Receiver[Catalina-Channel]-1] org.apache.catalina.tribes.io.BufferPool.getBufferPool Created a buffer pool with max size:[104857600] bytes of type: [org.apache.catalina.tribes.io.BufferPool15Impl]
10-Jul-2019 08:19:34.462 INFO [main] org.apache.catalina.tribes.membership.McastServiceImpl.waitForMembers Done sleeping, membership established, start level:[8]
10-Jul-2019 08:19:34.467 SEVERE [main] org.apache.catalina.ha.deploy.FarmWarDeployer.start FarmWarDeployer can only work as host cluster subelement!

上述用到的页面代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<%@ page contentType="text/html; charset=UTF-8" %>  
<%@ page import="java.util.*" %>
<html><head><title>Tomcat Cluster Demo</title></head>
<body>
Server Info:
<%
out.println(request.getLocalAddr() + " : " + request.getLocalPort()+"<br>");%>
<%
out.println("<br> ID " + session.getId()+"<br>");

String dataName = request.getParameter("dataName");
if (dataName != null && dataName.length() > 0) {
String dataValue = request.getParameter("dataValue");
session.setAttribute(dataName, dataValue);
System.out.println("application:" + application.getAttribute(dataName));
application.setAttribute(dataName, dataValue);
}
out.print("<b>Session List</b>");
Enumeration<String> e = session.getAttributeNames();
while (e.hasMoreElements()) {
String name = e.nextElement();
String value = session.getAttribute(name).toString();
out.println( name + " = " + value+"<br>");
System.out.println( name + " = " + value);
}
%>
<form action="test.jsp" method="POST">
Name:<input type=text size=20 name="dataName">
<br>
Value:<input type=text size=20 name="dataValue">
<br>
<input type=submit>
</form>
</body>
</html>

本文标题:nginx系列(二)session共享

文章作者:wsylp

发布时间:2019年07月07日 - 22:07

最后更新:2020年01月02日 - 10:01

原始链接:http://wsylp.top/2019/07/07/nginx系列-二-session共享/

许可协议: 本文为 wsylp 版权所有 转载请保留原文链接及作者。

-------------本文结束感谢阅读-------------