《构建高性能Web站点》笔记 – 7 集群与负载均衡

集群与负载均衡 负载分配的策略:    1. 按业务需要分配。比如“镜像下载”这种应用可以按用户所在地分配一个就近的实际服务器    2. Round Robin依次分配。实现这个策略需要记录上一次分发的去向。在高并发条件下,记录这个东西需要使用锁,因此对吞吐率有影响    3. 随机分配。做不到精确地平均分配,但一般情况下还是可以比较平均的 分发请求的手段:    1.前端服务器通过 http跳转将请求转发到实际服务器。缺点是用户可能会绕过前端服务器直接访问实际服务器,这样的话负载就不能均衡    2. DNS里一个域名配多个IP        a. DNS服务器一般采取Round Robin策略,但一般也支持其他智能策略;不管怎么样,分配策略的灵活度都比较有限,尤其是当你使用第三方的DNS服务时        b. DNS服务器不会成为性能瓶颈,这是它的最大优点        c. 由于DNS缓存问题,处理故障转移(某IP对应的服务机当机了)不是那么实时        d. 总的来说,DNS负载均衡简单可行,但比较粗放    3. 反向代理(第7层负载均衡)        a. 方便实现自己的调度策略,比如可以让好的机器多分担一些任务. Nginx就允许你设置“权重”        b. 反向代理本身要有比较强的性能,否则就会沦为瓶颈。当反向代理的能力到达极限时,后端再添加多少服务器都无济于事        c. 可以用作负载均衡器的反向代理:Nginx, HAProxy        d. 总的来说,反向代理做负载均衡比较灵活、好用,但额外开销比较大,容易成为瓶颈    4. DNAT: (传输层负载均衡)修改TCP数据包的目标IP和端口        a. …

《构建高性能Web站点》笔记 – 7 集群与负载均衡 Read More »

《构建高性能Web站点》笔记 – 6 写缓存

读缓存都好明白,这里就不说了 写缓存,实际上是写“缓冲”,即 数据进入到后端(如数据库)之前,先累积在一个缓冲区内,等满足了一定阈值再一次性写入。 这样对后端写只需要执行一次写操作,节省不少性能。 可以用缓存框架如memcached实现这个缓冲

apache httpd的优点

  1. 每个连接独占一个进程,进程之间比较独立; 一个进程的崩溃不会影响其他进程。   2. apache提供了大量的模块   3. 如果并发数在150以内,apache够用了 (郭欣)

《构建高性能Web站点》笔记:5 web组件分离

让你的网站的不同组件使用不同的域名 并且/或者 使用不同的服务器,如 www.glasswall.org          #信息、宣传相关的应用, 服务器名home bbs.glasswall.org          #论坛应用, 服务器名bbs image.static-glasswall.org    #图片,服务器名static js.static-glasswall.org       #javascript,服务器名static html.static-glasswall.org     #静态html,服务器名static 假设首页 /index既包含动态内容,又包含图片和js,使用上述方案有什么好处? 1. 不同域名,可以提高浏览器下载的并发数。 一个浏览器,对同一个域名只能同时下载5、6个组件;现在域名分开了,浏览器可以同时下载5、6个图片和5、6个js, 并发能力迅速翻倍 2. 不需要cookie的组件采用独立域名,避免不必要的cookie发送。你可以让动态内容发送的cookie只使用glasswall.org域,浏览器在请求*.static-glasswall.org时就不会发送cookie;这样可以减少http header的大小 3. 使用不同的硬软件服务器,以适应不同应用的特征;经过恰当的组合,可以获得最理想的总体请求时间或总体成本控制。 比如bbs服务器需要比较好的cpu/内存,而static服务器则需要比较好的带宽和磁盘,以及配置了非阻塞I/O的apache httpd和反向代理缓存。一台cpu强的机器 + 一台磁盘好的机器, 总价格小于两台 cpu/磁盘都强的机器 不同类型的内容,使用不同的优化方案 1. 图片   a.一个页面图片多而小,则可以使用长连接,避免频繁打开建立连接   b.图片内容一般不怎么变,所以Expires可以设得很大,以充分利用浏览器缓存 2. css/js: 变化频率比较小,所以Expires可以设得很大; 当真的发生变化时,可以给css的url加上新的版本号或时间戳,使浏览器原来缓存的内容失效 3. 大文件下载   a.服务器要接入高速宽带   b.磁盘有较好的并行能力   c.web服务器可以打开linux sendfile选项

《构建高性能Web站点》笔记:4.3 反向代理的缓存

用反向代理提供缓存:用户执行一次请求后,反向代理将请转发到后端服务器,转发应答时,反向代理将其内容缓存;下次再来同样的请求时,反向代理直接以自己的缓存应答   反向代理中如果不引入缓存,对性能可能会产生伤害;因为它引入了一次请求转发 提供缓存的反向代理:   1. Apache里可以mod_cache + mod_proxy联用实现代理,Nginx也有类似的模块。它们好用,但还不够强大   2. Squid是最著名的反向代理,它很强大,但过于重量级,使用比较复杂   3. Varnish则比较专注于反向代理,而且比较好用 Varnish   1.通过修改http头来决定是否缓存   2.它的配置文件是用一套长得很像c++/java的DSL写的,所以配置非常灵活   3.varnish的8011端口可以接受命令以清除缓存,你可以通过vinishadm工具直接向这个端口发送命令,也可以从它处向这个端口发送一个http请求   4.varnishstat提供了监控界面,给出诸如cache hit/cache miss之类的数据; varnish还有一个web监控界面 有了反向代理缓存,还有必要搞动态内容缓存(后端服务器自己的缓存)吗? 如果你的应用会有下列情形,则搞搞也无妨。   1. 有的请求不会通过反向代理,直接到达后端;这时后端的缓存就能发挥作用   2. 首次访问一个页面是没有缓存的,这时反向代理缓存就会miss。如果后端服务器预先实现了静态化(严格地说,这不算缓存),就可以解决这个问题    3. 如果一个后端服务器前面有N个反向代理,可能会出现缓存不均匀的情况;如果有的请求落在了缓存不丰满的反向代理服务器上,性能表现就会不佳;如果后端服务器有缓存,就可以为不丰满的反向代理服务器“补位”

缓存 V.S. 缓冲

缓存(cache)是指把远端的数据在本地复制一份,下次获取数据时在本地获取就可以了,以节省开销 缓冲(buffer)则是用于解决高速设备与低速设备的桥接问题。 高速设备如果直接把数据丢给低速设备(或从低速设备那里读),则数据的流速就受限于低速设备,高速设备也沦为了低速设备; buffer的作用就是让高速设备先按自己的速度把数据输出到缓冲区中,低速设备再来读取,这时高速设备可以干别的事,最大化地利用自己的吞吐量。 当然, 这里要有个时间差。

《构建高性能Web站点》笔记:4.2 动态内容静态化

把本应被动态的内容在被请求之前就存成静态文件,用户访问时不经web controller判断,而是让服务器直接返回静态文件;比如新闻网站的新闻,就可以直接存成html。 静态化对性能的帮助非常大。 静态化不属于缓存范畴,因为这里并没有缓存命中、过期等问题。    1. 不过, 静态文件仍有过期的问题,如新闻被修改了怎么办? 策略有两种,一是定时刷新,二是新闻在后端被修改时更新前端对应的静态文件    2. 局部化问题。 一个页面有一部分经常修改,有一部分基本不变,只有后一部分可以静态化。这种情况下应该把后一部分做成SSI文件,再包含到整体页面中; 不过,扫描SSI的include标签是比较耗CPU的;使用SSI机制时,应该告诉web服务器不要去不含SSI的文件中扫描include    3. 这样做可以大幅提升qps, 不过,你的服务器带宽要足够大才能最大地发挥它的优势

《构建高性能Web站点》笔记:4.1 动态内容缓存

动态html缓存是指 将动态的内容如 detial?id=xxx 缓存起来,存成文件; 当收到同样的请求时,直接返回缓存的文件,而不必再去执行一次完整的请求处理过程,比如查数据库什么的。 缓存除了放文件里,还可以放内存里,或者一台独立的缓存服务器中。 具体实现的方案包括:   1. web/mvc框架:如php的smarty,它提供了缓存操作的API   2. web服务器:如apache的mod_cache,它根据http头里的一些字段来决定缓存的刷新策略 (在这里,缓存的key是url)   #2比#1的代码侵入性要低的多、甚至可以说没有侵入; 但反过来说,这也意味着缓存的设计依赖了web server,并且应用程序对缓存失去了直接控制 前端 另一个重要的缓存点是动态脚本编译后的opcode,如jsp编译后的字节码。 将opcode缓存起来,可以避免每次请求时都编译一次   1.php/jsp都可以玩这一套,其中jsp还可以pre-compile   2.这种缓存只能节省CPU/内存的开销,跟I/O没什么关系; 如果你的应用的瓶颈是在I/O,那这种做法就没什么效果