• (转)负载均衡,回话保持,cookie


    servlet操作cookie:http://elf8848.iteye.com/blog/253198

    负载均衡,回话保持:http://www.cnblogs.com/qq78292959/archive/2012/12/27/2835950.html

    了解负载均衡 回话保持session同步

    一,什么负载均衡

    一个新网站是不要做负载均衡的,因为访问量不大,流量也不大,所以没有必要搞这些东西。但是随着网站访问量和流量的快速增长,单台服务器受自身硬件条件的限制,很难承受这么大的访问量。在这种情况下,有二种方案可以选择: 
    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语言都提供了会话保持时间的设定session.gc_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不能完全利用内存,会产生内存碎片,如果存储块不足,还会产生内存溢出。

    四,总结

    上面三种方法都是可行的 
    第一种方法,最影响系统速度的那种,不推荐使用; 
    第二种方法,效果不错,不过安全隐患一样的存在; 
    第三种方法,个人觉得第三种方法是最好的,推荐大家使用;

    转自:http://bbs.linuxtone.org/forum.php?mod=viewthread&tid=18212

    用到的类 javax.servlet.http.Cookie

    构造cookie 的方法 :  new Cookie(键,值)
    构造函数如下:
    Cookie(java.lang.String name, java.lang.String value)

    把cookie发送给客户端
    HttpServletResponse.addCookie(javax.servlet.http.Cookie)

    取得客户浏览器的cookie,返回的是数组
    HttpServletRequest.getCookies()

    getComment/setComment 

    获取/设置Cookie的注释。

    getDomain/setDomain
      获取/设置Cookie适用的域。一般地,Cookie只返回给与发送它的服务器名字完全相同的服务器。使用这里的方法可以指示浏览器把Cookie返回给同一域内的其他服务器。注意域必须以点开始(例如.sitename.com),非国家类的域(如.com,.edu,.gov)必须包含两个点,国家类的域(如.com.cn,.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:WindowsCookies,在Windows NT/2000/ XP的计算机中,Cookie文件的存放位置为C:Documents and Settings用户名Cookie文件夹。

    --------------------------------

    下面是代码,是直接从项目中实际代码

    Java代码  收藏代码
    1. /** 
    2.  * 设置SSO认证标识(把用户名,密码 写入客户端浏览器的cookie),关闭浏览器后,cookie立即失效 
    3.  *  
    4.  * @param response 
    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 编码,CookieUtil.encode()是BASE64编码方法,略..  
    16.     oItem = new Cookie("SSO", CookieUtil.encode(sSession));  
    17.     oItem.setDomain(.google.com);  //请用自己的域  
    18.     oItem.setMaxAge(-1); //关闭浏览器后,cookie立即失效          
    19.     oItem.setPath("/");  
    20.     response.addCookie(oItem);  
    21. }  
    Java代码  收藏代码
    1. /** 
    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 = request.getCookies();  
    10.     if (oCookies != null)  
    11.     {  
    12.         for (final Cookie oItem : oCookies)  
    13.         {  
    14.             final String sName = oItem.getName();  
    15.   
    16.             if (sName.equals("SSO"))  
    17.             {  
    18.                 final String sSession = CookieUtil.decode(oItem.getValue()); //解码 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. }  
  • 相关阅读:
    区块链学习笔记
    Ubuntu下Maven配置与Maven项目创建教程
    Java数字签名——ECDSA算法
    Java数字签名——DSA算法
    Java数字签名——RSA算法
    Python——Web.py詳解
    Flask從入門到入土(五)——Flask与数据库
    Flask從入門到入土(四)——登錄實現
    Flask從入門到入土(三)——Web表單
    Flask從入門到入土(三)——模板
  • 原文地址:https://www.cnblogs.com/wrencai/p/5042373.html
Copyright © 2020-2023  润新知