Linux kernel 的 sendfile 是如何提高性能的

现在流行的 web 服务器里面都提供 sendfile 选项用来提高服务器性能,那到底 sendfile 是什么,怎么影响性能的呢?sendfile 实际上是 Linux 2.0+ 以后的推出的一个系统调用,web 服务器可以通过调整自身的配置来决定是否利用 sendfile 这个系统调用。先来看一下不用 sendfile 的传统网络传输过程:

read(file, tmp_buf, len);
write(socket, tmp_buf, len);

硬盘 >> kernel buffer >> user buffer >> kernel socket buffer >> 协议栈

一般来说一个网络应用是通过读硬盘数据,然后写数据到 socket 来完成网络传输的。上面2行用代码解释了这一点,不过上面2行简单的代码掩盖了底层的很多操作。来看看底层是怎么执行上面2行代码的:

1、系统调用 read() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后 DMA 执行拷贝,把文件数据从硬盘读到一个 kernel buffer 里。
2、数据从 kernel buffer 拷贝到 user buffer,然后系统调用 read() 返回,这时又产生一个上下文切换:从kernel mode 切换到 user mode。
3、系统调用 write() 产生一个上下文切换:从 user mode 切换到 kernel mode,然后把步骤2读到 user buffer 的数据拷贝到 kernel buffer(数据第2次拷贝到 kernel buffer),不过这次是个不同的 kernel buffer,这个 buffer 和 socket 相关联。
4、系统调用 write() 返回,产生一个上下文切换:从 kernel mode 切换到 user mode(第4次切换了),然后 DMA 从 kernel buffer 拷贝数据到协议栈(第4次拷贝了)。

上面4个步骤有4次上下文切换,有4次拷贝,我们发现如果能减少切换次数和拷贝次数将会有效提升性能。在kernel 2.0+ 版本中,系统调用 sendfile() 就是用来简化上面步骤提升性能的。sendfile() 不但能减少切换次数而且还能减少拷贝次数。

再来看一下用 sendfile() 来进行网络传输的过程:

继续阅读 »

Nginx 上配置 WordPress Mu 的重写规则

wordpressmu

WordPress Mu 可以看作是一款多用户版的 WordPress,可以方便架设自己的 BSP,像 blogbus.com,yo2.cn 做的那样。 后台和 WP 差不多,多了一个 Site Admin 用来管理整个 blog, 其他部分和独立的 WP 大同小异。最方便的是 WPMU 和 WP 的部分插件和主题可以通用,基于 WP 丰富的主题和插件,可以很好的应用到 WPMU 上。这样,节约了重新定制主题和寻找插件的时间和资源。

首先需要安装和配置好 Nginx+PHP5+Mysql+FastCGI,然后从官方网站下载 WPMU,安装完毕后打开 nginx.conf,配置 Nginx 以支持 WordPress MU 的 rewrite rules。注意:需要把下面的 vpsee.com 和路径换成你自己的域名和路径;如果不用 WP SuperCache 插件可以把相关部分注释掉。

继续阅读 »

FreeBSD 上安装配置 Nginx+PHP+FastCGI+MySQL

freebsd

在 VPS 里很少看见 FreeBSD 的踪影,主要原因是因为两大开源虚拟系统 Xen 和 OpenVZ 对 FreeBSD 都不是那么友好:(,OpenVZ 不能支持非 Linux 内核的操作系统,Xen 对 FreeBSD 的支持不太好(也可以说FreeBSD 对 Xen 的支持不好)。最近 VPSee 从 Advantagecom 订了一个 256MB 的 Xen VPS,想在上面试试 FreeBSD 先,Advantagecom 不提供换操作系统的面板,每次都要提交 ticket 换系统好麻烦,而且一个月只能换一次系统。VPSee 打算先用一个月的 FreeBSD,然后再换成 Linux。就目前 VPS 的状况来说,VPSee 还是推荐使用 Linux,对于 VDS 或者自己的服务器来说,Linux 和 FreeBSD 都是很棒的操作系统。

安装所需软件

FreeBSD上 有2种安装软件的方法:一种是二进制安装;另一种是源代码安装(Ports collection)。

二进制安装所需软件:

# /usr/sbin/pkg_add -r -v mysql51-server
# /usr/sbin/pkg_add -r -v nginx
# /usr/sbin/pkg_add -r -v php5
# /usr/sbin/pkg_add -r -v php5-mysql
# /usr/sbin/pkg_add -r -v lighttpd

源代码安装所需软件:

# cd /usr/ports/databases/mysql51-server
# make install clean

# cd /usr/ports/lang/php5
# make install clean

# cd /usr/ports/lang/php5-extensions
# make config
# make install clean

# cd /usr/ports/databases/php5-mysql
# make install clean

# cd /usr/ports/www/lighttpd
# make install clean

实际上我们只需要 lighttpd 里面的 spawn-fcgi,所以先把 spawn-fcgi 拷出来再删除 lighttpd。

# cp /usr/local/bin/spawn-fcgi /root/
# /usr/sbin/pkg_delete -v lighttpd-1.4.22
# cp /root/spawn-fcgi /usr/local/bin/spawn-fcgi

配置 MySQL

# cp /usr/local/share/mysql/my-medium.cnf /etc/my.cnf
# chown -R mysql:mysql /var/db/mysql
# /usr/local/bin/mysqld_safe &
# /usr/local/bin/mysqladmin -u root password ‘newpass’

配置 PHP

# cp /usr/local/etc/php.ini-dist /usr/local/etc/php.ini

配置 FastCGI

启动 PHP FastCGI:

# /usr/local/bin/spawn-fcgi -a 127.0.0.1 -p 9000 -u www -g www -f /usr/local/bin/php-cgi

-a 127.0.0.1 : PHP FastCGI 绑定IP地址
-p 9000: PHP FastCGI 指定端口
-u www : PHP FastCGI 用户名
-g www : PHP FastCGI 用户组
-f /usr/local/bin/php-cgi : 指向 PHP5 fastcgi

检查 FastCGI 是否启动:

# sockstat -4 | grep 9000
www      php-cgi    33475 0  tcp4   127.0.0.1:9000        *:*
www      php-cgi    33474 0  tcp4   127.0.0.1:9000        *:*
www      php-cgi    33473 0  tcp4   127.0.0.1:9000        *:*
www      php-cgi    33472 0  tcp4   127.0.0.1:9000        *:*
www      php-cgi    33471 0  tcp4   127.0.0.1:9000        *:*
www      php-cgi    33470 0  tcp4   127.0.0.1:9000        *:*

如果不想每次重启 FreeBSD 都打一边上面的命令的话,把下面 PHP FastCGI 启动/自动代码保存到 FreeBSD 的启动目录(/usr/local/etc/rc.d/phpfcgi)里:

#!/bin/sh
# NGINX FastCGI php5 startup shell script
# Feedback 
# http://bash.cyberciti.biz/web-server/fastcgi-php-server-start-stop-script/
# Set ME #
PROVIDES=php-cgi
LIGHTTPD_FCGI=/usr/local/bin/spawn-fcgi
SERVER_IP=127.0.0.1
SERVER_PORT=9000
SERVER_USER=www
SERVER_GROUP=www
PHP_CGI=/usr/local/bin/php-cgi
PGREP=/bin/pgrep
KILLALL=/usr/bin/killall
### No editing below ####
cmd=$1
 
pcgi_start(){
  	echo "Starting $PROVIDES..."
 	$LIGHTTPD_FCGI -a $SERVER_IP -p $SERVER_PORT -u $SERVER_USER -g 
$SERVER_GROUP -f $PHP_CGI
}
 
pcgi_stop(){
	echo "Killing $PROVIDES..."
	$KILLALL $PROVIDES
}
 
pcgi_restart(){
	pcgi_stop
	pcgi_start
}
 
pcgi_status(){
        $PGREP $PROVIDES > /dev/null
	[ $? -eq 0  ] && echo "$PROVIDES running" || echo "$PROVIDES NOT 
running" 
 
}
 
pcgi_help(){
  	echo "Usage: $0 {start|stop|restart|status}"
}
 
case ${cmd} in
[Ss][Tt][Aa][Rr][Tt]) pcgi_start;;
[Ss][Tt][Oo][Pp]) pcgi_stop;;
[Rr][Ee][Ss][Tt][Aa][Rr][Tt]) pcgi_restart;;
[Ss][Tt][Aa][Tt][Uu][Ss]) pcgi_status ;;
*)      pcgi_help ;;
esac

注意要改成可执行文件:

# chmod +x /usr/local/etc/rc.d/phpfcgi

现在可以用 shell 脚本启动并查看 PHP FastCGI了:

# /usr/local/etc/rc.d/phpfcgi start
# sockstat -4 | less

配置 Nginx

打开 nginx.conf 配置 Nginx:

# vi /usr/local/etc/nginx/nginx.conf

user  www;

 # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
        location ~ \.php$ {
            root           html;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /www/vpsee$fastcgi_script_name;
            include        fastcgi_params;
        }

启动 Nginx:

# /usr/local/etc/rc.d/nginx start

如果启动不了,打开 /etc/rc.conf,加入

# vi /etc/rc.conf
nginx_enable="YES"

# /usr/local/etc/rc.d/nginx restart

测试

用文本写个 php 文件,用 phpinfo() 测试一下 PHP 是否可以运行。

64MB VPS 上优化 Nginx

nginx

Nginx 小巧,高效,稳定等优点非常适合配置不高,内存小的 VPS。这里的优化策略不是让nginx每秒能处理更多的请求,那是一个繁忙网站要做的。记住,这是一个只有 64MB 的 VPS,对于架设一个访问量不大的网站/博客来说,尽可能减少 Nginx 的内存占用率是最重要的,用尽量小的 Nginx 占用内存去满足不大的访问量。

优化 nginx.conf

Nginx 运行的进程数,一般设置成和 CPU 的核数相同。

worker_processes  1;

使用 epoll,Linux 内核2.6版本以上支持 epoll(eventport支持 Soaris,kqueue 支持 BSD系列),worker_connections 每个 Nginx 进程所允许的最大的连接数,max_clients = worker_processes * worker_connections。

 events { 
    use epoll;
    worker_connections  128;
 } 

设置连接的超时时间。

keepalive_timeout  5;


继续阅读 »

Nginx+FastCGI 运行 WordPress 和 WP Super Cache

wordpress

有了一个自己的 VPS 主机以后就自由多了,拥有 root 访问权限,几乎可以做任何事情,VPS 一开通我就迫不及待的想要用 nginx 换掉笨重的 apache,share hosting 就没那么幸运了,只能给什么用什么了。

WP Super Cache 是一个 WordPress 插件,用来给 WordPress 提供缓存,也就是说用户请求一个 WordPress PHP 页面后,WP Super Cache 会把结果转化成 HTML 文件保存下来,这样下次用户访问同一个页面的时候就会优先访问那个已保存的 HTML 文件,这样中间就没有 PHP 解析的过程,所以速度非常快,是高流量博客的必备插件。

说明一下为什么需要 FastCGI?Nginx 体积很小,本身不带 CGI 模块,所以需要和第三方配合以支持各种动态脚本的解析。这些解析脚本是如何和 web server 交流的呢?这时需要一个叫做 FastCGI 的支持。那么什么是 FastCGI 呢?FastCGI 是一个外部程序和 web server 之间打交道的协议/接口,有点像应用程序 API 和操作系统之间的关系。与老的 CGI 比起来,FastCGI 可以同时启动多个进程,而 CGI 程序只能运行在一个进程里,这意味着 FastCGI 的性能比 CGI 好得多;FastCGI 的运行完全和 web server 独立,就是说即使 FastCGI down 掉了也不会影响到 web server。

目前较普遍的有两种方法支持 FastCGI,一种是用 lighttpd 的 spawn-fcgi 程序;另外一种是直接用内嵌在 PHP 里面的 php-cgi。这里以第一种方法(spawn-fcgi)为例。

CentOS 上安装 nginx+spawn-fcgi

安装 nginx 和 spawn-fcgi

# rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/
epel-release-5-3.noarch.rpm

# yum install nginx
# yum install spawn-fcgi


继续阅读 »

Nginx 的多站点配置

nginx

当我们有了一个 VPS 主机以后,为了不浪费 VPS 的强大资源(相比共享主机1000多个站点挤在一台机器上),往往有想让 VPS 做点什么的想法,银子不能白花啊:)。放置多个网站或者博客是个不错的想法,可是如何配置 web 服务器才能在一个 VPS 上放置多个网站/博客呢?如何通过一个 IP 访问多个站点/域名呢?这就是大多数 web 服务器支持的 virtual hosting 功能。这里将描述如何一步一步如何用 nginx 配置 virtual hosting。

nginx 是一个小巧高效的 web 服务器,由俄罗斯程序员 Igor Sysoev 开发,nginx 虽然体积小,但功能一点也不弱,能和其他的 web 服务器一样支持 virtual hosting,即一个IP对应多个域名以支持多站点访问,就像一个IP对应一个站点一样,所以是”虚拟”的。你想在一个 IP 下面放多少个站点就放多少,只要硬盘够大就行。

这里以配置2个站点(2个域名)为例,n 个站点可以相应增加调整,假设:

IP地址: 202.55.1.100
域名1 example1.com 放在 /www/example1
域名2 example2.com 放在 /www/example2

配置 nginx virtual hosting 的基本思路和步骤如下:

把2个站点 example1.com, example2.com 放到 nginx 可以访问的目录 /www/
给每个站点分别创建一个 nginx 配置文件 example1.com.conf,example2.com.conf, 并把配置文件放到 /etc/nginx/vhosts/
然后在 /etc/nginx.conf 里面加一句 include 把步骤2创建的配置文件全部包含进来(用 * 号)
重启 nginx

具体过程

下面是具体的配置过程:

继续阅读 »