會話保持 (轉)


http://www.cnblogs.com/kellyseeme/p/7599061.html

理論部分

    會話也就是session,主要存儲在服務器端,用來識別用戶的身份。

    在瀏覽器中向服務端發送請求的時候,不是http協議就是https協議,而兩種協議在發送請求的時候,都是基於http協議,http協議又是無狀態的,也就是stateless,在每次用戶發送請求過去的時候,這都是一次新的連接,服務端是不會認識你是誰的。

    那么怎么讓服務端來識別客戶端誰是誰呢,從而也就有cookie,cookie好像沒有中文翻譯,cookie主要存儲在客戶端,一般是保存在某個特定路徑的文件之中,從而在每次發送請求的時候,都會附加上這個cookie信息,服務端得到這個信息之后,就會判定你是哪個用戶等信息,cookie主要就是找到服務端的session信息,從而用來追蹤用戶。

    在生產環境中,只要涉及到負載均衡的地方,我們就需要考慮會話保持,否則假如一個應用程序是需要登錄的,那么會頻繁的需要登錄。

    負載均衡主要分為硬件負載均衡F5,CITRIX等,nginx負載均衡,apache負載均衡,無論是硬件負載均衡或者是軟件負載均衡都會有一個會話保持的選項,在需要進行會話保持的時候,在每一個環節都需要進行會話保持,也就是硬件負載均衡要選擇會話保持,在軟件負載均衡也要進行會話保持。

    生產環境使用的過時的(第一種):

 

 

    在中間件的選擇上面,apache和webspare在逐漸淘汰,在使用此種架構的時候,F5會使用會話保持,nginx也使用的是ip_hash進行會話保持。此種架構的最大的優勢是部署比較簡單,在進行部署的時候只要將java程序的war包放置到具體的目錄即可進行部署,在進行自動化發布的時候,進行部署是非常簡單的事,因為集群中各個機器是獨立的,一個機器出問題,不會影響其他的機器;缺點就是在部署的時候,需要在每個主機上進行放置相同的war包,並且配置要保持一直;在需要會話保持的場景中,如果一台主機down,那么就會導致所有的會話丟失。

    生產環境使用的過時的架構(第二種):

 

 

 

    在使用domain模式的時候,前端的F5和nginx都不需要進行會話保持,只要做到負載均衡就好了。此種方式的最大有點就是在自動化部署的時候只要在domain節點的master或者是dmgr部署程序即可,主節點會自動將相關的程序同步到其他的slave或者node節點上去,在修改配置的時候,也只要在master上進行修改即可,在會話保持的上面,主機之間會同步相關的會話信息,從而不用擔心某台服務器宕機從而導致會話丟失。缺點就是,無論是在發布或者同步配置的時候,主節點總要聯系上從節點,進行同步,而從節點的相關進程還是比較容易出現假死的情況,在使用這種集群的時候,只要master節點或者dmgr節點的服務器損壞,那么這個集群就不能重新發布新的程序版本了,但是不會影響服務的可用性,在每次出現問題的時候,因為同步進程有好幾個,你都不知道是那個進程假死了,只能全部進行重啟一遍,說好的穩定性呢。為啥這種慢慢淘汰,一個是因為在自動化發布的時候,很容易出現問題;在進行灰度發布的時候,standalone模式更容易控制,而且domain模式有主機數量的限制,而standalone模式理論上無上限。

    生產環境目前架構如下:

 

    在使用此種架構的時候,前端無須進行會話保持,后端也無須進行會話的同步,在有后端主機宕機的時候,也不會丟失會話,灰度發布也很容易,自動化做起來比較簡單,從而也就成為了目前的架構。

 

使用tomcat standalon演示會話保持

    tomcat的首頁內容如下所示(可以查看到頁面的session信息):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@mogilenode3 kel] # cat index.jsp
 
<%@ page language= "java" %>
 
<%@ page import = "java.util.*" %>
 
<html>
 
     < head >
 
         <title>JAVA PAGE< /title >
 
     < /head >
 
     <body>
 
         <% out.println( "mogilenode3" ); %>
 
<%= session.getId() %>
 
     < /body >
 
< /html >

  

    在使用負載均衡的時候,准備兩台主機,均需要安裝jdk和tomcat,並且提供相同的應用程序,在首次訪問的時候,均會設置cookie信息,在java程序中,其中會有JSESSIONID,在第二次訪問同樣的主機的時候,就不會再次設置這個cookie信息了。

    使用nginx進行反代的時候,nginx的主要配置文件如下所示:

 

 

    在nginx的時候,主要的就是使用ip_hash。

    在使用apache進行反代的時候,可以使用http協議或者ajp協議,配置文件如下所示(在編譯的時候,需要幾個模塊mod_proxy,mod_proxy_http,mod_proxy_ajp,mod_proxy_balancer):

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
NameVirtualHost *:80
 
<proxy balancer: //tomserver >
 
     BalancerMember ajp: //192 .168.1.236:8009 loadfactor=1 route=mogilenode1
 
     BalancerMember ajp: //192 .168.1.238:8009 loadfactor=1 route=mogilenode3
 
     ProxySet stickysession=ROUTEID
 
< /proxy >
 
<VirtualHost *:80>
 
     DocumentRoot "/usr/local/apache/htdocs"
 
     ServerName www.kel.com
 
     ServerAlias www.kel.com
 
     ProxyVia On
 
     ProxyRequests Off
 
     ProxyPreserveHost On
 
     ProxyPass /status !
 
     <Location /balancer-manager >
 
         SetHandler balancer-manager
 
         ProxyPass !
 
         order allow,deny
 
         allow from all
 
     < /Location >
 
     ProxyPass  / balancer: //tomserver/
 
     ProxyPassReverse  / balancer: //tomserver/
 
     ErrorLog "logs/www.kel.com-error_log"
 
     CustomLog "logs/www.kel.com-access_log" common
 
< /VirtualHost >
 
<Location /status >
 
     SetHandler server-status
 
     Order allow,deny
 
     Allow from all
 
< /Location >
 
  
 
ExtendedStatus On

  

    使用http協議的配置如下:

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
NameVirtualHost *:80
 
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e;path=/" env =BALANCER_ROUTE_CHANGED
 
<proxy balancer: //tomserver >
 
     BalancerMember http: //192 .168.1.236:8080 loadfactor=1 route=mogilenode1
 
     BalancerMember http: //192 .168.1.238:8080 loadfactor=1 route=mogilenode3
 
     ProxySet stickysession=ROUTEID
 
< /proxy >
 
<VirtualHost *:80>
 
     DocumentRoot "/usr/local/apache/htdocs"
 
     ServerName www.kel.com
 
     ServerAlias www.kel.com
 
     ProxyVia On
 
     ProxyRequests Off
 
     ProxyPreserveHost On
 
     ProxyPass /status !
 
     <Location /balancer-manager >
 
         SetHandler balancer-manager
 
         ProxyPass !
 
         order allow,deny
 
         allow from all
 
     < /Location >
 
     ProxyPass  / balancer: //tomserver/
 
     ProxyPassReverse  / balancer: //tomserver/
 
     ErrorLog "logs/www.kel.com-error_log"
 
     CustomLog "logs/www.kel.com-access_log" common
 
< /VirtualHost >
 
<Location /status >
 
     SetHandler server-status
 
     Order allow,deny
 
     Allow from all
 
< /Location >
 
  
 
ExtendedStatus On

  

    在次兩種的配置下,tomcat需要配置如下信息:

?
1
<Engine name= "Catalina" defaultHost= "www.kel.com" jvmRoute= "mogilenode1" >

使用tomcat cluster演示會話保持

    在apache或者nginx端只要做負載均衡的配置即可,也就是在nginx中去掉ip_hash,在apache中去掉ProxySet stickysession=ROUTEID,主要的配置在tomcat的host標簽中,如下所示:

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
<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= "228.0.0.4"
 
                 port= "45564"
 
                 frequency= "500"
 
                 dropTime= "3000" />
 
     <Receiver className= "org.apache.catalina.tribes.transport.nio.NioReceiver"
 
               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 >

  

    在其中需要修改的組播地址,防止部署多個集群的時候,出現地址沖突,在部署的時候,可能出現的錯誤如下:

?
1
2
3
java.net.SocketException: No such device; No faulty members identified.
 
SEVERE: Unable to start cluster.

  

    主要是因為沒有設置網關地址或者組播地址,在其中如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@mogilenode2 extra] # route add default gw 192.168.1.1
 
[root@mogilenode2 extra] # route -n
 
Kernel IP routing table
 
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
 
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
 
192.168.249.0   0.0.0.0         255.255.255.0   U     0      0        0 eth1
 
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
 
169.254.0.0     0.0.0.0         255.255.0.0     U     1003   0        0 eth1
 
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0

  

    或者使用如下方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@mogilenode1 kel] # route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0
 
[root@mogilenode1 kel] # route -n
 
Kernel IP routing table
 
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
 
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
 
192.168.249.0   0.0.0.0         255.255.255.0   U     0      0        0 eth1
 
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 eth0
 
169.254.0.0     0.0.0.0         255.255.0.0     U     1003   0        0 eth1
 
224.0.0.0       0.0.0.0         240.0.0.0       U     0      0        0 eth0

    在應用程序的web.xml中,在web-app標簽中添加指令:

<distributable/>

    監聽的地址如下:

?
1
2
3
4
5
6
7
8
9
[root@mogilenode3 WEB-INF] # netstat -tnlp|grep java
 
tcp        0      0 :::8080                     :::*                        LISTEN      3920 /java          
 
tcp        0      0 ::ffff:192.168.1.238:4000   :::*                        LISTEN      3920 /java          
 
tcp        0      0 ::ffff:127.0.0.1:8005       :::*                        LISTEN      3920 /java          
 
tcp        0      0 :::8009                     :::*                        LISTEN      3920 /java

測試

    在第一次發送請求的時候,會設置cookie信息,如下所示:

 

 

    在第二次發送請求的時候,會帶上Cookie信息,如下:

 

 

    在JAVA程序中,只要收到了jsp或者servlet的請求,那么就會生成JSESSIONID。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM