锁定老帖子 主题:关于rails大容量网站部署的性能讨论
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-05-12
robbin 写道 firebody 写道 robbin 写道 呵呵,我现在设计的网站部署方案几乎就是照抄rails的群集部署方案:
lighthttpd作为web proxy,兼有处理静态资源(js,css,images),页面cache,和loadbalance/failover的功能(如果不是为了failover,我直接用iptables进行端口转发是速度最快的loadbalance); 后面n个tomcat clone来处理业务,不使用Hibernat二级缓存,用户ID使用cookie,不在session里面保存和标示状态,因此tomcat clone的数量可以近乎无限扩展。 memcached用来作为全局共享变量的holder,在spring里面配置一个bean去封装对memcached的访问,这样访问memcached的全局共享变量和过去访问JVM内部的全局共享变量的方式从编程接口上来说就根本没有任何区别了,桀桀。 好完美的一个群集部署方案啊,谁来挑挑刺? 感觉robbin 似乎遗漏了很重要的一点。 PersistenceContext在你说的水平扩展方案中不能选择extended scope 的,而是使用transaction scope的。 二级缓存的话,一个办法就是干脆不用,这样一来,ejb在二级缓存优化那一块都白做了。 另外一种选择,提供一种共享/集群的二级缓存策略。 不过性能我就那不准了。 PersistenceContext我认为transaction scope是最合理的。我看Hibernate也是这么推荐的。而且PersistenceContext要跨进程的话,还有意义吗? JVM级别的支持群集的二级缓存要看用什么了,据说像Tangosol Coherence性能就非常好。只要能够接受群集Cache的同步开销(想像一下10个节点的Cache同步),也可以用二级缓存。而且我觉得很重要的一点是,我们也完全可以用memcached来做EJB3的二级缓存。 PersistenceContext我认为transaction scope是最合理的。我看Hibernate也是这么推荐的。而且PersistenceContext要跨进程的话,还有意义吗? 不考虑复杂的并发冲突的话,PersistenceContext的短生命周期可以在大多数情况下工作良好。 |
|
返回顶楼 | |
发表时间:2006-05-12
粗略看了一下memcached的文档, 用法挺简单.
(这里有人编译了windows下的版本: http://www.ctoforaday.com/archives/000039.html) 但局限性也很明显, --由于没有事务锁定, 很容易读到脏数据. |
|
返回顶楼 | |
发表时间:2006-05-12
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。兼顾了性能和群集部署的无状态,哈哈,完美吧。 用户跳到clone1再跳回clone2还不是要创建一个新的session 没有sticky session的功能 理论上用户会不停clone1 clone2的跳,那就是clone1和clone2不停创建session了 |
|
返回顶楼 | |
发表时间:2006-05-12
zgd 写道 用户跳到clone1再跳回clone2还不是要创建一个新的session
没有sticky session的功能 理论上用户会不停clone1 clone2的跳,那就是clone1和clone2不停创建session了 实际上这样的事情发生几率不高 恩,另外这个再创建session 的开销,是可以由memcached之类的全局缓冲来作一些抵消 |
|
返回顶楼 | |
发表时间:2006-05-12
zgd 写道 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。兼顾了性能和群集部署的无状态,哈哈,完美吧。 用户跳到clone1再跳回clone2还不是要创建一个新的session 没有sticky session的功能 理论上用户会不停clone1 clone2的跳,那就是clone1和clone2不停创建session了 不会的,第一次访问设置好session,以后访问直接就拿session了。 |
|
返回顶楼 | |
发表时间:2006-05-13
引用 不会的,第一次访问设置好session,以后访问直接就拿session了。 问题是如果用户在跳来跳去的过程中对session有所改动呢,是不是session里面只能放登陆之后稳定的东西,其他的或者放到cookie或者放到memcache里面? |
|
返回顶楼 | |
发表时间:2006-05-13
shinwell 写道 粗略看了一下memcached的文档, 用法挺简单.
(这里有人编译了windows下的版本: http://www.ctoforaday.com/archives/000039.html) 但局限性也很明显, --由于没有事务锁定, 很容易读到脏数据. 这要应用自己决定何时直接写入数据库并刷新cache。虽然刷新代价很大,对读多写少的web应用还是可以接受的。 |
|
返回顶楼 | |
发表时间:2006-05-14
robbin 写道 zgd 写道 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。兼顾了性能和群集部署的无状态,哈哈,完美吧。 用户跳到clone1再跳回clone2还不是要创建一个新的session 没有sticky session的功能 理论上用户会不停clone1 clone2的跳,那就是clone1和clone2不停创建session了 不会的,第一次访问设置好session,以后访问直接就拿session了。 cookie里面保存的sessionid变了 |
|
返回顶楼 | |
发表时间:2006-05-15
zgd 写道 理论上用户会不停clone1 clone2的跳,那就是clone1和clone2不停创建session了
这个问题可以用LVS解决。 |
|
返回顶楼 | |
发表时间:2006-05-15
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超时以后就不再有效 |
|
返回顶楼 | |