June 29th, 2010 by 张磊
假如你在Linode入手了一个VPS,迅速地部署了Ubuntu,然后使用一大堆apt-get把LAMP服务都搭好了(这整个过程也就10分钟吧,可以更短)。此时可以算是“It works”,但还颇有一些地方需要调整。本文就在这种场景下,写一下此时可以做的最小优化,作用范围不仅限于Linode、Ubuntu,其他系统也可以参考。希望对一些朋友有帮助。
Linux
日志切分
如果没有日志切分,日志可能很快会把硬盘塞满,最后不得不手动清理。做日志切分推荐用logrotate,易于配置,一旦配置完成就会默默无闻地工作。
调整swapiness
swappiness用来控制使用系统swap的概率,ubuntu内核默认是60。建议修改为0,使系统尽可能使用物理内存而非swap。实际上,在上次Linode升级套餐后,我已经关掉了swap,系统运行得依然稳定。具体修改方法可以百度一下。
UPDATE: 经 @7id 提醒,swappiness参数更多的是降低磁盘io操作,对于内存不是特别小的情况,差别不大。详细请看下方留言。
Apache
启用压缩
启用压缩,可以减少传输的内容。对WebServer来说这几乎是必须的,但默认的Apache安装并未开启压缩。对于比较慢的连接,启用压缩会有更多好处。
调整MaxRequestsPerChild
MaxRequestsPerChild用于设置每个子进程在其生存期内允许伺服的最大请求数量。到达MaxRequestsPerChild的限制后,子进程将会结束。如果这个参数为0,Apache进程占用的内存会只增不减。一些使用Apache的VPS经常遇到iorate很高,可以尝试调整一下这个参数(ref)。
Mysql
关掉InnoDB
如果服务器用来放blog或是论坛,多数时候MyISAM就足够用了。此时可以把InnoDB关掉。my.cnf中的注释说:”You might want to disable InnoDB to shrink the mysqld process by circa 100MB.”。实测在VPS关掉Innodb时虽然没节约了100MB,但50M还是有的,内存珍贵,能省则省吧。
只需在my.cnf加入一行 skip-innodb 就可以把InnoDB的功能关掉。
PHP
开启输出缓冲
在使用mod_php时,如果不开Output Buffering,每一个输出都会使Apache向客户端发送数据,导致效率很低。使用fastcgi时,由于WebServer本身有buffer,影响并不大。但默认的apt-get安装,使用的就是mod _php,因此建议在php.ini里把Output Buffering打开。
–
以上只是一些最初级的调整,叫做“优化”都显得有点夸大。但在初期遇到问题时,调整这些地方往往可以很快见效。
除此之外,强烈建议用nginx换掉Apache。
June 17th, 2010 by 张磊
昨天Linode官方blog发表了一篇文章:Linode Turns 7, BIG RAM Increase 。大意是,为了庆祝Linode 7岁生日,他们将所有Linode服务器的内存都增加了42%。
此番增长以后,原来最低配的Linode 360现在变成 Linode 512,而价格依然保持在$19.9。相比之下,在SliceHost买同样内存的VPS需要$38,选择MediaTemple新推出的ve也需要$30。
我原来用着Linode 720,一直为内存不够而发愁,现在直接升级到了1024M内存,已经根本不用swap了。

当然,内存升级之后,机器是需要重启一下才能看到效果的
。
June 17th, 2010 by 张磊
在Twitter上看到盛大举办的校园牛人大赛,其中有“云计算脚本比赛”。看了下题目,开始悔恨大学里没好好学编译原理。但又手痒,就想用Racc试试。做题过程居然很顺利,从学习Racc到做完前三道题花了两三个小时,于是写一点有关Racc的示例,算是学习笔记。
以“云计算脚本比赛”第一题为例,要求执行如下脚本后,得到“Hello, 老赵”。
SET name = "老赵"
RETURN "Hello, " + name
简单来说,用Racc写成解释器,可以把上面的脚本,转化为Ruby代码并执行。
安装Racc:
gem install racc
创建一个level_1.y文件,定义一个JeffParser类。
class JeffParser
token T_SET T_RETURN T_STRING T_VAR
rule
lines:
| lines T_SET T_VAR '=' T_STRING {@local_vars[val[2]] = val[4] }
| lines T_RETURN exp {result = val[2]}
exp: exp '+' exp {result = val[0] + val[2] }
| T_STRING
| T_VAR {result = @local_vars[val[0]]}
end
先定义几个token。因为语法比较简单,只有 SET/RETURN/变量名/字符串四种。
在rule部分,格式是 token: token token … {action} 。中括号中的action 部分就是Ruby代码了,调试时可以把一些需要的变量打出来。val变量是由左边token的值构成的数组,0表示第一个token的值,依此类推。
之后是词法分析的部分。做的事儿是用正则表达式,把上面定义的4种token识别出来,并放到 @tokens 数组中。
---- header
require 'strscan'
---- inner
def parse(str)
@local_vars = {};
@tokens = []
s = StringScanner.new(str)
until s.eos?
case
when s.scan(/SET/)
@tokens << [:T_SET, s[0]]
when s.scan(/RETURN/)
@tokens << [:T_RETURN, s[0]]
when s.scan(/".+"/)
@tokens << [:T_STRING, eval(s[0])]
when s.scan(/[a-z0-9]+/)
@tokens << [:T_VAR, s[0]]
when s.skip(/[ \t\r\n]/)
else
@tokens << [s.getch, nil]
end
end
do_parse()
end
def next_token
@tokens.shift
end
保存后运行 `racc level_1.y ` 将生成一个名为level_1.tab.rb的文件,这就是我们想要的解释器了。
简单测试(假设脚本存放在level_1.file文件中):
ruby -r level_1.tab.rb -e \
'print JeffParser.new.parse(open("level_1.file").read())'
输出:
Hello, 老赵
当然,题目还只做了一半。题目要求:需要用http访问并得到结果。可以在前面挂一个Webrick来做到,就和Racc没关系了。
后面几道题,也可以如法泡制。
–广告时间–
赵姐夫(@jeffz_cn)说这次的题目是他经手的,后悔没把blog的链接放上去,于是我帮他打个广告,欢迎大家猛点此处。