RSS
 

Author Archive

http header中缺少Content-Type导致$_POST为空

27

今天出现一个诡异的情况,$HTTP_RAW_POST_DATA是有值的,但是$_POST却是空的array()。

反复尝试后发现是因为header中缺少Content-Type,设置Content-Type : application/x-www-form-urlencoded; charset=UTF-8 之后,就搞定了。

非常诡异的问题,总之以后养成设置Content-Type的好习惯就对了。

 
 

关于APC的性能优化,请看下面这段话

25

If you want to make the best use out of autoload with an APC cache don’t use spl_autoload. It uses relative paths and thus will perform a stat even with apc.stat=0 (either that, or it doesn’t work at all).

Instead make a custom function and use require/include with an absolute path (register it with spl_autoload_register).

Do NOT use *_once functions or a relative path. This will fail harder than spl_autoload.

Also avoid using file_exists and is_file. This will also perform a stat.

Why are stats bad? Because they access the file system. PHP does have a stat cache that helps, but it defeats the purpose of apc.stat = 0.

It’s also good to keep in mind that it’s good to keep your custom autoload function simple. This is my Loader class:

class Loader
{
    public static function registerAutoload()
    {
        return spl_autoload_register(array(__CLASS__, 'includeClass'));
    }

    public static function unregisterAutoload()
    {
        return spl_autoload_unregister(array(__CLASS__, 'includeClass'));
    }

    public static function includeClass($class)
    {
        require(PATH . '/' . strtr($class, '_\\', '//') . '.php');
    }
}

Also want to point out that APC does an optimization with require/include (not *_once) with relative paths if require/include is done in the global scope (and isn’t conditional). So it would be a good idea to explicitly include files you know you’re going to use on every request (but don’t use *_once). You could, for example, add a “registerProfiledAutoload” to the above class and keep track of what you’re including to help you determine what you could explicitly include (during development, not production). The key is try not to make heavy use out of autoload.

If you must use relative paths and don’t care about having to lower-case your file-names then spl_autoload works great.

 
 

强制指定javascript的编码

15

部分用gb2312编码的用户反应javascript装载之后出现乱码,还有各种奇怪的问题,明显都是把utf-8的javascript当成gb2312来解析导致的。

首先尝试了给<script>标签加上chareset=”utf-8″,解决了部分问题,但是仍然部分情况下是乱码。

接着尝试了类似css的 @charset “utf-8″,IE直接报错。

最后发现还是web server设置header最靠谱。nginx设置header方法是在server的配置中加入:

charset utf-8;

 
 

最好还是设置一下date.timezone

11

php 5.4.0开始,针对那那些既没有设置date.timezone,也没有执行过date_default_timezone_set()函数的情况下执行date()函数,开始抛出warning。所以还是最好在php.ini或者fpm.conf中设置一下timezone吧
It is not safe to rely on the system’s timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected the timezone ‘UTC’ for now, but please set date.timezone to select your timezone.

 
 

curl的header参数

08

今天解决一个问题,服务器去连一些主机,总是得到错误的结果,连另一些却完全没问题。

查了半天,发现是curl有一个header参数,Expect:,如果不设置,则会输出一个Expect:100-continue(curl默认行为),一些webserver不认识这个,于是就出错了。

解决办法是设置’Expect:’

鸟哥曾经在博客中介绍过这个:
http://www.laruence.com/2011/01/20/1840.html

 
 

用php渲染javascript

08

在webapp时代,代码开发的重心转移到了javascript端,几乎不可避免的,我们会需要在javascript代码中插入一些和数据/环境有关的动态代码。

用php渲染javascript是最简单有效的方法。

不过在php5-fpm 5.3.10版本中,直接用php渲染.js文件,会出现一个Access denied.错误。

网上搜了好几回,才发现新版本php-fpm中增加了一个蛋疼的选项:security.limit_extensions,默认值是.php

也就是说如果.js文件送到php-fpm处理会以安全为由拒绝,把.js加入security.limit_extensions就可以了。

 
 

true or false?

26

最近在看同伴们的代码。发现if else的部分总是会出现一些意外的情况。
对于js/php这样的弱类型语言来说,代码书写虽然非常灵活,但实际上却充满陷阱,边缘条件下都非常容易出错。

比如整数0和字符串’0′:
对于javascript来说,0是false,而’0′是true。但是对于php来说,0是false,’0′也是false。

再蛋疼一点,字符串’00′,在php中,竟然变成true。

 
 

购买了Linode 512主机,架了一个VPN翻墙

18

两年前买的HostMonster主机快要到期了,准备物色新主机。由于需求越来越复杂,我需要一个可以完全自己配置的环境,于是基于Xen的VPS主机Linode成了最佳选择,再加上它最近开通了东京数据中心,从国内ping只有120ms,绝对是翻墙越货最佳之选。

花了一个小时就搞定了信用卡支付,ubuntu系统的安装,nginx/php5/mysql/phpmyadmin安装,在国内的独立服务器上已经干过无数次了。基本上都快成为本能了。

值得一提的是在东京机房使用ubuntu的apt-get,需要修改一下源。日本最快的源是jp.archive.ubuntu.com,批量将us.archive.ubuntu.com替换成jp.archive.ubuntu.com就可以了。

接下来,就是配置VPN了,这才是VPS主机最大的价值。

  1. 先安装pptpd:
    apt-get install pptpd
  2. 配置pptpd:
    修改/etc/pptpd.conf配置文件,将以下两行的注释去掉
    localip 192.168.0.1
    remoteip 192.168.0.201-245
  3. 修改/etc/ppp/options配置文件,根据服务器所在的网络设置DNS服务器,我的Linode东京节点的DNS服务器设置是:

    ms-dns 106.187.34.20
    ms-dns 106.187.35.20
    ms-dns 106.187.36.20

    我后来发现似乎不设置DNS也可以,系统会直接使用服务器/etc/resolve.conf中的设置。
  4. 修改/etc/ppp/chap-secrets文件,设置密码
    username pptpd password *
    至此vpn已经可以直接拨通了,注意,在ubuntu上连接VPN要把Use Point-to-Point encryption (MPPE)的选项勾上。
  5. 修改/etc/sysctl.conf
    net.ipv4.ip_forward=1
  6. 修改/etc/rc.local,加入:
    iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE
    然后重启,就大功告成啦!twitter/facebook的打开速度嗷嗷快。
 
 

在header信息中隐藏php信息

17

在php渲染的网页header信息中,会包含php的版本号信息,比如: X-Powered-by: php/5.3.3,这有些不安全,有些黑客可能采用扫描的方式,批量寻找低版本的php服务器,利用php漏洞(比如最近流行的hash冲突)来攻击服务器。

php.ini中有一个选项可以控制是否暴露这个信息,那就是:
expose_php = On
默认值是On,改成Off之后,就不会显示php版本信息啦。

或者在php-fpm的pool配置文件中设置:

php_admin_flag[expose_php] = off

 
 

重负荷nginx的几个关键配置参数

15

不知不觉网站PV就爆发了。nginx压力越来越大,一些默认参数就显得不够用了。

我们的主服务器硬件配置非常健壮(双路至强5620 + 48GB内存 + SSD),理论上可以承受每天过500万的PV,当然,前提是优化得够好。

简单罗列一下优化过的几个参数:

  1. ulimit -n 65535这个参数位于/etc/default/nginx 中,或者/etc/init.d/nginx 文件中直接设置。

    默认是1024,意思是最多打开的文件个数。1024怎么够,至少开到8192,网上很多文章都直接开到了65535。

  2. worker_processes 8;
    worker数量,位于nginx.conf头部,一般来说有几个cpu核心开几个,不算超线程。
  3. worker_rlimit_nofile  65535;
    位于nginx.conf头部,也是文件数量限制,直接开大吧。
  4. worker_connections 4096;
    位于nginx.conf中,默认是1024,也不够。
  5. 另外,建议编译nginx的时候顺带编译status模块,以便监视性能。

    location /status/ {
    stub_status on;
    }

小小炫耀一下服务器的status参数,想当年刚用nginx的时候,Writing参数不是0就是1,现在已经这么大了:

Active connections: 2140
server accepts handled requests
 14727928 14727602 24524267
Reading: 92 Writing: 28 Waiting: 2020