锁定老帖子 主题:关于rails大容量网站部署的性能讨论
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-05-15
quaff 写道 robbin 写道 引用 第三次访问变成clone1
虽然clone1是已经创建了session 但是这个session id不见了,于是又创建一个新的session 这个session id不会不见的。除非你已经关闭浏览器了,既然关闭浏览器,那么当然session就没有了。 session id是不会不见的,但是拿clone2的session id去clone 1里面是取不到session的,会通过你设置的保存userid的cookie再去创建一个session 可能会有这个问题,我没有验证过。 不过我现在倾向于根本不使用session,因为这种使用方式,当用户修改信息的时候,难于在多个节点之间进行同步修改。因此一定要session信息的话,恐怕也只能往分布式Cache里面设置了。 |
|
返回顶楼 | |
发表时间:2006-05-15
robbin 写道 quaff 写道 robbin 写道 引用 第三次访问变成clone1
虽然clone1是已经创建了session 但是这个session id不见了,于是又创建一个新的session 这个session id不会不见的。除非你已经关闭浏览器了,既然关闭浏览器,那么当然session就没有了。 session id是不会不见的,但是拿clone2的session id去clone 1里面是取不到session的,会通过你设置的保存userid的cookie再去创建一个session 可能会有这个问题,我没有验证过。 不过我现在倾向于根本不使用session,因为这种使用方式,当用户修改信息的时候,难于在多个节点之间进行同步修改。因此一定要session信息的话,恐怕也只能往分布式Cache里面设置了。 不用session,权限怎么控制?比如根据不同的用户显示不同的连接,一般都是用tag取得session里面的值,acegi也是用session保存信息的 |
|
返回顶楼 | |
发表时间:2006-05-15
我觉得在节点数不多时可以考虑采用Session复制技术做群集,必要时用专用的光纤网卡和光纤交换机,这样应该可以支撑较多节点。
weblogic 的群集session复制可以控制在“主、从”两个节点间进行,占用带宽较小,可以参照其实现类似的session复制。 |
|
返回顶楼 | |
发表时间:2006-05-16
robbin 写道 引用 第三次访问变成clone1
虽然clone1是已经创建了session 但是这个session id不见了,于是又创建一个新的session 这个session id不会不见的。除非你已经关闭浏览器了,既然关闭浏览器,那么当然session就没有了。 我是指client保存的clone1的session id不见了 (我还不至于要讨论session什么原理,被人看小了) client保存的只有一个session id,那是clone1的还是clone2的呢? 如果load balance突然改了clone呢? 我是说,我们用jk Sticky session来解决这个问题的 请问你的load balance方案是怎么解决的? 如果你退一步说还是完全不用session好了 我就觉得这个方案还可以接受 |
|
返回顶楼 | |
发表时间:2006-05-16
zgd 写道 robbin 写道 引用 第三次访问变成clone1
虽然clone1是已经创建了session 但是这个session id不见了,于是又创建一个新的session 这个session id不会不见的。除非你已经关闭浏览器了,既然关闭浏览器,那么当然session就没有了。 我是指client保存的clone1的session id不见了 (我还不至于要讨论session什么原理,被人看小了) client保存的只有一个session id,那是clone1的还是clone2的呢? 如果load balance突然改了clone呢? 我是说,我们用jk Sticky session来解决这个问题的 请问你的load balance方案是怎么解决的? 如果你退一步说还是完全不用session好了 我就觉得这个方案还可以接受 你理解错了,robbin用来保存用户id的cookie不是tomcat存sessionid的那个cookie。 第一次访问clone1,没有登录,要求登录,我们自己生成存用户id的cookie(cookie1),同时tomcat会生成session1,sessionid存在cookie2中,同时我们自己在session1中setAttribute("userInfo",userInfo)。 然后访问clone2,tomcat自动生成session2,sessionid存在cookie3中,我们自己getAttribute("userInfo")读不到值,但是能读到存userId的cookie1,因此根据userId查询用户信息,然后在session2上setAttribute("userInfo",userInfo)。 这个时候,浏览器有两个tomcat的session,同时还有我们自己存userId的cookie。 再访问clone1的时候直接得到session1了,怎么会不停的创建呢? |
|
返回顶楼 | |
发表时间:2006-05-16
quaff 写道 AreYouOK? 写道 robbin 写道 AreYouOK? 写道 robbin 写道 多说一句cookie和session的群集解决方案。我现在是这样做的:
用户登陆的时候给他一个cookie,存放userId,使用32位uuid(Hibernate生成),不使用int,是为了避免被hack。此外同时给这个用户分配一个Session,存放user对象。 然后我再写一个webwork Interceptor,拦截所有的动态访问请求,如果他有cookie,但是没有session,就根据cookie里面的userId查数据库,给他session里面放入user。 这样就很完美了,例如用户在clone1上面登陆,然后用户请求被分发到clone2,这个时候clone2上面有cookie无session,但是我的拦截器会用cookie查数据库给他session。这样每个节点只需要访问一次数据库设置session而已。而应用程序里面照常使用session,从session里面拿user对象,不需要改一行代码。只要该节点有session,就直接使用session,如果该节点无session,就从cookie里面去userId访问数据库设置一次session。兼顾了性能和群集部署的无状态,哈哈,完美吧。 好像安全有问题 如果我没有理解错的话,放在cookie里面的那个userId和数据库里面存的userId是相同的吧,那我只要记下这个cookie的名字和userId,以后每次都能伪造出这个cookie绕过登录了。 url里面可能有其他用户的userId(比如查看用户资料的url,应该是类似这样的吧viewUser?userId=xxx),那么我得到其他用户的userId,也能伪造出其他用户的cookie登录了 即使cookie是加密过的userId,至少在一个已经登录的浏览器里面得到cookie的值,就能伪造出这个cookie以这个浏览器的当前登录用户进入 主要问题就在于,同一个用户记录登录信息的cookie,不管什么时候登录,它始终是同一个值。而tomcat管理的jsessionId是随机生成的,即使得到这个cookie的值,在session超时以后就不再有效 所以当你不在自己的私人机器上面使用的时候,登陆系统请不要选择“记住cookie” 嗯,如果这是解决方案的话,那我太伤心了 假如系统是一个web mail,那我可以趁朋友不再电脑前面的时候偷到这个永久有效的cookie(或者通过其它的手段如sniffer等),以后就可以一直偷看信件了。这个朋友知道信件被偷看后,居然束手无策,连修改密码也没有用,只能把这个id费掉了。假如这个系统就是JE论坛,又会如何? 要是不用这种单点登录的认证方式,只能自己实现随机的通行令牌了,象CAS那样,需要做一个专门的认证server来维护session。 google就可以通过copy cookie来绕过等录,可以拿ie和firefox试验一下 这是废话,所有用cookie保存sessionid的系统(基本上所有的系统)都是这样的。 问题在于,通常情况下,我们让tomcat自己管理session,sessionid是随机生成的,session超时以后就不再有效,而这里的这个cookie是永久有效的。 所有生成永久有效cookie的方式我认为都是有不安全的。 想到google我想起一个办法,google可以让你记住用户名自动登录,但是只有效两个星期。也就是说,最多两个星期以后就会更换加密密钥。 那么用robbin的方式也可以每天凌晨0点更换一个密钥加密userId。每个tomcat同时有两个密钥,昨天的和今天的,保持两个密钥是考虑到session存在的时间跨越一天的情况。每个userId的cookie过来先用昨天的密钥解(可能是昨天23:55生成的,但是现在时间是今天0:05),不行就用今天的密钥解。 这样每个cookie最多有效两天。算是解决了永久有效的问题,麻烦之处在于要在tomcat之间同步密钥。 |
|
返回顶楼 | |
发表时间:2006-05-16
acegi生成的自动登陆cookie:
username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key) |
|
返回顶楼 | |
发表时间:2006-05-16
似乎从Cluster的讨论演变成了SSO......
其实PHP就可以承受非常大的访问量,这点上不比Java差,用Squid + Apache + PHP + MySQL就可以具有非常高的性能。 而且用Squid之后可以很好的提升站点的性能,用反向代理比纯粹的Request转发具有更好的性能,前者具有自己的缓存机制,把静态数据的缓存做在这一层具有更好的性能。 SSO方面用过CAS,配置和实现都非常简单易用了,可以说比自己写Cookies还容易。对于Session的复制方面,如果可能的话,还是采用分布式缓存机制来做,比存数据库和各服务器互相复制的代价低。 |
|
返回顶楼 | |
发表时间:2006-05-16
AreYouOK? 写道 你理解错了,robbin用来保存用户id的cookie不是tomcat存sessionid的那个cookie。 第一次访问clone1,没有登录,要求登录,我们自己生成存用户id的cookie(cookie1),同时tomcat会生成session1,sessionid存在cookie2中,同时我们自己在session1中setAttribute("userInfo",userInfo)。 然后访问clone2,tomcat自动生成session2,sessionid存在cookie3中,我们自己getAttribute("userInfo")读不到值,但是能读到存userId的cookie1,因此根据userId查询用户信息,然后在session2上setAttribute("userInfo",userInfo)。 这个时候,浏览器有两个tomcat的session,同时还有我们自己存userId的cookie。 再访问clone1的时候直接得到session1了,怎么会不停的创建呢? 没理解。 按照robbin的方案,浏览器端是不知道访问了clone1还是clone2的,而且部署在clone1/clone2上的程序也不知道自己是部属在哪个节点上的,而且,这个程序也不应该为了群集而作特别的处理。 另外,浏览器得到的域名都是前端分发请求的那个服务器的域名。这样,实际上这些cookie都保存在一个cookie文件(文件名应当是域名)里面,而且,因为tomcat的sessionid用的是同一个名字,好像都是jsessionid吧,并且cookie的域名和路径也必然是一样的,按照RFC2109 .... 4.3.3 Cookie Management If a user agent receives a Set-Cookie response header whose NAME is the same as a pre-existing cookie, and whose Domain and Path attribute values exactly (string); match those of a pre-existing cookie, the new cookie supersedes the old. However, if the Set- Cookie has a value for Max-Age of zero, the (old and new); cookie is discarded. Otherwise cookies accumulate until they expire (resources permitting);, at which time they are discarded. .... 第一次从clone1跳到clone2的时候,就会把cookie里面的jsessionid从clone1的换成clone2的。然后再跳回去的时候,因为不可能根据clone2的sessionid从clone1里面取出session来,所以只能新生成一个session,然后从cookie里面取出userid,从数据库里面取出userinfo. 这样,就不停的在两个clone之间跳舞了。还不如不把userinfo保存在session里面,每次直接在数据库中取好了。 如果要在session里面放东西,那么session的同步复制问题肯定不能避免。还是不在session里搞东西的好。不过那样一来,代价就有点大了,就是说为了群集而修改了程序模型。 最好是httpsession可以提供一个缓存插口......... |
|
返回顶楼 | |
发表时间:2006-05-16
这个帖子是有些跑题,要不拆贴了吧,我觉得跑题的讨论还是有意义的
引用 没理解。
按照robbin的方案,浏览器端是不知道访问了clone1还是clone2的,而且部署在clone1/clone2上的程序也不知道自己是部属在哪个节点上的,而且,这个程序也不应该为了群集而作特别的处理。 另外,浏览器得到的域名都是前端分发请求的那个服务器的域名。这样,实际上这些cookie都保存在一个cookie文件(文件名应当是域名)里面,而且,因为tomcat的sessionid用的是同一个名字,好像都是jsessionid吧,域名和路径也必然是一样的,按照RFC2109 我弄错了,好像是有问题。 两个tomcat会生成相同的cookie,域名,路径都相同,cookie的名字也一样 引用 acegi生成的自动登陆cookie: username + ":" + expiryTime + ":" + Md5Hex(username + ":" + expiryTime + ":" + password + ":" + key) 这是个不错的主意,比我想出来的办法好。不过我不明白要password做什么 userName+对称加密的过期时间 就应该可以了 |
|
返回顶楼 | |