我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
标签 #PHP

Ubuntu 12.04 部署 Nginx + PHP-FPM 5.4 + APC

为什么选择这几个软件,和这几个版本?

  • Ubuntu的新版本一向很坑, bug成堆, 而12.04是一个LTS版本, 稳定性有保证. 而相比于其他发行版, Ubuntu是最易用的.
  • Nginx是一个轻量级的, 擅长并发的Web服务器, 相比于Apache, 它并发性能更好, 占用资源更少.
  • 和Nginx配合的话, 毫无疑问要选择PHP-FPM, 它是一个专用于PHP的FastCGI管理器.
  • PHP5.4 版本丢掉了很多历史包袱, 可以获得更高的安全性, 同时还有新的功能, 比如数组的方括号简写形式.
  • APC是一个开源的PHP字节码缓存器, 目前非常活跃, 且非常贴近PHP开发小组, 有望被内置到PHP6中.

安装软件包

12.04的默认源里面只有5.3版本的PHP, 而且nginx也比较旧, 所以我们需要自己添加源:

add-apt-repository ppa:ondrej/php5
add-apt-repository ppa:nginx/development
apt-get update

如果没有add-apt-repository这个脚本则需要:

apt-get install python-software-properties

ppa:ondrej/php5 这个是来自Debain的最新PHP构建. ppa:nginx/development 是来自官方的Nginx构建.

apt-get install nginx php5-cli php5-fpm php-pear build-essential libpcre3-dev
  • nginx - Nginx主程序
  • php5-cli - 命令行模式
  • php5-fpm - FPM模式
  • php-pear - PHP包管理器和扩展管理器(包括pecl)
  • build-essential - 编译环境(需要编译APC)
  • libpcre3-dev - 经测试APC依赖的一个库

配置APC

pecl install apc

然后pecl会自动下载并编译APC, 但APC没有默认被加入php.ini, 所以我们要:

echo "extension=apc.so;" >> /etc/php5/fpm/php.ini
cp /etc/php5/fpm/php.ini /etc/php5/cli/php.ini

APC 有个自带的监视器, 可以查看缓存的详细信息, 如内存占用, 命中率, 已缓存的文件等等, 有需要的话可以自行复制到Web目录.

cp /usr/share/php/apc.php /root/web/

配置Nginx

创建一个新站点:

cat > /etc/nginx/sites-enabled/web.conf

server {
    listen 80 default_server;
    server_name xxoo.xo;

    root /root/web;
    index index.html index.php;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

重启Nginx和PHP-FPM:

service nginx restart
service php5-fpm restart

把测试网页放到 /root/web/ 就可以了, 在此我们选用一个PHP探针做测试(来自http://www.yahei.net/tz/).

性能测试

应该说两台测试机差异很大, 不是很公平(我也说不好是偏向哪一方) … 大家凑合看

测试用例(5个线程, 请求1000次): ab -n1000 -c5 http://xxoo.xo/probe.php

Nginx + PHP-FPM + APC

QPS:1022 (每秒完成请求)

Nginx + Apache + mod_php

QPS:51

LightPHP v4

我又迫不及待地写LightPHP的第四个版本.
原因是RootPanel(RP主机面板)的代码又出现了危机,如果不修改LightPHP的漏洞,引入一些更先进的理念,恐怕很难再扩展了.

LightPHP v1和v2, 几乎都是我凭空造出来的,在此之前,我没阅读过别人的代码,没用过已有的框架,完全抱着“方便自己”的想法写了这么个库.
现在看来,其中很多设计,竟和一些已有的理念不谋而合…..很多时候都是这样.

那是2011年7月,刚刚考完中考,我决定用PHP重写我那原有的Asp.Net的网站.
我写了一个半月,宣告失败,改用PHPWind和WordPress.
失败的原因,很多,PHP基础不扎实,算是一方面.

Asp.Net, 提供给了我一个封装的非常好的框架,我刚刚用Asp.Net的时候,仅仅有VB6的基础,连HTML都不熟. 但Asp.Net却能够让我写出一个个复杂的网站(CMS+博客+论坛), 当然,代码很烂. 很多HTML片段甚至在不同的文件出现了几十次(比如<head>). 但也算是写出来了,这要归功于Asp.Net设计良好的框架,你只需要照着做就行了.

Asp.Net给我的感觉是我仍然在写桌面软件,你可以在代码中像操作窗体控件一样改变HTML <input>标记的值. 像响应窗体控件事件一样响应HTML <button>的点击.

而PHP更为原始,不愧于它“超文本预处理器”的名字,我一个人无法设计出整个网站的架构.
(当时)我对于PHP的C风格的数据库API、Cookie API、需要手动构造表单、处理表单非常不满.
因为Asp.Net的封装,我根本不理解Cookie和表单的工作原理,于是我继续不下去了.

当然我不是说Asp.Net不好,如果能够理解Asp.Net的工作原理,或许能够得到更大的收益.
不过我现在没那个兴趣了,因为我投入了自由软件的阵营.


在最后,我从已经失败的项目中抽取了一个库,叫LightPHP, 我绝对不会告诉你”Light”其实是“光”的意思.

LightPHP v1,有一个灰常简陋的模版系统,可以让多个页面共享一些HTML, 还是基于文本替换的,灰常蛋疼.
还有参考自Abreto的简陋的MySQL数据库封装,只是封装了申请/释放资源(RAII概念)、打开数据库、设置编码的功能.
其实PHP对内存泄漏并不敏感,反正执行完,进程就销毁了…
还有一个类似Asp中的Application, 全局的键/值对储存系统.

LightPHP v1基本上没派上什么用场, 2011年9月我开始搞LightPHP v2.

在MySQL封装中充分的考虑了安全,这时的LightPHP已经可以防御各种SQL注入了.
很简单的一个原则:SQL和参数分离,每一个参数必须经过mysql_real_escape_string()的转义.

引入了登录状态管理,核心设计来自我之前的Asp.Net网站.
只使用Cookie, 不用Session, 每个页面都会重新计算密码,写入Cookie.

应该说LightPHP v2的后端工具(数据库封装什么的)还算是派上一些用场,前端(模版功能)依旧鸡肋….


2012年2月, whtsky开始写PBB( https://github.com/whtsky/PBB ), 这个名字还是我起的呢….我绝对不会告诉你”Pb”是“铅”的意思(PBB = Pb BBS). 我从他的代码(Python)中学到了很多新的理念.
尤其是模版和路由,真的是让我眼前一亮,我从whtsky那学到了很多新的东西,包括使用Github.

我以像Python那样写网站为目标,开始写LightPHP v3.
我为MySQL加入了无需SQL的,基于数组的查询接口(有点类似Mongodb的接口).
重新设计了模版系统,基于缓冲和eval. 加入了路由,每个页面用一个类来对应. 引入了Bootstrap和jQuery.
后来还加了互斥锁、SMTP发信等工具.
而且我为LightPHP v3写了完整的文档和示例——虽然根本没人看.

LightPHP v3的作品则有很多了,如JyBBS( https://github.com/jybox/JyBBS )、RootPanel( http://rp2.jybox.net/ )等.

最近,我又参考了一些PHP框架,ThinkPHP、esoTalk的ET什么的,对很多东西又有了新的认识.


LightPHP v4:

数据库

让NoSQL封装支持更多功能. 支持下面的语法:

$conn("user")->where("xxx","ooo")->sort("id")->top(5)->select();

通过插件的形式支持更多数据库,甚至可以同时支持关系数据库和NoSQL数据库——只要不直接使用SQL的话.

模版/模型

MVC中的Model和View, 之前一直不理解Model层的作用——其实现在也不是很理解.

路由

没啥变化.

缓存(键/值对储存)

调研一下memcache

工具

互斥锁、邮件等,没啥变化

登录状态管理

使用更安全的方式:
像Dropbox一样,可以追踪每一个会话,为每个会话生成不同的令牌.

插件

这个是受ET的启发,要让每一个部件都是可以随时插拔的. 并且可以以插件的形式,随时在任何地方插入功能.

PHP built-in WebServer

PHP从5.4开始内置一个轻量级的Web服务器,不支持并发,定位是用于开发和调试环境(以下适用于Linux以及Windows).

不得不说,在开发环境使用它的确非常方便.
很简单,安装好PHP后,切换到你的工程所在目录,执行(确保php.exe在PATH中):

php -S localhost:8000

这样就在当前目录建立起了一个Web服务器,你可以通过 http://localhost:8000/ 来访问
其中localhost是监听的ip,8000是监听的端口,可以自行修改.

每个请求的信息会打印在终端窗口,类似:

[Thu Jul 21 10:48:50 2011] ::1:39146 GET / - Request read

很多应用中,都会进行URL重写,所以PHP提供了一个设置路由脚本的功能:

php -S localhost:8000 lp-main.php

这样一来,所有的请求都会由lp-main.php来处理,大多数MVC框架都会有一个类似的路由脚本.

所以在这里,我有必要给大家介绍一个支持MVC的轻量级的PHP框架——LightPHP:
项目地址:https://github.com/jybox/LightPHP

####使用XDebug调试
添加下面两行到php.ini

zend_extention=/abosute/path/to/xdebug.dll
xdebug.remote_enable=1

其中第一行的路径务必为绝对路径,XDebug的配置可参考 http://xdebug.org/docs/install

####PHP的其他命令行选项

-a选项可以开启一个交互式的PHP终端:

php -a

-r可以直接执行PHP代码:

php -r 'echo "Hello World";'

-t指定build WebServer的根目录,默认会以当前目录为根目录,你可以使用这个选项修改根目录:

php -S localhost:8000 -t /var/www

参考资料

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2024-04-08.