nginx+factcgi 下使用 ob_flush

Nginx与php-cgi是两个独立的程序,通过TCP或Unix套接字通信,不像Apache那样是集成在一起的。所以,Nginx有fastcgi 缓冲区,数据超出缓冲区大小、或程序执行完,才会将内容输出到客户端。如果要使用ob_flush,不能开启gzip压缩输出。

nginx.conf:

fastcgi_buffer_size 4k;
fastcgi_buffers 8 4k;
gzip off;

php.ini:

output_buffering = Off
<?php

set_time_limit(0);
ob_end_clean();
ob_implicit_flush(1);
for($i = 0; $i < 10; $i++)
{
    echo $i . \n";
    echo str_repeat(' ', 1024*4);
    sleep(1);
}

其中 echo str_repeat(' ', 1024*4);

使得fastcgi_buffer_size 4k; 的缓冲区满,从而输出内容到浏览器

参考: http://blog.s135.com/nginx_php_v6/2/1/

2010-03-08 121 buffer fastcgi nginx ob_flush php

lighttpd + PHP(fastcgi) 配置

php(fastcgi) 5.2.6 编译参数

./configure  --prefix=/usr/local/php --with-mysql=/usr/local/mysql --with-gd=/usr --enable-calendar --with-zlib --with-bz2 --with-curl --with-mysqli=/usr/local/mysql/bin/mysql_config --enable-mbstring --with-openssl --enable-zend-multibyte --with-gettext --enable-exif --with-png-dir=/usr --with-jpeg-dir=/usr --with-libxml-dir=/usr --enable-gd-native-ttf --enable-dom --with-freetype-dir=/usr --with-iconv-dir=/usr --enable-fastcgi

lighttpd 1.5.0 编译参数

./configure --prefix=/usr/local/lighttpd --with-mysql=/usr/bin/mysql_config --with-openssl --with-pcre --with-bzip2 --enable-lfs --with-linux-aio

添加fastcgi 及lighttpd执行用户

groupadd www
useradd -g www -s /sbin/nologin -d /dev/null www

复制lighttpd源码包内 doc/spawn-php.sh 并修改如下

#!/bin/bash

## ABSOLUTE path to the spawn-fcgi binary
SPAWNFCGI="/usr/local/lighttpd/bin/spawn-fcgi"
## ABSOLUTE path to the PHP binary
FCGIPROGRAM="/usr/local/php/bin/php-cgi"
## TCP port to which to bind on localhost
FCGIPORT="1026"
## SOCKET to which to bind on localhost
FCGISOCKET="/tmp/php-fastcgi1.sock"
## number of PHP children to spawn
PHP_FCGI_CHILDREN=16
## maximum number of requests a single PHP process can serve before it is restarted
PHP_FCGI_MAX_REQUESTS=1000
## IP addresses from which PHP should access server connections
FCGI_WEB_SERVER_ADDRS="127.0.0.1"
# allowed environment variables, separated by spaces
ALLOWED_ENV="HOME PATH USER"
## if this script is run as root, switch to the following user
USERID=www
GROUPID=www

################## no config below this line
if test x$PHP_FCGI_CHILDREN = x; then
  PHP_FCGI_CHILDREN=5
fi

export PHP_FCGI_MAX_REQUESTS
export FCGI_WEB_SERVER_ADDRS
ALLOWED_ENV="$ALLOWED_ENV PHP_FCGI_MAX_REQUESTS FCGI_WEB_SERVER_ADDRS"

# port
#if test x$UID = x0; then
#  EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN"
#else
#  EX="$SPAWNFCGI -p $FCGIPORT -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN"
#fi

# socket
if test x$UID = x0; then
  EX="$SPAWNFCGI  -s $FCGISOCKET -f $FCGIPROGRAM -u $USERID -g $GROUPID -C $PHP_FCGI_CHILDREN"
else
  EX="$SPAWNFCGI  -s $FCGISOCKET -f $FCGIPROGRAM -C $PHP_FCGI_CHILDREN"
fi

# copy the allowed environment variables
E=
for i in $ALLOWED_ENV; do
  E="$E $i=${!i}"
done
# clean the environment and set up a new one
env - $E $EX

保存为 spawn-php1.sh 放到 /etc/lighttpd 下, 多个fastcgi实例可复制此文件并修改相关端口号及socket

lighttpd 相关配置 lighttpd.conf 如下

server.use-ipv6 = "disable" # 缺省为禁用
server.event-handler = "linux-sysepoll" # Linux环境下epoll系统调用可提高吞吐量
#server.max-worker = 10 # 如果你的系统资源没跑满,可考虑调高  lighttpd进程数
server.max-fds = 4096 # 默认的,应该够用了,可根据实际情况调整
server.max-connections = 4096 # 默认等于 server.max-fds
server.network-backend = "linux-sendfile"
server.max-keep-alive-requests = 0 # 在一个keep-alive会话终止连接前能接受处理的最大请求数。0为禁止

# 设置要加载的module
server.modules = (
    "mod_rewrite",
    "mod_redirect",
#    "mod_alias",
    "mod_access",
#    "mod_cml",
#    "mod_trigger_b4_dl",
    "mod_auth",
    "mod_expire",
#    "mod_status",
#    "mod_setenv",
    "mod_proxy_core",
    "mod_proxy_backend_http",
    "mod_proxy_backend_fastcgi",
#    "mod_proxy_backend_scgi",
#    "mod_proxy_backend_ajp13",
#    "mod_simple_vhost",
    "mod_evhost",
#    "mod_userdir",
#    "mod_cgi",
    "mod_compress",
#    "mod_ssi",
#    "mod_usertrack",
#    "mod_secdownload",
#    "mod_rrdtool",
    "mod_accesslog" )

# 网站根目录
server.document-root = "/var/www/"
# 错误日志位置
server.errorlog = "/var/log/lighttpd/error.log"
# 网站Index
index-file.names = ( "index.php", "index.html",
                                 "index.htm", "default.htm" )

# 访问日志, 以及日志格式 (combined), 使用X-Forwarded-For可越过代理读取真实ip
accesslog.filename = "/var/log/lighttpd/access.log"
accesslog.format = "%{X-Forwarded-For}i %v %u %t \"%r\" %s %b  \"%{User-Agent}i\" \"%{Referer}i\""

# 设置禁止访问的文件扩展名
url.access-deny = ( "~", ".inc", ".tpl" )

# 服务监听端口
server.port = 80

# 进程id记录位置
server.pid-file = "/var/run/lighttpd.pid"

# virtual directory listings 如果没有找到index文件就列出目录。建议disable。 
dir-listing.activate = "disable"

# 服务运行使用的用户及用户组
server.username = "www"
server.groupname = "www"

# gzip压缩存放的目录以及需要压缩的文件类型
compress.cache-dir = "/tmp/lighttpd/cache/compress/"
compress.filetype = ("text/plain", "text/html")

# fastcgi module
# for PHP don't forget to set cgi.fix_pathinfo = 1 in the php.ini
$HTTP["url"] =~ "\.php$" {
    proxy-core.balancer = "round-robin"
    proxy-core.allow-x-sendfile = "enable"
#    proxy-core.check-local = "enable"
    proxy-core.protocol = "fastcgi"
    proxy-core.backends = ( "unix:/tmp/php-fastcgi1.sock","unix:/tmp/php-fastcgi2.sock" )
    proxy-core.max-pool-size = 16
}

# 权限控制
auth.backend = "htpasswd"
auth.backend.htpasswd.userfile = "/var/www/htpasswd.userfile"
# 基于 evhost 的虚拟主机 针对域名
$HTTP["host"] == "a.lostk.com" {
    server.document-root = "/var/www/lostk/"
    server.errorlog = "/var/log/lighttpd/lostk-error.log"
    accesslog.filename = "/var/log/lighttpd/lostk-access.log"
    # 设定文件过期时间
    expire.url = (
        "/css/" => "access 2 hours",
        "/js/" => "access 2 hours",
    )

    # url 跳转
    url.redirect = (
        "^/$" => "/xxx/index.html",
    )

    # url 重写 (cakephp可用)
    url.rewrite = (
        "^/(css|js)/(.*)$" => "/$1/$2",
        "^/([^.]+)$" => "/index.php?url=$1",
    )

    # 权限控制
    auth.require   = ( "" =>
         (
            "method" => "basic",
            "realm" => "admin only",
            "require" => "user=admin1|user=admin2"  # 允许的用户, 用户列表文件 在上面配置的auth.backend.htpasswd.userfile 里
        ),
    )
}

# 针对端口的虚拟主机
$SERVER["socket"] == "192.168.0.1:8000" {
    server.document-root        = "/var/www/xxx/"
    server.errorlog = "/var/log/lighttpd/test-error.log"
    accesslog.filename = "/var/log/lighttpd/test-access.log"
   # ...
}

fastcgi 以及 lighttpd 启动脚本

#!/bin/sh

startphp(){
    /etc/lighttpd/spawn-php1.sh
    /etc/lighttpd/spawn-php2.sh
}

starthttpd(){
    /usr/local/lighttpd/sbin/lighttpd -f /etc/lighttpd/lighttpd.conf
}

start(){
    startphp
    starthttpd
}

stopphp(){
    killall php-cgi
}

stophttpd(){
    killall lighttpd
}

stop(){
    killall php-cgi lighttpd
}

case "$1" in
    start)
        start
        ;;
    startphp)
        startphp
        ;;
    starthttpd)
        starthttpd
        ;;
    stop)
        stop
    ;;
    stopphp)
        stopphp
        ;;
    stophttpd)
        stophttpd
        ;;
    *)
        echo "Usage: lighttpd {start|stop|startphp|starthttpd|stopphp|stophttpd}"
        RETVAL=1
esac
2008-06-15 155 fastcgi lighttpd php