(转)负载均衡,回话保持,cookie
⼀,什么负载均衡
⼀个新⽹站是不要做负载均衡的,因为访问量不⼤,流量也不⼤,所以没有必要搞这些东西。但是随着⽹站访问量和流量的快速增长,单台服务器受⾃⾝硬件条件的限制,很难承受这么⼤的访问量。在这种情况下,有⼆种⽅案可以选择:
1,对单台服务器的硬件进⾏更新,由双核的变成四核的,内存加⼤等。
2,增加服务器的台数,来分担服务器的负担。以实现增加⽹络带宽,增加服务器的处理能⼒的⽬的。
第⼀种⽅法可以理解为纵向发展,这种⽅法总是有限。
第⼆种⽅法才是解决问题的正确选择
实现负载均衡的⽅法,⼤⾄分为⼆个⽅向,⼀种是⽤软件来实现负载均衡,另⼀种是硬件实现负载均衡(包括结合硬件和软件)⽤软件来实现负载均衡,实现负载均衡的过程,⾃⾝也要消耗⼀些系统资源,响应时间增加。例如:LVS,nginx,haproxy,apache等这些基于应⽤层的负载均衡软件,适合那些访问量不是特别⼤的⽹站。如果像sina,163这样⼤访量的⽹站,⽤硬件来实现负载均衡是最明志的选择。
负载均衡的算法很多,有根据请求数来进⾏负载均衡的,有根IP来负载均衡的,有根据流量的等等。我经常会⽤的⼆种算法。
⼀个是根据请求数
a,可以实现各台服务器都能⽐较平均分担客户的请求,其中⼀台服务器down掉的话也不会造成不好的影响。
b,服务器间的状态要同步,如session,需要其他⼿段来同步这些状态。
⼀个是根据IP
a,ip_hash算法可以把⼀个ip映射到⼀台服务器上,这样可以解决session同步的问题
b,ip_hash也有不好的地⽅就是,假如其中的⼀台服务器down掉的话,映射到这台的服务器的⽤户就郁闷了。
c,ip_hash容易导致负载不均衡的情况,现在河蟹政府对google的搜索关键词进⾏过滤,你会经常发现google打不开,但是过⼀会就好了。这让那些google的爱好者们郁闷不已,很多⽤户都到国外代理去了,狗急跳墙,⼈急帆樯。如果这样的话,这些代理会被分到同⼀个服务器,会导致负载不均衡 ,甚⾄失效。
⼆,什么是会话保持,有什么作⽤
会话保持是指在负载均衡器上有⼀种机制,在作负载均衡的同时,还保证同⼀⽤户相关连的访问请求会被分配到同⼀台服务器上。
会话保持有什么作⽤呢,举例说明⼀下
如果有⼀个⽤户访问请求被分配到服务器A,并且在服务器A登录了,并且在很短的时间,这个⽤户⼜发出了⼀个请求,如果没有会话保持功能的话,这个⽤户的请求很有可能会被分配到服务器B去,这个时候在服务器B上是没有登录的,所以你要重新登录,但是⽤户并不知道⾃⼰的请求被分配到了哪⾥,⽤户的感觉就是登录了,怎么⼜要登录,⽤户体验很不好。
还有你在淘宝上⾯买东西,从登录=》拍得东西=》添加地址=》付款,这是⼀个⼀系列的过程,也可以理解成⼀次操作过程,所有这⼀系列的操作过程都应当由⼀台服务器完成,⽽不能被负载均衡器分配到不同的服务器上。
会话保持都会有时间的限制(映射到固定某⼀台的服务器除外,如:ip_hash),各种负载均衡⼯具都会提供这种会话保持时间的设
置,LVS,apache等。连php语⾔都提供了会话保持时间的设定_maxlifetime会话保持时间
的设定要⼤于session⽣存时间的设定,这样可以减少需要同步session的情况,但是不能杜绝。所以同步session还是要做的。
三,session同步
为什么要进⾏session同步,说会话保持的时候已经提到了。具体⽅法请参考web集时session同步的3种⽅法
web集时session同步的3种⽅法
在做了web集后,你肯定会⾸先考虑session同步问题,因为通过负载均衡后,同⼀个IP访问同⼀个页⾯会被分配到不同的服务器上,如果session不同步的话,⼀个登录⽤户,⼀会是登录状态,⼀会⼜不是登录状态。所以本⽂就根据这种情况给出三种不同的⽅法来解决这个问题:
1、利⽤数据库同步session
在做多服务器session同步时我没有⽤这种⽅法,如果⾮要⽤这种⽅法的话,我想过⼆种⽅法:
a,⽤⼀个低端电脑建个数据库专门存放web服务器的session,或者,把这个专门的数据库建在⽂件服务器上,⽤户访问web服务器时,会去这个专门的数据库check⼀下session的情况,以达到session同步的⽬的。
b,这种⽅法是把存放session的表和其他数据库表放在⼀起,如果mysql也做了集了话,每个mysql节点都要有这张表,并且这张session表的数据表要实时同步。
说明:⽤数据库来同步session,会加⼤数据库的负担,数据库本来就是容易产⽣瓶颈的地⽅,如果把session还放到数据库⾥⾯,⽆疑是雪上加霜。上⾯的⼆种⽅法,第⼀点⽅法较好,把放session的表独⽴开来,减轻了真正数据库的负担
2、利⽤cookie同步session
session是⽂件的形势存放在服务器端的,cookie是⽂件的形势存在客户端的,怎么实现同步呢?⽅法很简单,就是把⽤户访问页⾯产⽣的session放到cookie⾥⾯,就是以cookie为中转站。你访问web服务器A,产⽣了session把它放到cookie⾥⾯了,你访问被分配到web服务器B,这个时候,web服务器B先判断服务器有没有这个session,如果没有,在去看看客户端的cookie⾥⾯有没有这个session,如果也没有,说明session真的不存,如果cookie⾥⾯有,就把cookie⾥⾯的sessoin同步到web服务器B,这样就可以实现session的同步了。
说明:这种⽅法实现起来简单,⽅便,也不会加⼤数据库的负担,但是如果客户端把cookie禁掉了的话,那么session就⽆从同步了,这样会给⽹站带来损失;cookie的安全性不⾼,虽然它已经加了密,但是还是可以伪造的。
3、利⽤memcache同步session
memcache可以做分布式,如果没有这功能,他也不能⽤来做session同步。他可以把web服务器中的内存组合起来,成为⼀个"内存池",不管是哪个服务器产⽣的sessoin都可以放到这个"内存池"中,其他的都可以使⽤。
优点:以这种⽅式来同步session,不会加⼤数据库的负担,并且安全性⽐⽤cookie⼤⼤的提⾼,把session放到内存⾥⾯,⽐从⽂件中读取要快很多。
缺点:memcache把内存分成很多种规格的存储块,有块就有⼤⼩,这种⽅式也就决定了,memcache不能完全利⽤内存,会产⽣内存碎⽚,如果存储块不⾜,还会产⽣内存溢出。
四,总结
上⾯三种⽅法都是可⾏的
第⼀种⽅法,最影响系统速度的那种,不推荐使⽤;
第⼆种⽅法,效果不错,不过安全隐患⼀样的存在;
第三种⽅法,个⼈觉得第三种⽅法是最好的,推荐⼤家使⽤;
⽤到的类 javax.servlet.http.Cookie
构造cookie 的⽅法 :  new Cookie(键,值)
构造函数如下:
Cookie(java.lang.String name, java.lang.String value)
把cookie发送给客户端
HttpServletResponse.addCookie(javax.servlet.http.Cookie)
取得客户浏览器的cookie,返回的是数组
getComment/setComment
获取/设置Cookie的注释。
getDomain/setDomain
  获取/设置Cookie适⽤的域。⼀般地,Cookie只返回给与发送它的服务器名字完全相同的服务器。使⽤这⾥的⽅法可以指⽰浏览器把Cookie返回给同⼀域内的其他服务器。注意域必须以点开始(例如.sitename),⾮国家类的域(如,.edu,.gov)必须包含两个点,国家类的域(如,.edu.uk)必须包含三个点。
getMaxAge/setMaxAge
  获取/设置Cookie过期之前的时间,以秒计。如果不设置该值,则Cookie只在当前会话内有效,即在⽤户关闭浏览器之前有效,⽽且这些Cookie不会保存到磁盘上。
若⽣存时间为负值,代表浏览器关闭Cookie即消失。⽣存时间为0,代表删除Cookie,⽣存时间为正数,代表Cookie存在多少秒。
getName/setName
  获取/设置Cookie的名字。本质上,名字和值是我们始终关⼼的两个部分。由于HttpServletRequest的getCookies⽅法返回的是⼀个Cookie对象的数组,因此通常要⽤循环来访问这个数组查特定名字,然后⽤getValue检查它的值。
getPath/setPath
  获取/设置Cookie适⽤的路径。如果不指定路径,Cookie将返回给当前页⾯所在⽬录及其⼦⽬录下的所有页⾯。这⾥的⽅法可以⽤来设定⼀些更⼀般的条件。例如,someCookie.setPath("/"),此时服务器上的所有页⾯都可以接收到该Cookie。
getSecure/setSecure
  获取/设置⼀个boolean值,该值表⽰是否Cookie只能通过加密的连接(即SSL)发送。
getValue/setValue
  获取/设置Cookie的值。如前所述,名字和值实际上是我们始终关⼼的两个⽅⾯。不过也有⼀些例外情况,⽐如把名字作为逻辑标记(也就是说,如果名字存在,则表⽰true)。
getVersion/setVersion
  获取/设置Cookie所遵从的协议版本。默认版本0(遵从原先的Netscape规范);版本1遵从RFC 2109 , 但尚未得到⼴泛的⽀持。
⼏个Cookie⼯具函数,获取指定名字的Cookie值
  该函数是ServletUtilities.java的⼀部分。getCookieValue通过循环依次访问Cookie对象数组的各个元素,寻是否有指定名字的Cookie,如到,则返回该Cookie的值;否则,返回参数中给出的默认值。getCookieValue能够在⼀定程度上简化Cookie值的提取。
cookie保存在哪⾥
在Windows 9X系统计算机中,Cookie⽂件的存放位置为C:\Windows\Cookies,在Windows NT/2000/ XP的计算机中,Cookie ⽂件的存放位置为C:\Documents and Settings\⽤户名\Cookie⽂件夹。
--------------------------------
下⾯是代码,是直接从项⽬中实际代码
2.  * 设置SSO认证标识(把⽤户名,密码 写⼊客户端浏览器的cookie),关闭浏览器后,cookie⽴即失效
3.  *
4.  * @param response
session如何设置和读取5.  *            HttpServletResponse
6.  * @param userName
7.  *            ⽤户名
8.  * @param password
9.  *            密码
10.  */
11. public static void setReffer(final HttpServletResponse response, final String userName, final String password)
12. {
13.    final String sSession = password + userName;  //密码是SHA1加密,长度为40个字符(160位)
14.    Cookie oItem;
15.    // 因为Cookie 中不允许保存特殊字符, 所以采⽤ BASE64 编码,de()是BASE64编码⽅法,略..
16.    oItem = new Cookie("SSO", de(sSession));
17.    oItem.setDomain(.google);  //请⽤⾃⼰的域
18.    oItem.setMaxAge(-1); //关闭浏览器后,cookie⽴即失效
19.    oItem.setPath("/");
20.    response.addCookie(oItem);
21. }
2.  * 认证SSO标识(从客户端浏览器读⼊cookie, 并取得⽤户名、密码,不能取得时返回null)
3.  *
4.  * @param request
5.  * @return 返回从cookie中取得的⽤户名、密码,不能取得时返回null.String[0]中保存⽤户名,String[1]中保存密码
6.  */
7. public static String[] checkReffer(final HttpServletRequest request)
8. {
9.    final Cookie[] oCookies = Cookies();
10.    if (oCookies != null)
11.    {
12.        for (final Cookie oItem : oCookies)
13.        {
14.            final String sName = Name();
15.
16.            if (sName.equals("SSO"))
17.            {
18.                final String sSession = CookieUtil.Value()); //解码 CookieUtil.decode()是BASE64解码⽅法,
略..
19.                if (sSession.length() > 40)
20.                {
21.                    // 获得存储在 Cookies 中的⽤户名称和密码
22.                    final String sUser = sSession.substring(40);
23.                    final String sPass = sSession.substring(0, 40);
24.                    final String[] strArr =
25.                    { sUser, sPass };
26.                    return strArr; //返回⽤户名,密码
27.                }
28.            }
29.        }
30.    }
31.    return null;
32. }

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。