DISCUZX/DISCUZ 模组挂载系统

三月 22nd, 2012 7 comments

发布一个DISCUZX模组挂载系统…
通过这个挂载系统 可以让我们在外部”手术刀”得方式 以最小改动源程序进行修改功能得目的
Read more…

PHP 脸部识别扩展 / PHP Facedetect Extension

三月 22nd, 2012 No comments

蛮好玩得扩展… 大家可以试试

With OpenCV it is possible to find structures on images. The library is shipped with training files to detect faces from different perspectives on images. To access the library and detect faces via PHP I wrote a wrapper.

Overview
This extension provides a PHP implementation of the OpenCV library. The extension offers two new functions. In princible, they differ only by their return value. The first returns only the number of faces found on the given image and the other an associative array of their coordinates.

var_dump(face_count('party.jpeg', 'cascade.xml'));
var_dump(face_detect('party.jpeg', 'cascade.xml'));

?>
Installation
Installing with `pecl` command-line utility

Install OpenCV (OpenCV 2.3.1)
Execute command “pecl install facedetect”
Make sure you have extension=facedetect.so in your php.ini
Installing from sources

Install OpenCV (OpenCV 2.3.1)
Download facedetect source package
Unpack facedetect source package
Go to facedetect folder and type “phpize && ./configure && make && make install”
Make sure you have extension=facedetect.so in your php.ini
Compiling Facedtect into PHP

Install OpenCV (OpenCV 2.3.1)
Download facedetect source package
Unpack facedetect source package to $PHP_SOURCE_DIR/ext/facedetect
In php source root directory run commands: “rm configure && ./buildconf –force”
Configure PHP with command “./configure –with-facedetect”
Run make && make install
Installation note
You should know, that OpenCV needs the following libraries and programs:

pkgconfig
libpng
zlib
libjpeg
libtiff
python
If you use Debian you can install the needed packages by run the following command:

# apt-get install pkg-config python libjpeg62-dev libpng12-dev libtiff4-dev
For details on how install OpenCV on Linux go to the OpenCV InstallGuide

Links
Intel OpenCV
OpenCV
Download PHP Facedetect
Facedetect Examples

WordPress完美更换域名/更换网址

三月 22nd, 2012 No comments

将一下SQL 按照自己得博客得域名进行修改 然后执行

比如下面 得是将wordpress 原http://blog.bigqi.com/wp 迁移到 http://blog.bigqi.com

Read more…

wordprss升级导致得 编辑器 不能可视化 或者空白得解决方案

三月 22nd, 2012 1 comment

 

今天 把博客重新开张了..

于是升级了一下博客到最新得3.3

但是发现编辑器得 可视化工具不能使用.. 而且不能相互切换 即使通过技术手段切换过来

编辑器内部显示空白.. 不显示文章编辑得内容

经过一番研究.. 得出解决办法..

SQL:

UPDATE `wp_options` SET `option_value`=’0′ WHERE (`option_name`=’can_compress_scripts’)

 

执行以上SQL语句 便可以修复编辑器问题..

如何重设WordPress密码

三月 19th, 2012 No comments

在WordPress 2.7或更高版本中更改用户密码,步骤如下:

1. 进入管理界面的用户选项

2. 点击用户列表中自己的用户名进行编辑

3. 在“配置”界面的最下方“新密码”区域,在两个输入框中输入新密码。输入框下方深色背景的方框显示了新密码的强度。

4. 点击“更新配置”按钮

之后新密码会立即生效。

通过邮件自动发送新密码

如果记得自己的用户名与用户资料中的电子邮件账号,可以使用WordPress的“忘记密码”功能:

访问自己网站的登录界面(类似于http://yoursite.com/wordpress/wp-login.php)
点击“忘记密码”
被带往一个界面,输入用户资料中自己的用户名、邮箱地址
稍等片刻,新密码就会被发送到所填的邮箱了
获得新密码后,再次登录,在“配置”页面将密码改为自己能够记住的密码
通过MySQL命令行更改密码

1. 获取密码的MD5散列表

访问md5 散列表生成器,或者….
用Python生成一个密码
在Unix上:echo -n | md5sum
2. 使用”mysql -u root -p”命令——登录MySQL

3. 输入mysql密码

4. 使用”use (数据库名)”命令——选择WordPress数据库

5. 使用”show tables;”命令——查找一个名称中含有”users”的表名

6. 使用”SELECT ID, user_login, user_pass FROM (查找到的表名)”命令——帮助给出内部运行状态

7. 使用”UPDATE (查找到的表名) SET user_pass=”(MD5 字符串)”命令,其中ID = (id#-需要重设密码的用户)——实际更改密码

8. 使用”SELECT ID, user_login, user_pass FROM (查找到的表名)” 命令——确定已经更改密码

9. (输入Control-D,退出mysql客户端)

如果MySQL版本较新(5.x),可以直接用MySQL计算MD5散列表:

1. 跳过上文介绍的第一步

2. 将第七步的命令改为:

使用”UPDATE (查找到的表名) SET user_pass=”(新密码)”命令,其中 ID = (id#-需要重设密码的用户)——实际更改密码
通过phpMyAdmin更改密码

适用于用phpMyAdmin访问数据库的用户。注意:使用phpMyAdmin时,风险自担。如果对自己的能力有怀疑,请向他人寻求帮助。WordPress对数据丢失概不负责。

登录phpMyAdmin,点击数据库:

之后会出现一个数据库列表,点击WordPress数据库

中国微博集体月经~

七月 14th, 2010 No comments

过去几天,一系列莫名其妙的小故障导致中国的微博服务中断,引起了用户的不安,人们担心政府将整顿这种广受欢迎的、类似于Twitter的社交网络工具。

首先,门户网站搜狐网的微博服务周末一度无法接入。之后, 新浪微博的标志旁边周一打上了“beta”符号(意为测试版),网易和腾讯的微博服务上也出现了这个符号。然后用户于周二晚报告说网易的微博服务突然“处于维护中”,账号也无法接入了。


同时,继网易微博停运、搜狐微博曾短暂中断之后,新浪微博也开始进行内部整顿,总编辑陈彤发出内部通知,“肯定要被删除的微博,通知监控部门,需要封杀的用户,拿不准的再请示我”。
新浪微博方面表示没有接到类似的指令。

分析人士表示,新浪此举或预示着微博正遭遇到一些监管压力。从本周开始,新浪微博页面增添的“测试版”字样正体现出对压力的某种妥协姿态。

新加坡中文报纸《联合早报》在其网站上报道称搜狐微博暂停服务是由于审查合规问题。这一报道致使用户推测微博这一愈发受到欢迎的互联网应用程序或许有受到限制或停用的危险。

搜狐网的客服代表证实于周五晚至周一期间关闭了搜狐微博,但说是为了维护而不是由于政府的命令。

新浪网营销中心副总经理刘奇否认网站打出“测试版”符号与政府命令或其它竞争者有关,并说用户不必担心微博服务会被关闭。他说自去年8月启用以来,微博网站严格来说一直处于试用阶段,目前正在为其一周年纪念日策划再次启用仪式。

尽管如此,几家网站的微博服务同时出现“beta”版本符号仍让许多用户焦虑,特别是由于过去中国的网站与政府进行不公开谈判造成网站停用时,曾以“网站维护”充当借口。

随着越来越多的知名网站受到屏蔽,加上谷歌决定停止审查其中文搜索引擎等受到广泛宣传的事件让公众意识到审查的存在,中国的互联网用户对政府的互联网控制措施越来越心存警惕。

去年,Twitter被中国屏蔽,与之类似的中文服务“饭否”也被关闭。尽管这两个网站在主流网民中并不普及,但由新浪网、搜狐网和网易网

启动的微博网站却开始蓬勃发展。作为最受欢迎的微博网站,新浪微博目前的用户超过500万人。这些网站均依据自我审查制度受到网站的监管。

在此之前,政府支持的中国社科院发表报告指出了社交网站的危险性。这份于7月7日发表的报告以Facebook(也被中国屏蔽)为例指出社交网站可被用作颠覆和侵犯用户隐私的工具,并称这些网站被西方国家情报机构所利用.

最后等待中国微薄集体水产的一天…那天所有人回归Facebook

关于Discuz!X1 嵌入点 及其插件的编写 注意说明

七月 8th, 2010 No comments
首先插件的路径改变了
插件放置于 source/plugin/目录下
数据库读取的写法也发生了改变:
使用了类的静态方法好处显而易见不需要原来 $GLOBALS[‘db’] 直接在任何地点拿出来就能用
DB::table(‘forum_attachment’);   //这里会返回 pre_ forum_attachment
DB::fetch_first($query)              //这里对应原来DZ7的 $db->
fetch_first($query)
DB::query($query)                    //对应原来DZ7的 $db-> query ($query)
DB::fetch($query)                     //对应原来DZ7的 $db-> fetch ($query)
关于嵌入点:
Discuz!X1  由于有众多模块 .. 所以插件平台在原来DZ7.2 的基础上进行了升级
具体的写法:
class plugin_bigqi_com {
function plugin_bigqi_com(){
//这个写法会被插件执行函数runhooks() 运行时调用执行…
return ‘this is globals plugin_bigqi_com’;
}
function global_footer(){
// 这个是全局嵌入点的…所有的页面包括首页论坛群组空间等等
return ‘this is globals global_footer’;
}}
//下面这里就重要了..
// DISCUZ! X 的插件运行机制有些改动… 由于Dx 使用了模块化包含方式..
//所以就有必要强调嵌入点是哪个模块下的
//模块的定义在每个最外层文件的最上部如:forum.php
// define(‘CURSCRIPT’, ‘forum’); 定义了模块名称 forum
//另外原来DISCUZ 7.2 使用的执行脚本常量由原来的 CURSCRIPT 改为 CURMODULE
//所以大家在写 forum 嵌入点的时候判断模块下执行的脚本就要用 CURMODULE 来判断
//另外嵌入点的具体写法如下:
//只有用插件名+下横线+模块的名称对原来的类进行继承扩展才能让模块内的嵌入点显示
class plugin_bigqi_com_forum extends plugin_bigqi_com {
function index_top(){
return ‘this is forum index_top’;
}
}
// 另外 原来的 DZ7.2 使用的引用模板的写法不变只是插件的模板目录的名称改变了
由templates 改成了 template
例如:
source/plugin/bigqi_com_picrollshow/template/
插件模板引擎的写法 保持不变 我这里写个示例
// include template(‘bigqi_com:picrollshow’);
// return $return;

首先插件的路径改变了
插件放置于 source/plugin/目录下
数据库读取的写法也发生了改变:
使用了类的静态方法好处显而易见不需要原来 $GLOBALS[‘db’] 直接在任何地点拿出来就能用
DB::table(‘forum_attachment’);   //这里会返回 pre_ forum_attachmentDB::fetch_first($query)              //这里对应原来DZ7的 $db->fetch_first($query)DB::query($query)                    //对应原来DZ7的 $db-> query ($query)DB::fetch($query)                     //对应原来DZ7的 $db-> fetch ($query)
关于嵌入点:
Discuz!X1  由于有众多模块 .. 所以插件平台在原来DZ7.2 的基础上进行了升级
具体的写法:
class plugin_bigqi_com {         function plugin_bigqi_com(){                   //这个写法会被插件执行函数runhooks() 运行时调用执行…                   return ‘this is globals plugin_bigqi_com’;         }         function global_footer(){                   // 这个是全局嵌入点的…所有的页面包括首页论坛群组空间等等                   return ‘this is globals global_footer’;         }}
//下面这里就重要了..// DISCUZ! X 的插件运行机制有些改动… 由于Dx 使用了模块化包含方式..//所以就有必要强调嵌入点是哪个模块下的//模块的定义在每个最外层文件的最上部如:forum.php// define(‘CURSCRIPT’, ‘forum’); 定义了模块名称 forum//另外原来DISCUZ 7.2 使用的执行脚本常量由原来的 CURSCRIPT 改为 CURMODULE//所以大家在写 forum 嵌入点的时候判断模块下执行的脚本就要用 CURMODULE 来判断//另外嵌入点的具体写法如下://只有用插件名+下横线+模块的名称对原来的类进行继承扩展才能让模块内的嵌入点显示class plugin_bigqi_com_forum extends plugin_bigqi_com {         function index_top(){                   return ‘this is forum index_top’;         }
}
// 另外 原来的 DZ7.2 使用的引用模板的写法不变只是插件的模板目录的名称改变了由templates 改成了 template例如:source/plugin/bigqi_com_picrollshow/template/插件模板引擎的写法 保持不变 我这里写个示例// include template(‘bigqi_com:picrollshow’);// return $return;

Discuz! X 所有嵌入点的方法

七月 8th, 2010 No comments

打开:sourceclassclass_template.php
找到
$dev = ”;
改成
$dev = “echo ‘[$hookid]‘;”;

哈哈 更新缓存后所有的嵌入点就都看到啦!!

Apache Nginx lighttpd HAProx Litespeed 高速的WEB解决方案

七月 7th, 2010 No comments

RoR的部署方案可谓五花八门,有Apache/Fastcgi方式的,有Nginx/Mongrel方式的,还有lighttpd/Fastcgi方 式,也有人使用HAProxy/Mongrel,各种部署方式都是众说纷纭,让人搞不清楚哪种方式更好一些。我的这篇文章就是希望结合我们运营 JavaEye网站一年多以来的经验(通过统计Rails的production.log,JavaEye网站目前每天处理超过70万200 OK状态的Ruby动态请求,应该是国内目前负载量最大的RoR应用了),为大家剖析RoR部署方案的优劣,帮助大家选择适合自己生产环境的RoR部署方 式。

在讨论部署方案之前,先让我们看一下RoR网站部署的简单架构:

浏览器的HTTP访问请求首先达到Web服务器,充当Web服务器的一般是Lighttpd/Apache/Nginx,如果访问请求包含静态资 源,那么Web服务器就会直接从本地硬盘读取静态资源文件,例如图片,JavaScript,CSS等等,返回给客户端浏览器;如果访问请求是动态请求, 那么Web服务器把URL请求转发到后端的FastCGI/Mongrel来处理,等到FastCGI/Mongrel处理完请求,将生成的页面数据返回 给Web服务器,最后Web服务器把页面数据发送到客户端的浏览器。

从RoR的部署方式来看,主要由前端的Web服务器和后端的应用服务器构成:前端的Web服务器可以使用Apache,Lighttpd,Nginx和Litespeed,后端的应用服务器可以使用FastCGI和Mongrel,下面我们分门别类的介绍和剖析:

一、介绍Web服务器

Web服务器的主要作用有两点:一是处理静态资源,二是将动态请求分发到后端应用服务器,然后接收后端应用服务器生成的页面数据,将其返回浏览器,充当了一个信息沟通的桥梁作用,在本文当中我们重点分析后者的作用。

1、Apache 2.2

Apache是全球互联网使用最广泛的Web服务器,但在处理静态资源文件上却不是性能最优秀的Web服务器,不过一般情况下,静态资源的访问并不是RoR网站的瓶颈,因此也不必过于在意这一点。

Apache 2.2既支持HTTP Proxy方式连接后端的Mongrel应用服务器,也可以通过mod_fastcgi/mod_fcgid来连接FastCGI应用服务器:当以 HTTP Proxy方式连接Mongrel的时候,Apache接收Mongrel返回的页面数据的buffer size最大只能开到8KB(默认是4KB或者8KB),因此当页面数据超过8KB的时候,可能需要Apache和Mongrel之间发生多次交互;当以 mod_fastcgi方式连接FastCGI应用服务器的时候,接收返回数据的Buffer size仍然只有8KB而已,如果使用mod_fcgid,那么buffer size为64KB,有了很大的改善。

2、Nginx

Nginx是俄国人出品的轻量级Web服务器,在处理静态资源方面,据说性能还略微超过Lighttpd,但是Nginx在性能消耗方面略微比Lighttpd要高一些。

Nginx内置了良好的HTTP Proxy和FastCGI支持,因此即可以连接Mongrel,也可以连接FastCGI服务器,在这两种情况下,Nginx默认的接收应用服务器返回 数据的Buffer Size也只有区区的8KB,但是你可以自行设置更大Buffer Size。

3、Lighttpd

Lighttpd是全球互联网排名第五的Web服务器,也是近两年来上升最快的Web服务器,特别是很受一些著名Web 2.0大网站的欢迎,例如wikipedia的某些服务器,youtube的视频服务器,在国内,豆瓣网站和JavaEye网站都是Lighttpd的绝 对拥护者。在处理静态资源方面,Lighttpd性能远远超过Apache。

Lighttpd既支持HTTP Proxy连接Mongrel,也支持FastCGI方式,但是Lighttpd的FastCGI支持在所有流行的Web服务器当中可能是最优秀的,所以 用FastCGI的网站都很喜欢Lighttpd。Lighttpd在接收后端应用服务器返回数据的方式上和Apache/Nginx有非常大的区别:

Apache/Nginx是针对每个应用服务器连接分配固定Size的Buffer,而且默认只开8KB,这个Size对于现在网页动辄 50-100KB的情况来说,显得过于保守,如果应用服务器的返回数据无法一次填满Web服务器的Buffer,那么就会导致应用服务器和Web服务器之 间多次数据传输,这对于RoR网站的性能会造成一些相关的影响,我们在后面会详细的分析。

Lighttpd并不针对应用服务器的每个连接分配固定的Buffer,而是尽可能的把应用服务器返回的数据一次性接收下来,因此无论应用服务器返回多大的数据量,Lighttpd都是照单全收,胃口非常惊人。

4、Litespeed

Litespeed是一个商业收费的Web服务器,静态资源处理能力据它自己的评测数据比Lighttpd略高。Litespeed也同时支持 HTTP Proxy连接Mongrel和FastCGI连接应用服务器。此外Litespeed专门为单机运行的RoR开发了一个lsapi协议,号称性能最好的 RoR通讯协议,比HTTP Proxy和FastCGI都要好。但是lsapi的运行方式有很大缺陷:因为lsapi不是web server启动的时候启动固定数目的ruby进程,而是根据请求繁忙程度,动态创建和销毁ruby进程,貌似节省资源,实则留下很大的黑客攻击漏洞。只 要黑客瞬时发起大量动态请求,就会让服务器忙于创建ruby进程而导致CPU资源耗尽,失去响应。

由于Litespeed在运行RoR方面并没有表现出比Lighttpd优越之处,而且还是收费软件,企业版本售价在双核CPU上面每年收费 499美元,并且也不开源,因此我们就不再把关注点放在Litespeed上面。当然Litespeed收费也不是白收的,它提供了非常好用的基于Web 的服务器管理界面,以及非常多的安全性方面的设置参数。

5、HAProxy

HAProxy并不是一个Web服务器,他既不能处理静态资源,也不能充当浏览器和应用服务器之间的缓冲桥梁,他只是充当了一个请求分发的软件网 关作用。ThoughtWorks公司的RubyWorks选择使用HAProxy + Mongrel Cluster的方式来部署RoR应用,不能不说是一个愚蠢的方案。这种方案其实相当于把n个Mongrel应用服务器捆绑起来,直接充当Web服务器, 而Mongrel毕竟是一个Ruby写的服务器,无论是网络IO能力,还是静态资源的处理速度,无法和真正的Web服务器相提并论,让Mongrel直接 处理静态资源和调度网络IO,会造成服务器资源毫无必要的极大开销,因此HAProxy也不在我们的考虑之列。

二、分析应用服务器的处理方式

无论是Mongrel还是FastCGI,都能够良好的运行Rails服务器,但是他们在和Web服务器之间的数据传输方式上存在一些差别,而正是这些差别,对部署方式有重大的影响:

1、Mongrel

Mongrel本身可以直接充当Web服务器,但在这种情况下性能并不会好。因为Mongrel只有HTTP协议的解析部分是用C语言编写的,其 余所有代码都是纯Ruby的。在处理静态资源下载上面,Mongrel的实现方式非常低效率,他只是简单的以16KB为单位,依次读入文件内容,再写出到 网络Socket端口,其性能远远比不上传统的Web服务器调用操作系统的read()和write()库实现的静态文件下载速度,如果和现代Web服务器实现的sendfile方式的“零拷贝”下载相比,简直就是望尘莫及。

Mongrel使用了Ruby的用户线程机制来实现多线程并发,并且使用了一个fastthread补丁,改善了Ruby用户线程的同步互斥锁问 题。但是Ruby并不是本地线程,我们也不要对Mongrel的网络IO负载能力抱有什么不切实际的幻想。同时Rails本身也不是线程安全的,因此 Mongrel在执行Rails代码的过程中,完全是加锁的状态,那和单进程其实也没有太大差别。

因此,当我们使用Mongrel的时候,一般会在前端放置Web服务器,通过HTTP Proxy方式把请求转发给后端的Mongrel应用服务器。在这种情况下,Mongrel只处理动态请求,在运行Rails框架生成页面数据之后,把数 据返回给Web服务器就可以了。但是在这种部署方案下,有一个很重要的细节被我们忽视了,Mongrel运行Rails生成的页面数据是怎么返回给Web 服务器的呢?通过仔细钻研源代码我们可以搞清楚Mongrel处理Rails请求的细节:

1) Mongrel接收到请求以后,启动一个ruby线程解析请求信息

2) 加锁,调用Rails Dispatcher启动Rails框架

3) Rails处理完毕,创建一个StringIO对象,把Rails生成的页面数据写入到StringIO中

4) 解锁,把StringIO的数据flush到Web服务器

这个StringIO对象其实很重要!它充当了一个输出缓冲区的作用,我们设想一下,当Mongrel作为独立的Web服务器的时候,如果 Rails生成的页面比较大,而客户端浏览器下载页面的速度又比较慢,假设没有这个StringIO对象,会发生什么问题? Rails线程在执行render方法的时候就会被挂住!同步互斥锁没有解锁,Mongrel再也无法处理下一个动态请求了。

当Mongrel仅仅作为应用服务器的时候,这个StringIO仍然很重要,为什么?我们前面提到过了,Apache/Nginx的接收缓冲区 都只开了8KB,如果页面比较大,Mongrel就没有办法一次性把数据全部推给Web服务器,必须等到Web服务器把接收缓冲区的8K数据推到客户浏览 器端以后,清空缓冲区,才能接收下一个8KB的数据。这种情况下,Mongrel必须和Web服务器之间进行多次数据传输,才能完成整个Web响应的过 程,显然没有一次性把页面数据全部推给Web服务器快。如果Web服务器使用Lighttpd的话,情况会不一样。当Mongrel把StringIO的 数据flush出去的时候,Lighttpd是一次性全部接收下来了,不需要多次交互,因此Lighttpd+Mongrel的RoR网站的实际速度要快 于Apache/Nginx+Mongel。

Mongrel使用StringIO对象缓存输出结果,在某些特殊的情况下会带来很大的安全隐忧。我们假设使用服务器端程序控制带权限的文件下 载,某用户下载的是一个100MB的文件,该用户使用了多线程下载工具,他开了10个线程并发下载,那么每个线程Mongrel在响应之后,都会把整个文 件读入到内存的StringIO对象当中,所以总共会创建出来10个StringIO对象保存10份文件内容,所以Mongrel的内存会一下暴涨到 1GB以上。而且最可怕的是,即使当用户下载结束以后,Mongrel的内存都不会迅速回落,而是一直保持如此高的内存占用,这是因为Ruby的GC机制 不好,不能够及时进行垃圾回收。

也许你会觉得不太可能下载100MB那么大的附件,但是以JavaEye网站为例,圈子的共享文件最大允许10MB,只要用户在多台机器上面,每 台机器开100个线程下载圈子共享文件,每个Mongrel的内存占用都会立刻超过1GB,用不了几分钟,服务器的物理内存就会被耗尽,网站失去响应。这 个缺陷非常容易被别有用心的黑客利用,攻击网站。这也是JavaEye网站为什么始终不用mongrel的原因之一。

通过上面的剖析,我们知道Mongrel在使用Lighttpd的时候,可以达到最快的RoR执行速度,但是Lighttpd当前的1.4.18 版本的HTTP Proxy的负载均衡和故障切换功能有一些bug,因此一般很少有人会使用这种方式。大多数人都会采用Mongrel搭配Apache2.2或者 Nginx,但是正如我们上面做分析的那样,Apache/Nginx的Buffer Size实在是一个很讨厌的限制,特别是Apache只能最大开8KB的Buffer,因此我建议使用Nginx搭配Mongrel,并且把Nginx的 Proxy Buffer Size设置的大一些,比如说设置为64KB,以保证大多数页面输出结果可以一次性flush到Web服务器去。

2、FastCGI

很多人对FastCGI谈虎色变,仿佛FastCGI就是内存泄漏,性能故障的罪魁祸首,又或者嫌弃FastCGI太古老了,已经被淘汰掉的技术 了,其实这是一个很大的误解。FastCGI本质上只是一种进程间通讯的协议,虽然是一个比较古老的协议,但是还是比HTTP协议年轻多了,HTTP协议 不是照样现在很流行吗?

在PHP/ASP/JSP流行之前,FastCGI曾经非常普及,只不过那个时代的FastCGI程序是用C语言编写的,写起来太费劲,而PHP /ASP/JSP相比之下,写起来就太简单了,所以FastCGI就渐渐被丢到了历史的故纸堆里面。但是最近两年来,由于Ruby和Python的快速 Web开发框架的强势崛起,FastCGI仿佛又咸鱼翻身了。

当我们以FastCGI方式运行Rails应用服务器的时候,每个FastCGI进程都是单线程运行的,考虑到Rails本身不是线程安全的,所 以和Mongrel运行Rails的实际效果是一样的,都是每个进程只能跑一个Rails实例。但是FastCGI在Rails生成页面数据返回给Web 服务器的方式和Mongrel截然不同:

前面我们说到Mongrel自己开了输出缓冲区,而FastCGI则完全不开任何缓冲区,当Rails执行render方法的时 候,FastCGI实际执行的是FCGI::Stream.write方法调用,直接把数据写给Web服务器了。此时如果Web服务器是 Apache/Nginx,会发生什么?

如果我们使用mod_fastcgi模块,那么Apache的接收缓冲区就是8KB;

如果我们使用mod_fcgid模块,那么Apache的接收缓冲区就是64KB;(mod_fcgid是中国人开发的取代mod_fastcgi的开源项目,在Apache社区很受欢迎,谁敢说中国人只是开源“消费”国?)

如果我们使用Nginx服务器,那么默认的接收缓冲区就是8KB,但是可以改得更大;

如果页面数据比较大,超过8KB,会怎么样? FastCGI进程被挂在render方法上!必须等到Web服务器的缓冲区清空,把页面数据全部接收下来以后,FastCGI进程才能结束本次 Rails调用,处理下一个请求!所以千万别用Apache/Nginx搭配FastCGI应用服务器,否则你的RoR应用会死的很难看。根据我个人的测 试数据表明,同样的测试负载,Apache搭配70个FastCGI进程挂掉,但是Lighttpd搭配30个FastCGI进程轻松跑完!

当FastCGI搭配Lighttpd的时候,我们知道Lighttpd会一次性照单全收FastCGI送过来的页面数据,所以FastCGI进 程并不会被挂住。如果我们对比一下Lighttpd搭配Mongrel和FastCGI会发现,Lighttpd搭配FastCGI性能最好,为什么呢?

Mongrel首先自己会用StringIO缓冲页面数据,然后推送给Lighttpd以后,Lighttpd也在内存当中缓冲了一份页面数据, 造成了毫无必要的double buffer的开销。这自然不如FastCGI不做任何缓冲,直接推给Lighttpd性能来得高,内存消耗少了。

我们的方案分析到这里,大家应该自己心里有结论了,Lighttpd+FastCGI是性能最佳,服务器资源消耗最少的RoR部署方案,事实上目 前RoR网站部署使用最多最流行的也是Lighttpd+FastCGI方式,而JavaEye网站,自然也是这种方式的部署。因此我们可以对各种方案进 行一个性能优劣的排队:

Lighttpd+FastCGI > Lighttpd+Mongrel > Nginx+Mongrel > Apache+Mongrel > Ngignx+FastCGI > Apache+FastCGI

其中Lighttpd+FastCGI是性能最佳方案,而Apache+FastCGI是性能最差方案。

有些细心的同学可能会产生一个新的疑问?你说到底,之所以Lighttpd跑RoR性能最好,还是在于Lighttpd接收数据不限定缓冲区的大 小,而Apache/Nginx限定了缓冲区大小所至。那为什么Nginx要限制呢?Lighttpd如果不限制的话,会不会导致Lighttpd内存爆 掉?

Nginx限制Proxy Buffer Size其实也有道理,因为Nginx并不是为RoR量身打造的Web服务器,Nginx最广泛的用途还是高负载大访问量的代理服务器,在Nginx主要 的应用场合,如果不做这样的限制,那Nginx端的资源消耗就相当高了,有可能会拖累所代理的服务速度。

Lighttpd主要用途之一就是提供高性能的FastCGI支持的Web服务器,所以必须为FastCGI量身打造。Lighttpd端承担的 负载越高,就越能有效的加快FastCGI执行速度。其实我们稍微心算一下,假设Lighttpd后面挂1000个FastCGI进程,每个 FastCGI进程同时送过来50KB的页面数据,Lighttpd就是全部吃下来,也不过只消耗50MB的内存而已,而事实上1000个FastCGI 进程足以支撑每日上千万的大网站了。

只有当我们使用服务器端程序控制大文件下载的时候,有可能造成Lighttpd内存暴涨,例如某个用户使用100个线程并发下载JavaEye圈 子的共享文件,在没有特殊处理的情况下,Lighttpd将全部吃下100个FastCGI进程送过来的10MB数据,就会立刻暴涨1GB的内存。这种情 况怎么办呢?其实我们也有办法让Lighttpd一点内存都不吃, 请看我写的另外一篇文章:RoR网站如何利用lighttpd的X-sendfile功能提升文件下载性能

可能很多人看了我的文章,对结论觉得很诧异,既然Lighttpd+FastCGI这样好,为什么那么多人都推崇Mongrel,否定FastCGI呢?我想,不外乎几个原因:

一、Lighttpd+FastCGI配置起来比较专业,而Mongrel配置简单

尽管我当初第一次搭建Lighttpd+FastCGI环境没费什么周折,但是我观察到非常多的Ruby程序员很难成功搭建一个 Lighttpd+FastCGI的环境出来,很多人连Lighttpd都无法独立的运行起来。这也许是因为很多程序员习惯了Windows开发环境,对 于Unix上面通过源代码编译安装的方式过于陌生造成的。而我从97年开始使用Unix,至今已有10年历史,因此搭建这样简单的系统,对我来说不造成什 么障碍。

而Mongrel就简单了,gem install mongrel安装完毕,mongrel_rails start启动,哪个人不会?毕竟绝大多数开发人员和部署人员不是高手,他们熟悉哪种方式,自然就会推崇哪种方式。

二、Mongrel可以独立作为Web服务器运行,开发环境和部署环境统一

一般来说,程序员肯定是尽量保持开发环境和部署环境的一致性,避免部署到生产环境出现不测的后果。既然在开发环境熟悉了Mongrel,当然更加愿意在生产环境使用Mongrel,而不愿意碰没有接触过的Lighttpd。

三、Mongrel支持HTTP协议,因此不论监控还是集成其他服务都比较简单,容易玩出更多的花活。

HTTP协议要比FastCGI协议普及的多,因此通过HTTP方式的监控工具,群集管理工具,集成其他服务的工具都是一抓一大把。而支持 FastCGI的第三方工具就少得可怜了。你要玩很多花活出来,用FastCGI的话,就难免得自己开发相应的工具,那当然不如使用Mongrel方便 啦。

解决WordPress中文URL不存在并让其支持中文链接及其TAG

七月 1st, 2010 No comments

下午在安装调试WordPress的时候做了个固定链接(/%postname%),但是通过WP内部的URL居然不能访问 经过多方查找资料才发现问题原因。WP 由于使用的是UTF8字符集.但是URL访问提交过来的URL中文字符是GBK 所以根据这个GBK的字符串查找文章标题 肯定是找不到.. 所以要对这个GBK字符串转换成UTF8

经过多方查找,终于知道了不用插件只需简单的修改两句代码就可以支持汉字链接了。
以下是修改方法

修改wp-includeclasses.php文件:

1、找到

$pathinfo = $_SERVER['PATH_INFO'];

修改为

$pathinfo = mb_convert_encoding($_SERVER['PATH_INFO'], 'UTF-8', 'GBK');

2、找到

$req_uri = $_SERVER['REQUEST_URI'];

修改为

$req_uri = mb_convert_encoding($_SERVER['REQUEST_URI'], 'UTF-8', 'GBK');

(以上两处修改都在函数parse_request()内)

经过修改之后 WordPress URL里就可以支持中文字符串了