Tuning Linode VPS-小规模低性能低流量网站优化实践

| 18 Comments

偶然看到以前写过的这篇帖子 『小规模低性能低流量网站设计原则』,重新发到微博上引起了一点反响,觉得有必要以 Linode VPS 为例再做个简单的优化实践说明,免得总有人问我,也顺便赚点点击量 :)

假定现在你已经有了一个基本的 VPS 可用,基本内存 512MB 。参考官方提供的各种安装指导将 LAMP 这个组合运行了起来,操作系统一般 Ubuntu ,Web 服务器 Apache ,数据库 MySQL ,然后是 PHP ,以及需要安装的应用软件,WordPress 、Drupal 或是 OpenCart 什么的,一步一步配置好,能够正常的浏览页面。按照官方指导文档操作的一个好处是会包括一些基本的优化一点的配置。不至于出现太大的错误。

一旦应用就绪后,登录到操作系统中,通过 top / iostat / free 等基本操作系统命令收集基准数据,做记录。收集信息越全面,对于后面的优化就越便利。优化没有魔法,只有合理的方法。

1.内存相关的调整

内部测试或是较小范围使用,可能这样也不会遇到太大问题。一旦访问人数多了一点,机器响应可能就有点慢了。对于 VPS ,第一步着手调整的就是各个组件对内存的使用。因为内存受限,对内存的使用一定要精打细算一点。记住一旦内存耗尽,一部分内存调用压到磁盘上,系统负载会飙升,一般就会挂掉。

一般来说,对于 LAMP 环境,以下几个地方要注意:

PHP 程序的内存相关的调整

PHP5 配置文件 php.ini 中 memory_limit 定义的值默认情况是16MB,该参数定义单个 PHP 脚本消耗最大的内存大小(大意)。如果程序某个页面需要的内存超过这个限制,访问者最可能遇到一个 HTTP 500 错误,查看 Web 服务器错误日志也可以看到。多数情况下,这个值需要做相应调整。比如设置为32MB,是否合适,需要做观察。有一个经验方法是观察 top 命令的输出,看相应进程的 SHR 字段的值,实际上总是尽量大一点点。但不能过大,一旦有个别程序写的不好调用的时候占用过多资源,会导致 VPS 挂掉。

经常有人问,这个服务器跑某某 Web 应用,能支持多少并发? 一个大致的思路是估算单个进程占用的内存,看系统能分配多少内存给应用程序,并发的量大致可以估算得到。但实际上,这个提问基本没多大价值。

另外,还有一个比较重要的参数需要修改 output_buffering 需要修改为 On 或是具体数值(eg, 4096)。修改配置后,检查是否生效(如何检查?)。另外,记住error_log的位置,随时查看。

MySQL 数据库内存占用

如果不确定 MySQL 内存使用情况,可以利用 MySQLReport 这个工具收集一下 MySQL 实例的信息报告,不同时间段多收集几次作为对比。然后相应的调整 key_buffer/query_cache_size 等参数的大小, 一次调整一个参数,重启动 MySQL ,继续抽取报告,分析数据,然后调整下一个参数。既然需要编辑配置文件 my.cnf , 建议顺手加大一点 max_connections 这个参数(为什么?)。

多数内存问题都是由数据库 I/O 引起,导致 I/O 问题多由不合理数据库调用有关(这么说严谨么?),解决不合理调用要么修改应用,要么通过查询缓存或是 Key-Value Cache 等办法缓解。这地方说来话长,假定 VPS 上基本不会有这么复杂的环境。

2. 影响 CPU 利用率的调整

这个主要针对 PHP 的 Opcode(Accelerator) 而言,解析、编译PHP代码是相当消耗CPU的操作。常见的要么是 APC, 要么是 eAccelerator 或是 XCache,在 Ubuntu 下安装配置都相对简单,参数调整简单搜索一下就知晓了。如果是 PHP 环境,那么一定要用 Opcode 减少 CPU 的负荷(为什么?)。至于用哪一个关系倒是不大,但前提是必须要有一个。

另外,张磊同学这篇 让进程运行在指定的CPU 对于特定需求的应用,很有借鉴意义。

3. 网络参数控制

修改 /etc/sysctl.conf 文件,增加如下几行:

net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

然后 sudo sysctl -p 使修改生效。使用如下一行命令观察半连接数量:

$ netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

其实一般来说,网络连接数不会成为最明显的瓶颈。但顺手调整一下也好,「不费电」。有人问,如果遇到 DDoS 怎么办忍着。

4. 应用程序相关的调整

比较流行的开源程序,不安装第三方插件的情况下,性能多少过得去。建议如果没有必要,不要启用过多的第三方插件,尤其是一些带有统计或是「智能」显示内容之类的插件能不用就不用。

这些开源程序也基本上都有面向前端优化的静态化解决方案,比如 WordPress 的 Cache 相关的插件,强烈推荐启用。有时间看看前端优化的实践建议。

Tuning_LAMP.jpg
(图片来源)

优化最重要的是找到瓶颈,对症下药。前面已经说到了内存、CPU、网络,大致提了一点 I/O 问题,基本也就够了。PHP 的 Log , MySQL 的慢查询 Log ,Apache 的 Error Log ,常过滤看一下有没有新情况。

补充一点,别忘了修改 OS 的 ulimit 限制:

编辑 /etc/security/limits.conf 增加如下两行(具体数值大点小点问题不大):

*  soft  nofile 40960
* hard nofile 40960

编辑 /etc/pam.d/common-session ,增加如下一行:

session required pam_limits.so

编辑 /etc/profile ,增加如下一行:

ulimit -SHn 40960

重新启动 OS 即可生效。

Linode 后台提供了几个基本的统计图,基本够用。可以设置磁盘 I/O 过高的时候报警,系统会发邮件给你。注意看一下网络流量的使用。不要因为个别文件被盗链而将带宽消耗殆尽。

上面提到的不少修改建议不要照葫芦画瓢,知其然,还要知其所以然。每一步的调整多阅读系统手册,尤其是涉及到具体的参数数值,一定要针对实际情况修改。对基本的配置足够掌握之后,可以根据具体情况尝试性能效率的组件,比如用 Nginx/Lighttpd 替换 Apache ,但是要记住,如果 Apache 不是瓶颈的话,用传说中性能更好的 Web 服务器来替换无疑是折腾。

再次提醒不要过度优化,足够满足需求就行了。有更多的精力完全可以放在其他环节上。另外,如果基本的调整做过之后,想用最省事的办法改善性能,那么,直接向服务商购买额外的内存吧。

好吧,最后我想说的是其实这个优化思路并不局限于 VPS ,这个最小实践套路对于复杂的服务器环境也是基本适用的。

--EOF--

Tip:页面不要引用太多的三方脚本。否则也会被拖慢不少。

18 Comments

没被null route的ddos都不叫ddos,被d过2次的人非常郁闷的飘过

想请教一下,如果遇到php进程经常性占到 100% cpu,如何借助一些方法或者工具,判断问题究竟出在哪里呢(用的是官方版的Wordpress,姑且认为程序没问题吧)

嗯,要学习的是其优化思路。简约而不简单!

其中编译 PHP 是很重要的一个部分,禁用所有不需要的扩展。我有个 VPS 的就是把 PHP 的执行程序压缩到了 3M 多一点(记得 strip php)

另外尽量用 nginx 只开2个 worker 进程就绝对够了。

对于 php-fpm 的php重启次数尽量设置低一些,如:100次就重启。否则 php 的持久运行会消耗很多内存(并且很多是没用的)

MySQL 部分则系统优化谈不上了,重点是索引的KEY大小,CHAR 索引比 BYTE 索引大多了(但这得改业务程序)

关于网络参数控制这部分,我在网上看到有人提到修改net.ipv4.tcp_fin_timeout改变系统默认的超时时间,请问这有必要吗?

网络设置部分有问题。
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1
这两个不能同时用。防火墙|nat|load balancer的情况下,可能会导致服务器错误的处理包请求。比如说建立一个tcp连接可能会花10s。
ulimit设置部分不一定适合全部的系统,比如debian默认的ssh pam配置中已经有了pam_limits.so。这样只要重新登录,就可以将/etc/security/limits.conf的改动生效。按照你的改法,没有必要再加ulimit -SHn 40960了。如果你的程序都是脚本启动的,脚本都是root跑的,然后用daemon切换到一般用户的,那么可以在脚本中加入ulimit设置,这样可以避免修改全局的limits.conf。

我们最后发现IO是瓶颈,可能是因为KVM。vmstat和sar一起调试最后发现磁盘IO和网络跟不上,导致一直在等。换用Solaris Zone后解决。所以自己的服务器也有必要研究一下。很多时候是%sys很高……

net.ipv4.tcp_syncookies = 1
值得商榷。在压力不大时,syncookies没有必要吧

我们的app目前遇到了SQL效率的瓶颈,想请教个MySQL高手,预算3k,大概要花一个下午。

请问Fenng兄有没有人推荐呢?

请问怎样的预算比较靠谱呢?我理解问题和问题差异比较大,按小时是OK的,每小时500?1000?

另外这样的人如何才能找到呢?

多谢哈!

好实在的技术,大辉blog上好久没见到这样的文章了,学习了。

经过尝试,ulimit设置这一部分在Ubuntu 10.04.3 LTS下无效(不是VPS,真实服务器上)。以前也碰到过这问题,尝试过各种方法设置全局ulimit,但都没有成功。后来看到国外一篇帖子说是Ubuntu的一个bug,原帖地址忘了。。。

按照这篇文章进行了一些优化,服务器性能好多了,还找到了一个MySQL瓶颈。省了不少钱。

多谢!

vps上能优化的还真不多。更需要限制一下内存使用。比如fpm的进程数,去掉php不需要的模块,调好mysql的缓存。

至于ulimits这些,估计到不了那个并发量就不行了。

你好,经常看贵博客。现在非常流行的linux+apache+nginx+php+mysql搭建web服务器不知道博主是否有接触,网上很多自动安装的脚本,但是我在linode vps上没有一个完美运行的,不是这样就是那样的问题。不知道博主能否写篇相关的文章。s135的文章貌似只针对centos 5,在6下很多问题。。。。