某大型社区网站系统

流量集中

大部分bbs的流量都是冷热不均,相差很大,热帖一天可达数百万访问,冷贴就是一个访问量也没有。热帖主要是在列表第一版的帖子,和精华贴,这些帖子的流量加起来至少占到整个bbs流量的50%以上。虽然热帖占了很大流量,但这些热帖的数量不会太多,所以用缓存架构的话对这些热帖优化程度就很大,对热帖优化程度大相当于对整个系统优化程度大。(特点:热数据少而集中,用缓冲可以极大提高性能

实时性

每发或回复一张贴,就必须让这张贴立刻发布出去,用户能马上看到。所以用到缓存架构的话,这个缓存要能实时更新。

回帖少,看帖多

因为bbs也是由人来组成,所以这个现象是不可改变的,1/10是比较保守,估计大部分都在1/100以下吧。虽然有实时性,但是因为回帖少看帖多,意味着触发更新缓存的频率少,比率越小,优化效果越大。(特点:r/w的比例比较大,多read少write,cdn和缓冲比较有效


系统主要解决问题

bbs因为是实时系统,所以常规上都是设计为纯动态+直读数据库架构,纯动态架构的性能问题是一个突出问题,在达到一定访问量或受到一些攻击时,系统就容易挂掉,严重的时候数据库还会损坏,数据库坏掉的话服务恢复时间就很长。更困惑人的是,以往即使知道性能是个问题,但是去解决这个问题的风险很大,需要对系统进行很大的变动。做很大的变动就难免会引发很多新的bug,这样很容易导致大量的网友流失。

今天讲的这个架构基本可以解决性能问题,而且对程序部分的修改不算很多,而且有一个成形的实施步骤,按步骤就能做完。

架构图

前面是lvs负载均衡,lvs下面挂几台squid,squid的配置统一指向到中层代理nginx,由nginx负载均衡到几台应用服务器,后面就是数据库。其中lvs安装调试起来可能麻烦一些,可以用haproxy替换,haproxy是目前7层纯代理中性能最好的,安装配置和出问题时处理也相对简单。squid的配置比较特别的是缓存时间可以尽可能长,对单贴的缓存时间可以配到一天以上,目的是让帖子尽量不要过期,只有后端发来更新的请求才会更新。
(lvs(haproxy) -> squid(缓冲,rewirte) -> nginx(运行gzip等压缩) -> app server -> db)

高性能

因为有了缓存,很多帖子都被缓存住了,请求的时候当然直接从缓存出去,不会触及到应用服务器,所以效率很高。

gzip压缩可以减少页面流量80%左右,100k的页面可以压到20k这样,一方面减少了带宽,另一方面用户访问起来感觉也会快很多。这个是在中层代理的nginx上完成的,用nginx做这个事情在效率方面没有任何感觉。
(特点:压缩可以解决带宽和存储容量问题,主要是以cpu计算换来空间容量的减少,在静态页面方面,效果更为明显)

应用服务器可以看作一个很慢的,很容易挂掉的系统,中层代理的负载均衡可以将它们保护起来,在这里用nginx作负载均衡有几个优点:
1,可以用多端口,这样在一台服务器上可以多开几个应用服务器。(代理走80, 后端可以是8080, 8081等其他端口)
2、nginx可以在访问一个后端出错之后,将这个请求再发到另一个后端,这样基本可以保证每个请求都能返回正确的数据。

实时性静态化

因为用到了缓存,所以页面中有不少要修改的地方:
1、用rewrite把帖子变成一个.html结尾的文件,虽然squid也可以缓存带?的链接,但是rewrite技术可以使链接固定并且简洁,比如帖子有两个参数帖子id和分页的页数,用?有两个参数,如果把这两个参数的顺序调过来,那么squid就认为是两个链接,有两份缓存,更新缓存时就会漏掉一个。

2、squidclient是squid自带的一个程序,可以用它来观察squid的运行状态,和更新缓存,更新缓存的机制就是向squid发送一个特殊的请求让squid去删掉对应的缓存链接,然后下一次访问到这个链接的时候,squid就会重新去后端取这个链接的内容。

3、因为用到了缓存,页面上是不能直接放一些信息,比如用户登录状态,在动态程序中可以直接用程序语言读取显示,但在这个架构中只能把它从页面中除去,然后用javascript读取cookie来显示。有其它需求的话,还要用到ajax或json技术。
(注:变成了静态页面(可以利用缓冲) + 动态拉取ajax(及时性))

4、同样是因为有缓存,每次更新缓存都要花去一些时间, 为了加快速度,所以会用到异步更新缓存的机制(为啥异步更新会加快速度?貌似解决不了这个问题)。用到异步更新会出一个问题,当用户得到发帖成功的响应的时候,事实上这张贴还没有更新,如果让用户直接访问这张帖子,那他往往看不到自己刚发表的回帖,这会让用户联想到“审核”这个动作,感觉非常不好。所以这个发帖成功这个动作应该让用户看到“5秒后跳到某某页面”这样的提示,让他缓冲一下,这样程序就有足够的时间来执行更新缓存的动作了。另外一个是更新缓存时遇到分页帖子就不好处理,所以应让页面尽可能长,像猫扑天涯的帖子都很长,就是这个原因。
注:架构优化有时也需要和产品体验一起考虑

5、因为脱离了动态程序,所以之前如果是用动态程序直接统计点击量的话,点击量就会有问题,这时可以通过统计squid的log来统计帖子的点击量,然后再更新到后台的一个接口里。
(注:这里给出了一个新的思路:如果计算统计量?基于流水统计和后台接口merge的方式)


二级缓存的优点是可以进一步减少请求量,这里配置了4台缓存,意味着一个热门帖子每次更新都会更新这4台机器,这4台机器就会发出4个请求,用一台二级缓存就可以化为1个请求,理论上可以将请求优化掉3/4。 另外是squid这个服务器在一些情况下会出现某台机请求全部穿透的现象,这时二级缓存就可以拦截住这些量很大的请求。一般来说,一个系统用到二级缓存就基本足够了,没有必要用到三级。

缓存过期时间在nginx或squid做,比较方便,比如有个没有被缓存的页面,访问量突然很大,这时可以立刻调整它让它暂时被缓存住。

在nginx可以通过log观察,屏蔽掉一些ip和访问,比如一些设计不良的爬虫来爬页面,造成系统负载突增,可以直接将它的ip或user-agent屏蔽掉。
(access log是否一定会打开?)

权重和分流调节是lvs和nginx都有的功能,如果机器性能不均造成负载不均,或者有机器处于调试状态,可以调整他们的访问权重。lvs因为工作在http的第4层,所以分流功能不算太强,除了可以调权重,另外就是可以根据客户端ip分,还有根据后端负载动态分。nginx是7层代理,分配方式就更多,可以实现基于ip/url/header/后端响应速度等等来分。

高可用性就是说系统的稳固状态,最好的就是这个系统永远都能正常访问,无论什么时候访问都绝对能打得开,当然这世界上根本没有永远都能打开的系统了,所以我们也只能让它尽可能访问正常。在计算机系统中某一台单机的可用性都是不可靠的,单机即使软件性能做到很强,但是硬件也会有问题,所以要用到集群架构。

lvs通过双机热备,实时切换,可保证有故障时会自动换到备机。
squid直接利用lvs的故障屏蔽
nginx可利用自己写的程序来实现热备,也可以用lvs分到两台nginx上
应用服务器就是nginx集群
数据库就麻烦一些,现用的方案是通过程序判断来做双机热备

因为用到缓存架构,大量的流量都是通过缓存直接输出的,这样就可以轻松实现流量分配,一般的分流问题有两种,电信网通的分流和双线路分流,都可以做。

电信网通,在电信机房和网通机房各架一组缓存,中层代理和应用服务器都用一套。( set部署?)
多线路分流和电信网通分流差不多,就是比如两条100M的带宽,怎么一起服务。

权限划分,这个是大公司才会有的问题了,大公司分工比较细,比如我就是做运维的,所以我就主要管理前面的squid和nginx这个部分,应用服务器和数据库就让产品维护的兄弟去做,在性能优化有什么问题需要他们帮忙的,我只提供方案,让他们去实施。有部分要合作的,要想办法减少耦合度,像点击量统计这部分,他们设计一个接口,然后我去写统计log的脚本,然后往接口发。反过来也一样,我设计接口,然后他们发来。
流量集中

大部分bbs的流量都是冷热不均,相差很大,热帖一天可达数百万访问,冷贴就是一个访问量也没有。热帖主要是在列表第一版的帖子,和精华贴,这些帖子的流量加起来至少占到整个bbs流量的50%以上。虽然热帖占了很大流量,但这些热帖的数量不会太多,所以用缓存架构的话对这些热帖优化程度就很大,对热帖优化程度大相当于对整个系统优化程度大。(特点:热数据少而集中,用缓冲可以极大提高性能

实时性

每发或回复一张贴,就必须让这张贴立刻发布出去,用户能马上看到。所以用到缓存架构的话,这个缓存要能实时更新。

回帖少,看帖多

因为bbs也是由人来组成,所以这个现象是不可改变的,1/10是比较保守,估计大部分都在1/100以下吧。虽然有实时性,但是因为回帖少看帖多,意味着触发更新缓存的频率少,比率越小,优化效果越大。(特点:r/w的比例比较大,多read少write,cdn和缓冲比较有效


系统主要解决问题

bbs因为是实时系统,所以常规上都是设计为纯动态+直读数据库架构,纯动态架构的性能问题是一个突出问题,在达到一定访问量或受到一些攻击时,系统就容易挂掉,严重的时候数据库还会损坏,数据库坏掉的话服务恢复时间就很长。更困惑人的是,以往即使知道性能是个问题,但是去解决这个问题的风险很大,需要对系统进行很大的变动。做很大的变动就难免会引发很多新的bug,这样很容易导致大量的网友流失。

今天讲的这个架构基本可以解决性能问题,而且对程序部分的修改不算很多,而且有一个成形的实施步骤,按步骤就能做完。

架构图

前面是lvs负载均衡,lvs下面挂几台squid,squid的配置统一指向到中层代理nginx,由nginx负载均衡到几台应用服务器,后面就是数据库。其中lvs安装调试起来可能麻烦一些,可以用haproxy替换,haproxy是目前7层纯代理中性能最好的,安装配置和出问题时处理也相对简单。squid的配置比较特别的是缓存时间可以尽可能长,对单贴的缓存时间可以配到一天以上,目的是让帖子尽量不要过期,只有后端发来更新的请求才会更新。
(lvs(haproxy) -> squid(缓冲,rewirte) -> nginx(运行gzip等压缩) -> app server -> db)

高性能

因为有了缓存,很多帖子都被缓存住了,请求的时候当然直接从缓存出去,不会触及到应用服务器,所以效率很高。

gzip压缩可以减少页面流量80%左右,100k的页面可以压到20k这样,一方面减少了带宽,另一方面用户访问起来感觉也会快很多。这个是在中层代理的nginx上完成的,用nginx做这个事情在效率方面没有任何感觉。
(特点:压缩可以解决带宽和存储容量问题,主要是以cpu计算换来空间容量的减少,在静态页面方面,效果更为明显)

应用服务器可以看作一个很慢的,很容易挂掉的系统,中层代理的负载均衡可以将它们保护起来,在这里用nginx作负载均衡有几个优点:
1,可以用多端口,这样在一台服务器上可以多开几个应用服务器。(代理走80, 后端可以是8080, 8081等其他端口)
2、nginx可以在访问一个后端出错之后,将这个请求再发到另一个后端,这样基本可以保证每个请求都能返回正确的数据。

实时性静态化

因为用到了缓存,所以页面中有不少要修改的地方:
1、用rewrite把帖子变成一个.html结尾的文件,虽然squid也可以缓存带?的链接,但是rewrite技术可以使链接固定并且简洁,比如帖子有两个参数帖子id和分页的页数,用?有两个参数,如果把这两个参数的顺序调过来,那么squid就认为是两个链接,有两份缓存,更新缓存时就会漏掉一个。

2、squidclient是squid自带的一个程序,可以用它来观察squid的运行状态,和更新缓存,更新缓存的机制就是向squid发送一个特殊的请求让squid去删掉对应的缓存链接,然后下一次访问到这个链接的时候,squid就会重新去后端取这个链接的内容。
3、因为用到了缓存,页面上是不能直接放一些信息,比如用户登录状态,在动态程序中可以直接用程序语言读取显示,但在这个架构中只能把它从页面中除去,然后用javascript读取cookie来显示。有其它需求的话,还要用到ajax或json技术。(注:变成了静态页面(可以利用缓冲) + 动态拉取ajax(及时性))
4、同样是因为有缓存,每次更新缓存都要花去一些时间, 为了加快速度,所以会用到异步更新缓存的机制(为啥异步更新会加快速度?貌似解决不了这个问题)。用到异步更新会出一个问题,当用户得到发帖成功的响应的时候,事实上这张贴还没有更新,如果让用户直接访问这张帖子,那他往往看不到自己刚发表的回帖,这会让用户联想到“审核”这个动作,感觉非常不好。所以这个发帖成功这个动作应该让用户看到“5秒后跳到某某页面”这样的提示,让他缓冲一下,这样程序就有足够的时间来执行更新缓存的动作了。另外一个是更新缓存时遇到分页帖子就不好处理,所以应让页面尽可能长,像猫扑天涯的帖子都很长,就是这个原因。( 注:架构优化有时也需要和产品体验一起考虑
5、因为脱离了动态程序,所以之前如果是用动态程序直接统计点击量的话,点击量就会有问题,这时可以通过统计squid的log来统计帖子的点击量,然后再更新到后台的一个接口里。 (注:这里给出了一个新的思路:如果计算统计量?基于流水统计和后台接口merge的方式)


二级缓存的优点是可以进一步减少请求量,这里配置了4台缓存,意味着一个热门帖子每次更新都会更新这4台机器,这4台机器就会发出4个请求,用一台二级缓存就可以化为1个请求,理论上可以将请求优化掉3/4。 另外是squid这个服务器在一些情况下会出现某台机请求全部穿透的现象,这时二级缓存就可以拦截住这些量很大的请求。一般来说,一个系统用到二级缓存就基本足够了,没有必要用到三级。

缓存过期时间在nginx或squid做,比较方便,比如有个没有被缓存的页面,访问量突然很大,这时可以立刻调整它让它暂时被缓存住。

在nginx可以通过log观察,屏蔽掉一些ip和访问,比如一些设计不良的爬虫来爬页面,造成系统负载突增,可以直接将它的ip或user-agent屏蔽掉。 (access log是否一定会打开?)

权重和分流调节是lvs和nginx都有的功能,如果机器性能不均造成负载不均,或者有机器处于调试状态,可以调整他们的访问权重。lvs因为工作在http的第4层,所以分流功能不算太强,除了可以调权重,另外就是可以根据客户端ip分,还有根据后端负载动态分。nginx是7层代理,分配方式就更多,可以实现基于ip/url/header/后端响应速度等等来分。

高可用性就是说系统的稳固状态,最好的就是这个系统永远都能正常访问,无论什么时候访问都绝对能打得开,当然这世界上根本没有永远都能打开的系统了,所以我们也只能让它尽可能访问正常。在计算机系统中某一台单机的可用性都是不可靠的,单机即使软件性能做到很强,但是硬件也会有问题,所以要用到集群架构。

lvs通过双机热备,实时切换,可保证有故障时会自动换到备机。
squid直接利用lvs的故障屏蔽
nginx可利用自己写的程序来实现热备,也可以用lvs分到两台nginx上
应用服务器就是nginx集群
数据库就麻烦一些,现用的方案是通过程序判断来做双机热备

因为用到缓存架构,大量的流量都是通过缓存直接输出的,这样就可以轻松实现流量分配,一般的分流问题有两种,电信网通的分流和双线路分流,都可以做。

电信网通,在电信机房和网通机房各架一组缓存,中层代理和应用服务器都用一套。( set部署?)
多线路分流和电信网通分流差不多,就是比如两条100M的带宽,怎么一起服务。

权限划分,这个是大公司才会有的问题了,大公司分工比较细,比如我就是做运维的,所以我就主要管理前面的squid和nginx这个部分,应用服务器和数据库就让产品维护的兄弟去做,在性能优化有什么问题需要他们帮忙的,我只提供方案,让他们去实施。有部分要合作的,要想办法减少耦合度,像点击量统计这部分,他们设计一个接口,然后我去写统计log的脚本,然后往接口发。反过来也一样,我设计接口,然后他们发来。

你可能感兴趣的:(社区)