在 FreeBSD 10.0 上安装和配置 Nginx+PHP+APC+MySQL

上月得知一位同事要退休,留下一些 BSD 机器需要接手(是的,在国外玩技术可以玩到退休~),接下来两个月讨论 FreeBSD/OpenBSD 的机会可能多一些。FreeBSD 10.0 发布的亮点不少,clang 替代了 gcc 成为默认编译器、大幅增强了对虚拟化的支持、下一代软件包管理工具 pkgng 替代了 pkg_add/pkg_delete 成为默认包管理工具、Linux 一直在虚拟化方面遥遥领先 BSD 阵营,这次的发行版本终于包括了 BSD 自己的虚拟化技术 bhyve,…

在 FreeBSD 下安装软件的传统方法是用 ports 源码安装,不过使用 ports 源码编译安装太耗时(尤其是各种库依赖多、大的时候),个人还是喜欢 pkg 这种软件包管理工具直接安装编译好的二进制软件包,不用自己编译,省时省力。

和 Linux 一样,FreeBSD 也能一行命令解决所有安装和软件包依赖问题(下面的输出要比 apt-get/yum 来的清新舒服吧~):

# pkg install nginx php55 php55-extensions pecl-APC mysql56-server
Updating repository catalogue
The following 23 packages will be installed:

	Installing nginx: 1.4.7,1
	Installing php5-session: 5.4.26
	Installing php5-xmlwriter: 5.4.26
	Installing php5-dom: 5.4.26
	Installing php5-xml: 5.4.26
	Installing php5-simplexml: 5.4.26
	Installing php5-ctype: 5.4.26
	Installing php5-posix: 5.4.26
	Installing php5-hash: 5.4.26
	Installing php5-filter: 5.4.26
	Installing php5-tokenizer: 5.4.26
	Installing php5-json: 5.4.26
	Installing php5-sqlite3: 5.4.26
	Installing php5-pdo: 5.4.26
	Installing php5-iconv: 5.4.26
	Installing php5-phar: 5.4.26
	Installing pecl-APC: 3.1.14_1
	Installing php5-xmlreader: 5.4.26
	Installing php5-pdo_sqlite: 5.4.26
	Installing php5-extensions: 1.7
	Installing mysql56-client: 5.6.16_1
	Installing mysql56-server: 5.6.16

The installation will require 149 MB more space

14 MB to be downloaded

Proceed with installing packages [y/N]: y

安装完后把服务加到系统启动文件里:

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

配置 MySQL:

# vi /usr/local/etc/my.cnf
[mysqld]
socket = /tmp/mysql.sock

skip-networking
skip-name-resolve

# service mysql-server start

# /usr/local/bin/mysqladmin -u root password 'password'

配置 PHP 和 PHP-FPM,这里不需要配啥,默认的配置就行:

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

# vi /usr/local/etc/php.ini
# vi /usr/local/etc/php-fpm.conf

# service php-fpm start

配置 APC:

# echo 'apc.enabled="1"' >> /usr/local/etc/php.ini
# echo 'apc.shm_size="32M"' >> /usr/local/etc/php.ini
# service php-fpm restart

配置 Nginx:

# vi /usr/local/etc/nginx/nginx.conf
user  www;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       80;
        server_name  localhost;

        location / {
            root   /usr/local/www/nginx;
            index  index.html index.htm;
        }

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/local/www/nginx-dist;
        }

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

# service nginx start

写个 phpinfo() 页面测试一下 Nginx/PHP/PHP-FPM/APC 组合是否能正常工作。如果一切正常的话访问 http://localhost/info.php 能看到 PHP 环境详细信息:

# vi /usr/local/www/nginx/info.php
<?php phpinfo(); ?>

对 NetBSD 感兴趣的同学可以参考:NetBSD 上安装和配置 Nginx+PHP+FastCGI+MySQL

WordPress 和 APC 的小问题

昨天晚上给一位付费客户安装 APC PHP 加速器 的时候发现一个小问题,访问 WordPress 页面没问题也可以看到 WordPress 管理后台页面,但是无法登录,报错如下:

Fatal error: Call to undefined function wp_dashboard_setup() in /home/vpsee/wordpress/wp-admin/index.php on line 15

关闭 APC 后这个问题就消失了,只要一打开 APC 就报错,进一步调查把问题缩小到一个 APC 配置参数上 apc.include_once_override=1,如果设置成 apc.include_once_override=0 就没有问题。根据 APC 参考手册的说明,apc.include_once_override 参数是用来 Optimize include_once() and require_once() calls and avoid the expensive system calls used. 一般的建议是设置成0(关闭这个选项)。现在解决办法有两个,一个是设置 apc.include_once_override 为 0(这样会影响到所有网站,所有 PHP 站都不能用到 apc.include_once_override 这个优化了):

# vi /etc/php.d/apc.ini

...
apc.include_once_override = 0
...

另一个办法是修改 WordPress 文件(这样只会影响到一个 WordPress 网站),打开 wp-admin/index.php 文件找到 require_once(ABSPATH . ‘wp-admin/includes/dashboard.php’); 这行注释掉后修改成如下:

# vi /home/vpsee/wordpress/wp-admin/index.php

...
/* require_once(ABSPATH . 'wp-admin/includes/dashboard.php'); */
require_once('./includes/dashboard.php');
...

Wikipedia 的 LAMP 架构

Wikipedia.org 是个标准的运行在 LAMP 上的高流量网站,看看能从 Brion Vibber (CTO, Wikimedia Founation)的这篇讲义:Scaling and Managing LAMP at Wikimedia 学到些什么。(图片资源来自:Scaling and Managing LAMP at Wikimedia

数据

每个月100亿 PV
高峰时后每秒达 50000 http requests
约400台 x86 服务器,约250台是 Web Server,剩下的基本上是 MySQL Server
只有7个工程师维护
每个月35000美元的带宽和 hosting 费用

LAMP

Wikipedia 是架在标准 LAMP 上的一个非常好的示例,以下是 Wikipedia.org 用到的一些 stack:

多个不同版本的 Linux,Ubuntu,Debian 等
Apache
PHP
MySQL

Cache

缓存就不用说了,从前端的 web cache,中间的 opcode cache,到后端的 database cache 都需要。Wikipedia 用 Squid + APC + memcached 来完成 cache 工作。Squid 对 wiki 这种内容为主,不经常变化的相对静态的 web 应用很有效。Wikipedia 还用 Squid 做 geographic load balancing,根据不同地理位置访问各地的服务器。只要用到 PHP 的地方就应该用到 opcode cache,Wikipedia.org 选择了 APC,good choice!,VPSee.com 也用 APC:)。memcached 用来缓存数据库的临时 object,不用反复从数据库读取,而且 memcached 可以做成缓存服务器供网上 share object,其他的服务器可以直接读取,比起从磁盘重新读取数据库,网络读取的延迟要小多了。现在大家都用 cache,送礼就送 cache(cash?)!

继续阅读 »

VPS 上用 APC 加速 PHP

PHP 是一个解释型语言,每当浏览器请求服务器上一个 PHP 页面的时候,这个 PHP 页面都要在服务器上载入,分析,解释,然后返回给浏览器。对于一个复杂的 PHP 应用程序,如果有一个加速器能缓存 PHP 的中间代码避免每次重新载入同样的 PHP 页面将会很好的提高性能,因为每次浏览器请求将会直接从服务器缓存中读取已被解释过页面,不必再让服务器从磁盘重新读取,节约了磁盘 IO 的时间,也节约了CPU 解释页面的时间。所以对于复杂的 PHP 应用,会有大幅的性能提升。

像这样的加速器有很多,最出名的几个 PHP 开源加速器是:APC,eAccelerator 和 XCache。这里介绍安装和配置 APC。对于 64/128MB 的 VPS,VPSee 不推荐使用加速器,原因很简单,加速器需要适量的内存才能表现出良好的性能,64MB 运行一个 WordPress 刚刚好,还腾不出内存出来运行加速器。

安装必要软件包

# yum install gcc make
# yum install pcre pcre-devel
# yum install php-pear
# yum install php-devel
# yum install httpd-devel

安装 APC

# pecl install apc 

配置 APC

新建一个 apc.ini,加入下面配置:

# vi /etc/php.d/apc.ini
extension = apc.so
apc.enabled = 1
apc.shm_size = 32
apc.include_once_override = 1
apc.mmap_file_mask = /tmp/apc.XXXXXX

载入 APC

如果用的是 Apache 的话就重新启动 Apache,如果用 Nginx/FastCGI 就重启 FastCGI

# /etc/init.d/httpd start

测试

如果想看 APC 正在干嘛,就把 apc.php 拷贝到你的 web 目录,用浏览器访问 apc.php,就可以看到很清楚的数据和图表。先查找 apc.php 在哪,如果 locate 报错就先 updatedb 再 locate,最后打开浏览器访问 http://www.vpsee.com/apc.php 看效果。

# locate apc
locate: can not open `/var/lib/mlocate/mlocate.db': No such file or directory

# updatedb

# locate apc.php
/usr/share/pear/apc.php

# cp /usr/share/pear/apc.php /home/www/vpsee.com