Web架构
大型网站动态应用系统架构设计思想
大型动态应用系统平台主要是针对于大流量、高并发网站建立的底层系统架构。大型网站的运行需要一个可靠、安全、可扩展、易维护的应用系统平台做为支撑,以保证网站应用的平稳运行。
Mysql应用层面的优化(下)
2 Web服务器的议题
Apache是Web应用中使用最广泛的服务器软件。在各种用途下,它都能运行良好,但如果使用得不恰当,它也会占用大量的资源。最常见的一个情况是让它的进程活动了太长的时间,并把它用在各种不同类型的任务下却没有做相应的优化。
Apache经常在prefork配置项里使用mod_php、mod_perl、mod_python。预分叉(Prefork)是为每个请求分配一个进程。因为PHP、Perl和Python等脚本语言运行起来很费资源,每个进程占用50MB或100MB内存的情形也不罕见。当一个请求处理完后,它会把绝大多数内存归还给操作系统,但不会是全部。Apache会让这个进程保持在运行状态,以处理将要到来的请求。这就意味着如果这个新来的请求只是为了获得一个静态文件,比如一个CSS文件或一张图片,你都需要重新启用那个又”肥”又”大”的进程来处理这个简单请求。这也是为什么把Apache用作多用途Web服务器是件危险的事情。它是多用途的,若你对它进行了有针对性的配置,它才会有更好的性能表现。
另外有个主要的问题是如果你打开了Keep-Alive参数项,进程就会长时间地保持忙碌状态。即使你不这么做, 有些进程也会这样。如果内容是像”填鸭”一样传给客户端的,那这个读取数据的过程也会很漫长。
人们也经常犯这样的错误:按Apache默认开启的模块来运行。你可以按照Apache使用手册里的说明,把你不需要的模块都关闭掉,做法也很简单:查看Apache的配置文件,把不需要的模块都注释掉,然后重启Apache。你可以从php.ini文件中把不需要的PHP模块都移除。
如果你创建了一个多用途Apache才需要的配置当作Web服务器来用,你最后可能会被众多繁重的Apache进程所拖垮,这些进程纯粹浪费你的Web服务器上的资源。而且,它们会占用大量与MySQL的连接,以至于也浪费了MySQL的资源。这里有一些方法能给你的服务器”减负”:
不要把Apache用作静态内容的服务,如果一定要用,那也至少要换个另外的Apache实例来处理这些事情。常见的替代品有lighttpd和nginx。
使用一个缓存代理服务器,比如Squid或Varnish,使用户请求无须抵达Web服务器后才能被响应。即使在这个层面上你无法缓存所有的页面,你也能缓存大部分页面,并通过Edge Side Includes(ESL,http://www.esi.org)技术把页面上的小块动态部分放到缓存的静态部分里。
对动态内容和静态内容都设置过期策略。你可以使用缓存代理软件,像Squid,去验证内容的明确性。Wikipedia就是用这样的技术在缓存里移除内容已发生变化的文档。
有时你可能需要改变一下应用,使它能使用更长的超期时间。举例来说,如果你告诉浏览器要永久缓存CSS和JavaScript文件,然后又对这个网站静态HTML文件做了一些修改,这样这些页面的显示效果可能会变得很糟。对此,你需要使用一个唯一的文件名对每次修订后的页面文件都作一个明确的版本标记。举例来说,你可以自定义你的网站发布脚本,把CSS文件复制到/css/123_frontpage.css目录下,这里的123 就是Subversion里的修订号。你也可以用同样的方法来处理图片文件– 不要重用原来的文件名,否则,即使你更新了文件内容,页面不会再被更新,不管浏览器要将原来的页面缓存多久。
不要让Apache与客户端做”填鸭”式通信。这不仅仅是慢,而且很容易招致拒绝性服务攻击。典型地,硬件化的负载平衡器会处理好缓存,Apache就能很快地结束响应,然后让负载平衡器从缓存里读出数据去”喂”客户端。你也可以使用lighttpd、Squid,或者设为事件驱动模式下的Apache作为应用的前端。
开启gzip压缩。现在的CPU很廉价,它可以用来节省大量的网络流量。如果你想节省CPU周期,那可以使用轻量级的Web服务器,比如lighttpd,来缓存和提供压缩过的页面。
不要将Apache上的长距离连接配置为”保活”(Keep-Alive)模式,因为它会使Apache上臃肿的进程长时间处于运行状态。代替的方案是,用一个服务端的代理来处理”保活”的连接,使服务器免受这类客户端的伤害。如果将Apache与代理之间的连接方式设为”保活”,那是不错的主意,因为代理仅使用几个连接从服务器上读取数据。下图说明了以上两者的差异。
以上这些策略应该可以帮助Apache减少进程的使用数,使你的服务器不会因为太多的进程而崩溃。然而,有些具体的操作仍然会引起Apache的进程长时间地运行,吞掉大量的系统资源。有一个例子就是查询外部资源时具有很高的延迟,比如访问一个远程Web服务器。这样的问题还是无法用上述那些方法来解决。
2.1找出最佳并发数
每个Web服务器都有它的一个最佳并发数–它的含义是服务器能同时处理的并发连接数目,它们既能尽可能快地处理客户端请求,又不会使服务器过载。这个”神奇的数目”需要做多次的尝试-失败的反复才能得到,相比于它能带来的好处,这还是值得一做。
对于大流量的网站而言,Web服务器同时处理几千个连接是件很平常的事情。然而,这些连接中只有很少的一部分需要主动地去处理请求,而其他那些都是读取请求、文件上传、”喂”内容,或者仅仅等待客户端的下一步请求。
并发数增加时,服务器会在某一点上达到它的吞吐量顶峰,在此之后,吞吐量会变得平稳,往往还会开始下降。更重要的是,系统的响应时间(延迟)开始增加。
想要知道究竟,就要设想如果你只有一颗CPU,而服务器同时接收到100个请求,接下来会发生什么?假如一个CPU秒只能处理一个请求,而且你使用了一个完美的操作系统,没有任务调度的开销,也没有上下文切换的开销,那么这些请求总共需要100个CPU秒才能完成。
那么,怎样去做才是处理这些请求的最好办法?你可以把它们一个接一个放进队列里,或者对它们进行并行处理,每个请求在每一个轮回中都获得一样多的处理时间。这两种方式里,吞吐量都是每一秒一个请求。然而,如果使用队列,平均延迟有50秒(并发数=1),如果并行处理,那延迟有100 秒(并发数=100)。在实际环境下,并发处理方法的平均延迟还会更高,因为其中还有个切换开销。
对于高CPU占有率的工作负载而言,其最佳并发数就是CPU(或者是CPU里的核)的数目。然而,进程不总是可以运行的,因为它们会执行阻塞式调用,比如I/O、数据库查询和网络请求等。因此,最佳并发数往往会多于CPU数目。
你可以估计最佳并发数,但是这需要精确的分析模型。通常情况下,还是通过实验的方法比较容易,你尝试着不同的并发数,然后观察系统在降低响应时间前,能达到多大的顶峰吞吐量。
Mysql应用层面的优化(上)
对于更快性能的追求开始时很简单:应用响应请求花费了太长的时间,你总要为此做点什么吧。然而,真正的问题是什么呢?通常的瓶颈是缓慢的查询、锁、CPU饱和、网络延时和文件I/O。如果应用配置错误,或者不恰当地使用资源,以上任何一个因素都会引出一个大问题。
