Tech.Memo 类别下的文章

偶然看到以前写过的这篇帖子 『小规模低性能低流量网站设计原则』,重新发到微博上引起了一点反响,觉得有必要以 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:页面不要引用太多的三方脚本。否则也会被拖慢不少。

SSD 趋势小窥

| 3 Comments
Image representing Andy Bechtolsheim as depict...

Image by idg.com.au via CrunchBase

来自 Sun 的大牛 Andy Bechtolsheim (Sun创始人之一)在 HPTS 2009 上做了题为 Memory Technologies for Data Intensive Computing 的演讲。其中对硬件趋势的演绎很有参考价值。

摩尔定律在未来十年内仍然有效。但是对物理磁盘来说某些方面是需要修改的--速度得不到质上的飞跃了 :)

传统 2.5 寸物理磁盘,能够提供 180 个写 IOPS,320 个读 IOPS,平均一个 IOPS 的价格是 $1(这里指价格处以 IOPS 的平均值,不是累积)。而现在主流 SSD 能够提供 8000 个写 IOPS ,3.5万个读 IOPS,每个IOPS 的成本大约是 $0.1。从性价比上看,SSD 的优势逐渐明显。根据来自 NetApp 的信息,SSD 目前一 GB 大约 $3,而磁盘则为 $ 0.10

而实际上,要想达到百万级别的 IOPS 并非易事,I/O 控制器的处理能力毕竟还有限。SSD 写能力仍然是目前的一大问题,随着时间而写能力下降,"均匀磨损算法"(Wear leveling algorithms)目前也不够完美。

密度每年翻倍,内部延时在未来几年将以每年 50% 的速度减小(现在小于100 usec,磁盘则是大于 5000 usec),而传输能力将每年翻倍。成本也将每年减少 50%。这些都是好事情。未来几年,是 SSD 的天下。而传统物理磁盘将成为磁带,SSD 将成为磁盘。(Disk is Tape,Flash is Disk。这话不是我说的,这是 Jim Gray 的名言)

Tape is Dead
Disk is Tape
Flash is Disk
RAM Locality is King
--Jim Gray 2006

--EOF--

延伸观看:MySQLConf 09: Andreas von Bechtolsheim, "The Solid State Storage Revolution"

最近一直在考虑这个关于信息的"五分钟"的问题。搜索了一下,发现还很少有人考虑这个现象,思路还没有完全理顺,先抛几个观点等待大家的补充吧,期待能引发一些对信息处理的思考。

最早注意到这个现象是每次我 BLOG 更新之后,在大约 5 分钟左右,通过 Google 的 BlogSearch 就可以看到内容。这个倒很容易理解,因为我用的 Movable Type 在发布文章的时候会自动通知一下 Google 服务器。接到通知之后,Google 能够较快的把信息合并(Merge)到当前的索引中,但是应该还没加上非常严格的排序(Sort),这是个很经典的处理技巧。

不过,Google 获得信息绝大部分是通过爬虫"抓取",也就是"拉"(Pull)数据,只有少部分是用户"推送"(Push)的。这就导致 Google 在信息处理上节拍总要慢一点。Google 的目标是处理地球上的所有信息,无远弗届,但信息的及时性或许是最难解决的。

Facebook / Twitter / FriendFeed 等具备面向"实时信息流"(Real Time Lifestreaming)功能的网络应用,大部分信息都是用户"推送"上来的,所以也有天然的优势触及这五分钟之内的数据,并经过简单的局部计算之后呈现给用户。得到"即时"信息似乎是人的天性(另一个侧面的印证是人们无法摆脱手机而全部使用 IM 和电子邮件),所以五分钟之内的数据处理能力是对普通用户来说有着难以言明的吸引力。

"五分钟"只是个大致的说法,相信随着技术的发展,会缩短到三分钟,乃至更短。但这部分始终是 Google 无法完全覆盖的地方,技术没办法打败时间,这也是信息暗网的也无法解决的问题。最终我们发现,信息处理的巨人和信息处理的快刀手一起相处的比较融洽。

--EOF--

注:很明显,这个"五分钟"问题和我之前说的关于 I/O 的五分钟问题是不搭界的。

在我看来,如果要评选一个IM 工具的功能"更影响沟通的有效性、更能浪费生产力" 的话,恐怕非"群"莫属。

昨天在 Twitter 上发了一句对"群"这个玩意儿的牢骚,引来了不少朋友的回复,大部分朋友对"群"还是深恶痛绝的,云风随后写了一篇《关于"群"的那些破事》叙述网易泡泡的群功能出炉的来龙去脉。

经常看到有讨论技术的人会开很多 QQ 群,然后一大堆人加入,我最不屑这样的讨论技术的方式,我不相信有谁通过 IM 群学会了很多东西,当然,他们浪费了很多宝贵时间我倒是深信不疑的。所以不乏偏激的说:

"喜欢用群的人都是喜欢用开会来消磨时间的。他们享受群,认为那东西理所当然的是"好"的沟通工具。我也赞同群里面90%都是一些垃圾信息的说法。小笑话、新闻链接、有趣的小图片占据了这 90% 的大部分内容。"

这样的说法如果也在内部会议上提出的话,估计也要像 Tim Yang 那样遭受一片嘘声。(我不排除有人把"群"用的出神入化,比如昨天就有一位互联网大佬给我讲述他当年用群的功能做推广的案例,但这只是个例)。Twitter 上就有不少人不同意我的说法:

"吾之蜜糖彼之砒霜,QQ 群用的人那么多,凭什么说人家烂?不适合罢了"

也有朋友给出了建议:

  • 建议用临时会话,说完正事就退出。(refer)
  • 群的成员不应该是固定的。(refer)
  • 做个Twitter进化的桌面IM...

现在的群,如果非要继续沿用的话,改进的余地还有很大。产品经理请注意,下面是可以给你带来业绩的地方:学习 Twitter 风格的对话模式,针对每一条信息有上下文,便于群内的参与者能够知道信息的指向(这是非常关键的一点,否则就是乱七八糟胡乱抢话筒的会议而已)。第二,设计一个可以将"会议"记录发送到指定电子邮件的功能(这应该并不复杂)。学学 Gtalk 的优点应该不难吧?

欣喜的看到网易已经用不许员工上班时间用群了,这是个伟大的决定。

--EOF--

(注:众多推友对此文亦有贡献)

关于 SSD 的闲言碎语

| 18 Comments

前不久写给《程序员》的一篇文章里,个人预测在 2009 年,SSD (Solid-State Drive,固态盘) 在企业级市场能大展拳脚。上周参加了 EMC 的一个会议,提及了 SSDEMC 存储产品对 SSD 的引入也有一年了,做点 SSD 的科普知识应该是有必要的。

Wear Leveling

很多人对 SSD 的误解是:既然你可擦写次数有限制,比如 200 万次,那么不是没几天不久坏掉了,怎么说使用寿命还比物理硬盘长呢?

Wear Leveling 是有效提升 SSD 的 MTBF (Mean Time Between Failures)的一种技术手段。我们都知道木桶原理,对 SSD 硬盘也是这样,如果不停的对某个 Cell 擦写,那肯定很快就报废。 Wear Leveling 的基本思想就是利用算法保持所有的可擦写单位的次数是近似均匀的,这样就把写次数均匀的分散到各个 Cell 上。

Wear Leveling 翻译似乎还没有统一,有翻做均匀磨损、磨损分级、换位写入等。

对 Wear Leveling 粗略一点的描述大致是:假设更新某个数据块,假定8KB ,而可擦写块(erase block)是 256 KB,那么定位到当前数据位置后,将找个没写过或者写过次数更少的可擦写数据块写入,并不是对原来的位置反复更新。Wear Leveling 算法的效率直接影响 SSD 的寿命。

而 8K 到 256 KB 这个过程实际上是加大了 I/O 操作,称之为 Write Amplification (写放大)。当然 SSD 厂家另有其他技术尽量减少写的频率。

为什么 SSD 写入速度相对较慢?

用一句话解释:擦写块(erase block)比较大。

很明显这样做的目的是减少擦写次数,提升 SSD 寿命。但也影响了数据写入速度。

为什么 SSD 容量是 2 的幂次? 比如 32GB,64GB

这个我也不甚了了,猜测是因为 erase block 多数是 2 的幂次的缘故。物理硬盘的尺寸由来我也不甚清楚。

SSD 的擦写次数是不是致命的瓶颈 ?

这个问题太容易给用户带来疑惑。个人认为要依赖应用的特点和设计。对于合适类型的数据,基本不是问题。但对于某些特定的数据类型,那可能是灾难(比如数据库的 Redo Log)。

SSD 会给数据库应用的银弹么?

是曙光,但不会是银弹。对于密集写入的数据库应用来说,SSD 可能不会带来更多的好处。但是对于密集读的应用,那是有可能带来数量级上的性能提升。在未来若干年内,好的数据库应用仍然严重依赖于设计人员的能力和数据库管理员的优化技巧。

此外,还要期待数据库厂商针对 SSD 进行软件级别的优化。

是否从现在选择 SSD ?

典型的废话答案应该是:这取决于你的具体情况。

要看性价比,EMC 最早引入的 SSD ,性能是普通硬盘的 30 倍,价格大约也是 30 倍。而现在,在企业级市场,SSD 已经降到大约 10 倍普通硬盘的价格。如果再低一些,那绝对是比较有吸引力的。

--EOF--

其中观点仅供参考。SSD 有风险,玩家谨慎操作。而这篇文章中的有些观念有实效性,细节也可能不够准确。

Note: 这里的 SSD ,是说面向企业应用而不是面向个人消费品的。

再增加一个图:

SSD vs. HDD.png

Linux 的一点杂记

| No Comments

Q: 环境变量 LD_ASSUME_KERNE 是干啥的?

A: 动态连接器(dynamic linker)决定使用哪个操作系统 ABI (Application Binary Interface) 库的。LD_ASSUME_KERNE 的值要设定为操作系统版本号。比如 2.4.1 。更多参见 Metalink 文档:433292.1 。

Linux 有些版本的严重 Bug:GLIBC: calloc() Breaks when Application Runs with Locked Process Address Space

补充:在 Glibc-2.5-20 以上版本修复。各发行商有单独的版本。RHEL 4.x 中在 4.7 以上修复。不过 RHEL 4.7 Kernel 也有问题

RHEL 5 特性几个值得关注的点

其中一个是 Root device MPIO support,尽管可能没有人会在根设备用 MPIO. 另外一个是 I/O-AT 的支持,I/O-AT 是 Intel 的网络加速技术. 第三个是 Dynamically switchable per-queue I/O schedulers 。

零星记录的一点东西,以后想到什么再补充。 另外,推荐一下 hutuworm 同学的 BLOG 。很有嚼头。

--EOF--

配置好 Nginx 后,可能有的朋友还想用 Awstats 分析日志。如果另外再起一个 Apache ,觉得费二遍事。如果在 Nginx 上跑 Awstats ,还需要 FASTCGI 支持。配置的方法有些山寨。Nginx 尽管提供 Perl 模块支持,毕竟还是实验性质的。

对比了一些文章,决定还是用 nginx-fcgi 这个脚本。作者是 Daniel Dominik Rudnicki 。这个脚本要比顺子文中提到的要好一点。

该脚本中用到如下的 Perl 模块。所以使用前要确保相关 Perl 模块已经存在。要不,手工下载安装一下。

  • perl-FCGI
  • perl-Getopt
  • perl-IO
  • perl-Socket

使用命令示意:

/usr/local/nginx/nginx-fcgi -S /tmp/fastcgi.sock -l /var/log/nginx/nginx-fcgi.log
-pid /var/run/nginx-fcgi.pid

网上常见的那个脚本必须要显示的指定最为后台进程跑。不是很完善的方法。

注意事项:不能用 root 用户执行(会提示). 要用与 Nginx 相同身份的用户执行。否则可能会在 Nginx Log 中提示 Permision Denied 。

Nginx 中配置好 Log 格式:

log_format  main          '$remote_addr - [$time_local] "$request" ' 
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" $http_x_forwarded_for';

相对应的 Awstats 中 Log 格式为:

LogFormat = "%host - %time1 %methodurl %code %bytesd %refererquot %uaquot" 

其他的配置参考一下Sunnyu 的 "为了Awstats给Nginx添加FastCGI方式的Perl支持" 应该就成了。

BTW: 应该说,Nginx 能够有效抵挡搜索引擎爬虫对网站的影响。对于 Apache 来说,这是个很大的进步。

--EOF--

更新:如果手工写脚本做 Nginx 日志 logrotate 的话,注意不要简单的用 mv 命令, cp 然后 echo ''> 的方式更好。

推荐: Sina 张宴的 Nginx 0.7.x + PHP 5.2.6(FastCGI)搭建胜过Apache十倍的Web服务器(第4版),这是目前关于 Nginx 最详细的实践文章。

日复一日的 Unix/GNU Linux 使用过程中,或许总有一些命令让你感觉肝颤,看看如下几个命令是不是让你很烦?

fsck -- file system consistency check

如果有可能,不要手工运行 fsck 命令。关于人为调用 fsck "修复" 系统而引起更大灾难的实例已经有很多了。

Unix 的 rm 命令问题

rm 命令可能是最容易给 Unix 使用者带来麻烦的一个命令,但我想这个命令带来的问题几率可能并不如 fsck 那么高。所以放到第二位。另请请参考我以前写的 如何避免 Unix 环境中的 'rm -rf' 灾难 这个帖子。

crontab -r -- 不经提示删除了 cron 内容

这条命令我从来没用过,是网友留言提示的,看来他深受其苦,或许还有同病相怜的人。

source ~/.bash_history

The source command sends the contents of a text file to the Unix shell. 我相信如果有人运行了这样的命令,肯定是命令行自动补全惹得错 :)

或许还有很多命令是尽量不要运行的,话说回来,在 Unix 系统里面运行每个命令都需要谨慎。IBM dw 上这篇关于系统管理员的"懒惰"我倒是挺认同的,无为而治。

上面提到的 Unix ,包括 GNU/Linux,具体的 Shell 具体对待。

--EOF--

还有个老生常谈的提醒:不要在 root 用户下做日常操作。

<< 1 2 3 4 5 6

关于归档

本页包含 Tech.Memo 类别下的所有文章.

上一类别为 Startup.

Web 为下一类别.

回到 首页 查看最近发表的文章或者查看所有 归档文章.