新年钟声即将敲响,没什么机会总结这一年的成果,或者说没什么大成果可以总结,依然离自己的目标很远。只希望能从小事做起,一点点改变,一步步去做。
给自己的BLOG做了一个新的主题,希望能通过坚持这一件小事来一点点改变自己。希望大家给我的主题提一下意见和建议。
Nginx不仅是一个小巧且高效的HTTP服务器,也可以做一个高效的负载均衡反向代理,通过它接受用户的请求并分发到多个Mongrel进程可以极大提高Rails应用的并发能力。下面介绍一下如何在一台服务器上配置Nginx + Mongrel cluster。
获得Nginx方法可以参考前一篇配置Nginx+PHP5 FastCGI的文章,这里我们假设大家是通过自己编译,并配置了默认的编译的参数,此处使用的是Nginx 0.5.x版。
配置Mongrel cluster
我们还需要获得Mongrel和其Cluster插件(用来方便得启动多个Mongrel进程),如下通过gem进行安装:
gem i -y mongrel mongrel_cluster
然后建立mongrel_cluster的配置文件。进入Rails应用即你的程序的根部目录(以下假设/usr/rails),运行:
mongrel_rails cluster::configure
然后mongrel_cluster便会在config目录下生成一个mongrel_cluster.yml,内容如下:
—
log_file: log/mongrel.log
port: 3000
pid_file: tmp/pids/mongrel.pid
servers: 2
我们可以通过修改其中的设置来更改mongrel_cluster的运行,这个范例配置省略了一些其他参数,具体的参数的含义如下:
address: 指定绑定的地址
port: 指定mongrel_cluster所运行的mongrel进程从哪个端口开始绑定
servers: 指定同时运行多少个mongrel进程,结合port参数,就是表示port到port+servers-1(含)的端口将被使用
environment: 指定Rails运行的配置环境
user: 指定mongrel进程以什么用户的身份运行
group: 指定mongrel进程以什么组的身份运行
cwd: 指定mongrel运行的根目录
log_file: 各个mongrel进程的输出日志的位置,相对于cwd的目录,会在文件的扩展名之前加上各进程对应的端口号
pid_file: 各个mongrel进程的pid文件的位置,相对于cwd的目录,会在文件的扩展名之前加上各进程对应的端口号
大家可以根据自己的具体情况进行修改。以下是一个完整的mongrel_cluster.yml配置文件:
—
user: apache
cwd: /usr/rails/
log_file: log/mongrel.log
port: 3000
environment: production
group: apache
address: 127.0.0.1
pid_file: tmp/pids/mongrel.pid
servers: 5
接下来便可以启动mongrel_cluster了,以下是控制mongrel_cluster的命令:
mongrel_rails cluster::start #启动
mongrel_rails cluster::restart #重启
mongrel_rails cluster::stop #停止
配置Nginx负载均衡反向代理
利用nginx的upstream指令配置哪些服务器需要进行负载均衡。在这里也可以说直接说告诉nginx mongrel_cluster在哪些地址和端口上,按照上面的mongrel_cluster的配置,在nginx中应该这样写:
…
http{
…
#upstream段要放在http段中
upstream mongrel {
[...]
来自Ruby官方网站的最新消息,Matz已经发布了1.9的开发版本作为献给大家的圣诞礼物。
1.9的性能较1.8有大幅提升(请参考相关测试结果),并且添加了大量新的语言的特性。
这无疑对于Ruby爱好者是一个福音,但前不久刚发布Rails 2.0还不能完全正常运行于Ruby 1.9之上,包括诸如Mongrel之类的其他组件,所以在很长时间内Ruby 1.8将仍然是主流的平台。不过相信Ruby社区和相关社区的朋友们会一起努力,使这个迁移快速而顺利地完成(就像当年Python 2.5发布的时候)
WordPress 2.3加入了标签功能,我们可以在撰写文章的时候,在文章编辑框的下方输入一些以“,”分割的标签。这是一个半角的逗号,对于国内的用户来说,经常需要输入中文的标签,这时候中文输入法打出来的是全角的逗号“,”,就必须切换到半角模式或者关闭输入法,再输入一个半角的逗号,输入完了之后还要把输入法切换回来,十分麻烦。目前没有找到任何一种插件可以解决这个问题。当我研究了WordPress的代码之后,发现光写一个插件是不能达到我要的功能的,必须对现有的代码进行一些修改。这是由于WordPress代码本身有一个小小的不完善的地方。下面我给出我的解决方案,希望对大家有用:
找到WordPress安装目录下wp-includes/post.php,打开编辑,将第432行(WordPress 2.3.1版)由原有的:
$fields = array(‘post_author’, … , ‘post_category’);
改为
$fields = array(‘post_author’,…, ‘post_category’, ‘tags_input’);
大家可以看到在这个数组的最后添加了一个’tags_input’, 这样修改的原因是:包含这一行的函数
sanitize_post 要对输入的帖子的数据数组进行过滤和转义,这个数组就是告诉 sanitize_post ,
帖子数据中有哪些键对应的值需要过滤和转义,正好漏掉了标签对应的键名“tags_input”。另外很有意思的是,我们还能在这一行的上面看到一个 TODO 注释:
// TODO: Use array keys instead of hard coded list
也就是说,WordPress的开发团队注意到了这个问题,将来会直接遍历整个数组(或对象)来进行过滤和转义而非使用这样一个列表。
接下来,将我写的以下代码保存为一个php文件,放到wp-content/plugins目录下:
<?php
/*
Plugin Name: Multiple Tag Separator
Plugin URI: http://shiningray.cn/2007/12/22/multiple_tags_separator/
Description: use other tags separator instead of the default ‘,’.
The plugin requires hacking now,
see http://shiningray.cn/2007/12/22/multiple_tags_separator/.
Version: 0.0.1
Author: ShiningRay
Author URI: http://shiningray.cn/
*/
function multiple_tag_separator($c){
[...]
WordPress是一个非常流行的Blog系统,它可以利用Apache的mod_rewrite来实现URL的静态化。安装好的WordPress在配置了持久链接之后,会在网站的根目录下(如果可写)生成一个.htaccess文件,这个文件可以指示Apache如何进行URL重写(如果服务器配置为允许使用htaccess的指令的话),它的内容如下:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
这个文件的意思就是,如果当请求的文件不存在,那么把请求内部重定向到/index.php。WordPress会自己分析请求的URL,来判断显示哪个页面。
在上次配置了Nginx+PHP之后,由于Nginx不支持Apache的.htaccess文件,要实现持久连接静态化,我们必须手工配置Nginx的文件。首先找到Nginx的配置文件,默认编译后的配置文件在/usr/local/nginx/conf/nginx.conf;Ubuntu通过包安装的配置文件位于/etc/nginx/nginx.conf,也可以编辑vhost的配置文件,放在了/etc/nginx/sites-available下。
以下是基本的配置(Ubuntu下的范例):
location / {
index index.html index.php;
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
[...]
Nginx是俄罗斯人编写的十分轻量级的HTTP服务器,以事件驱动的方式编写,所以有非常好的性能,同时也是一个非常高效的反向代理、负载平衡。其拥有匹配Lighttpd的性能,同时还没有Lighttpd的内存泄漏问题,而且Lighttpd的mod_proxy也有一些问题并且很久没有更新。
因此我打算用其替代Apache应用于Linux服务器上。但是Nginx并不支持cgi方式运行,原因是可以减少因此带来的一些程序上的漏洞。那么我们必须使用FastCGI方式来执行PHP程序。
下面是我成功地配置Nginx + PHP5 FastCGI的过程
从今年7月开始,在被无奈的服务器网络问题郁闷了很久之后,终于让我找到真正的原因,确实在于防火墙的问题。我发现问题原因的过程如下:
公司有2台服务器在万网机房,而且在同一子网中,两台服务器上有同样的两套服务器端程序。我通过ab,对指定的URL发出10个并发总计1000个请求,两台服务器都在200个请求之后,就不能连接了。其中有一台是Windows服务器,我当时还开着远程桌面,ab刚打印出“Completed 200 requests”,远程桌面立刻变灰,随即右上角显示出断开图标,闪烁之后便告诉我链接被终止。另一台是Linux服务器,我开着Putty链接在上面,通过ab测试的时候,到200个请求之后,Putty便报警说链接断开。
至于万网要这样进行限制的原因还不得知,至少即便我打电话,他们不会去改正这个问题更不会承认他们有问题。那么如果我们有放在万网或者类似机房的服务器(比如叫A),又需要在另外的地方放一个反向代理服务器到这个服务器(比如叫B),那么怎么办才能解决这个问题?在这里我找到两种解决方案:
把A的服务器端移动到服务器B,让A做专门的数据库服务器,B通过长连接(或称持久链接,persistant connection)连接到A。当然如果服务器端应用使用了短链接也是没用的。现在的很多框架如Rails能很好地利用长连接。另外,Memcached的客户端链接一般也是长链接,
架设一个VPN,然后A,B都接入这个VPN中,并只使用VPN分配的地址进行交互,这个可以完全解决前面出现的问题。
两个方案都可以尝试,复杂程度相当。
就这个问题上,我得出的结论是,压力测试是必须的,如果以后公司再托管服务器,我会先利用工具从外部测试一下其是否满足要求。
2008-03-04更新:
经过长久的深思熟虑之后,我觉得如果服务器分布在不同机房,有必要使用数据加密来防止数据包被嗅探,VPN方案可以采用加密的方式,长链接的方式也可以配置使用ssl。MySQL的SSL配置请参考:http://dev.mysql.com/doc/refman/5.0/en/secure-connections.html
问题描述:
当使用memcached并将Model对象保存在其中时,若要取出这个缓存对象时,可能会找不到Model的类,并抛出“Undefined Class/Module SomeClass”的错误。
例如:
if not (genres = Cache.get(key))
genres = Genre.find(:all, :condition => “platform_id = 1″)
Cache.put(key, genres, 60*60*24) # cache for 1 day
end
解决方案
要解决这个问题,可以在引用到该对象之间,先引用其类。比如,在前面的代码前面加入要引用的类Genre:
Genre
if not (genres = Cache.get(key))
genres = Genre.find(:all, :condition => “platform_id = 1″)
Cache.put(key, genres, 60*60*24) # cache for 1 day
end
还有更好地方法是在Controller的before_filter中加载所依赖的所有Model:
before_filter :preload_models
def preload_models
Model1
Model2
[...]
原文:http://weblog.rubyonrails.org/2007/12/7/rails-2-0-it-s-done
但是,目前仍应该将所有的必须的gems(除了Mongrel)freeze到正在维护的Rails应用中。请运行:
rake rals:freeze:gems
就在前一个星期,我终于决定要把nirvanastudio.org的域名从原来的域名服务商“中申网”(291CN)迁移出来了——好几年前是iCream推荐让我在这里注册的,当时还是买了个套餐100MB ASP空间+一个域名(后来我问他为什么在这里买,他居然说是随便找的)。为什么要迁移呢,是因为我实在无法继续信任这样一个域名提供商了:
他们网站大概在一两年前做过一次系统升级,替换了原来的系统,因此老用户和新用户使用了不同的登录方式。而他们一直没有通知我这个事情,直到有一次我需要修改DNS设置。我反复在新老登录界面尝试登录,始终没有成功。最后只能联系QQ客服直接帮我修改了DNS。
那么我帐号哪里去了呢?我总不可能每次都让客服给我修改吧?后来经过多次交流沟通,客服给我的答案是,升级过程中可能我的帐户丢失了,于是让我重新建一个,再把我和我的域名关联起来。
他的域名控制面板非常简陋,界面上只有“修改域名信息”、“域名解析MyDNS”、“修改域名管理密码”、“安全退出”几个链接,连一点点和291cn有关的界面都没有。而其中的“修改域名信息”,总是显示“查询密码失败,可能是网络不正常,也可以重试一次!出错代码是:ret=0&err=db-failure&err=nottheowner”。而且还无法自己修改域名服务器。
有一次我想尝试将nirvanastudio.org的邮箱服务绑定到Live Mail。按照domains.live.com的提示,我在DNS中添加了MX记录,结果过了2天都没有生效,也就是Live Mail没法检查到我已经绑定了这个域名。最后我只能放弃。而我用过在Godaddy和Yahoo购买的域名,修改的DNS记录生效非常快,就是那么十几分钟的事情。
像这样一个不专业的域名服务商怎么让我放心?而接下去在迁移过程中发生的事情,则更加让我庆幸,迁移域名是个正确的选择。
我在上周日,也就是11月25日,在Yahoo办理了过户申请,并完成了支付。根据Yahoo网站上的指示,要将被迁移的域名的DNS服务器地址修改为Yahoo的DNS服务器地址。因为291cn无法自己修改DNS服务器地址,于是我在第二天,也就是周一,想联系一下291cn,顺便看看这边还需要什么额外的手续。我首先去看他们的“联系我们”的页面,上面有2个QQ号码,一个在线客服,统统都是离线的,而当时正是工作时间。然后看了右下角的两个电话号码,我再拨打电话,发现右边那个号码是“尚未启用”的。我只好再打另外一个,终于通了。结果话筒里面传来了一个很随便的男人的声音。我首先告之说要将域名迁出,他还反问“迁出?”,解释了一下,还没等我说完Yahoo那边新域名服务商的手续,他就很快地说说随便迁的,他们那里过户自由,只要那边域名提供商办理手续就行了,换句话说也就是这事儿和他们无关,别来烦他们。
然后我又等了一天,发现Yahoo的域名控制面板上还是显示Pending,于是我觉得还是有必要去修改域名的DNS服务器的。于是我在周三再次联系他们的客服。而这回不管我什么时候打开他们的“联系我们”页面,看到的QQ和客服统统都是离线状态,又是上班时间。只好再次拨打电话。多次尝试未通,最后终于在下午一点多的时候让我打通了,我让他修改DNS服务器,他给我的回答是因为他在机房没法记东西,所以让我过2个小时再打。我再等了2个小时,再打电话,再告知其要改域名服务器,并把两个域名服务器报给了他:yns1.yahoo.com和yns2.yahoo.com。这位仁兄没见过yns1和yns2的二级域名做域名服务器的,觉得就只有ns1和ns2,便废话了几句。不管怎样,至少他这次修改了之后,我觉得又离迁移成功近了一步。
因此我又安心地等了2天。按照说明,修改DNS服务器生效+Yahoo将剩下手续办理完成,可能需要最多48小时。可是周五我去看,怎么还是Pending呀?而www.nirvanastudio.org已经无法打开了,心想不好,立即查了一下whois,结果让我喷饭了,他把域名服务器改成了:
Name Server:YNS1.YOHOO.COM
Name Server:YNS2.YOHOO.COM
当时我就立刻拨了电话,耐着性子让他把地址更正了。而接下来手续十分快,忙了一天之后,晚上Yahoo控制面板上便可以对域名进行操作了。
最近每天都看余世维的讲座,现在正好讲的是《如何打造职业化的团队》,就这个事情上,我觉得我们国内确实很多服务商都是非常不专业的,这不仅仅是域名提供商,所以他们的竞争力很差。
如果大家有兴趣了解一下余世维博士讲座的内容,推荐大家看One Leo的笔记。