一 错误输出
找到php.ini
; Log errors to specified file.
error_log = /Data/logs/php/error.log
比如会捕获到类似信息:
[23-Oct-2011 17:17:41] PHP Fatal error: Class 'Strclass' not found in /Data/webapps/www.aslibra.com/application/errors/error_404.php on line 11
这个有助于分析被访问的页面发生的致命错误或者是警告
二 慢日志
慢日志和数据库的慢查询有点类似,会记录下来执行超过多少时间的php执行的内容
这个如果是用fast-cgi的话,可以在fpm的配置里面有
'0s' means 'off'
<value name="request_slowlog_timeout">10s</value>
The log file for slow requests
<value name="slowlog">/Data/logs/php/slow.log</value>
比如上面是记录超过10秒的php,记录在相应的文件里
你可以拿到类似的日志:
script_filename = /www.aslibra.com/index.php
[0x00007fffae1869e0] mysql_query() /www.aslibra.com/system/database/drivers/mysql/mysql_driver.php:163
[0x00007fffae186bb0] _execute() /www.aslibra.com/system/database/DB_driver.php:453
[0x00007fffae186eb0] simple_query() /www.aslibra.com/system/database/DB_driver.php:299
[0x00007fffae1870b0] query() /www.aslibra.com/v3/models/myuser.php:51
[0x00007fffae1872a0] get_users_by_uids() /www.aslibra.com/v3/models/myuser.php:58
[0x00007fffae187580] get_users() /www.aslibra.com/v3/controllers/pic.php:134
[0x00007fffae187870] experience() /www.aslibra.com/v3/controllers/pic.php:349
[0x00007fffae187940] user() unknown:0
[0x00007fffae187cf0] call_user_func_array() /www.aslibra.com/system/core/CodeIgniter.php:297
[0x00007fffae187f40] +++ dump failed
日志里包含的信息:执行时间,访问入口,执行的函数的顺序和所有父级调用关系
比如这里可以获知是数据库查询时出现过慢,调用关系也一目了然,可以去排查跟踪了
使用3G卡的一个最大问题就是 流量=金钱,这个对所有网站也是这样的
如何控制这个流量呢?
一个最简单的做法就是加防火墙,只是白名单的流量可以使用,因为大部分后台程序都可能用掉你的流量,你明确自己要用3G网络的流量就最方便了。
比如我们运维使用,则开放22端口请求即可,其它的就可以干掉了
但如果还需要上网呢? 可以用sock5代理,这样也保证所有访问都是正常的
苹果电脑里可以借助第三方软件控制防火墙
http://www.hanynet.com/waterroof/
add 01004 allow ip from me to any dst-port 3306 keep-state
add 01100 deny ip from any to any
add 65535 allow ip from any to any
sock5代理:
浏览器设置使用sock5代理即可,firefox可以用autoproxy插件
注意,系统里设置代理就可能全局了,不起限流作用了
最近想用php写一个爬虫,就需要解析html,在sourceforge上找到一个项目叫做PHP Simple HTML DOM Parser,它可以以类似jQuery的方式通过css选择器来返回指定的DOM元素,功能十分强大。
首先要在程序的开始引入simple_html_dom.php这个文件
include_once('simple_html_dom.php');
PHP Simple HTML DOM Parser提供了3种方式来创建DOM对象
目前使用MySQL的网站,多半同时使用Memcache作为键值缓存。虽然这样的架构极其流行,有众多的案例,但过于依赖Memcache,无形中让Memcache成为故障的根源:
- Memcache数据一致性的问题:当MySQL数据变化后,如果不能及时有效的清理掉过期的数据,就会造成数据不一致。这在强调即时性的Web2.0时代,不可取。
- Memcache崩溃后的雪崩效应:作为缓存的Memcache一旦崩溃,MySQL很可能在短时间内承受高负载而宕机。据说前段时间新浪微博就遭遇了这样的问题。
注:关于清理过期数据的问题,可以在程序架构上想办法,如果数据操作有统一DAO封装的话,可以利用Observer模式来清理过期数据,非主题内容,资料自查。
面对这些问题,HandlerSocket项目是个不错的解决方案,它通过插件的方式赋予MySQL完整的NoSQL功能,从原理上讲,它跳过MySQL中最耗时的语法解析,查询计划等步骤,直接读取数据,如果内存够大,能装下索引,MySQL的查询效率能提高若干倍!
性能测试:Using MySQL as a NoSQL – A story for exceeding 750,000 qps
因为HandlerSocket的性能足够好,所以就没有必要使用Memcache了,能节省大量的硬件资源,相当低碳!而且HandlerSocket操作的是MySQL放在内存中的索引,没有额外的缓存,所以自然就不存在数据一致性的问题。
安装
如果使用Percona Server版本的MySQL就简单了,因为它已经内置了HandlerSocket支持,不过考虑到其内置的版本不够新,存在一些早已修复的BUG,所以最好采用源代码编译。
注:旧版本HandlerSocket的一些问题可参见:What’s up with HandlerSocket?
官方已经有了一份简单的安装文档,但在我实际安装时,遇到了一些其他未说明的问题,所以这里就把相应的安装过程再写一遍。
首先要确保已经安装了MySQL5.1以上的版本,我用的是Ubuntu操作系统,事先已经用apt安装了MySQL5.1.37,同时还需要相应的mysql_config,如果是Ubuntu的话,可以:
shell> aptitude install libmysqld-dev
注:如果你用的MySQL是从源代码编译的或官方提供的二进制版本,可以略过此步。
接着下载一份和系统MySQL版本一致的MySQL源代码和HandlerSocket源代码:
shell> tar zxf mysql-5.1.37.tar.gz shell> tar zxf ahiguti-HandlerSocket-Plugin-for-MySQL-1.0.6-76-gf5f7443.tar.gz shell> cd ahiguti-HandlerSocket-Plugin-for-MySQL-f5f7443 shell> ./autogen.sh shell> ./configure --with-mysql-source=../mysql-5.1.37 \ --with-mysql-bindir=/usr/bin \ --with-mysql-plugindir=/usr/lib/mysql/plugin
其中的参数含义如下:with-mysql-source表示MySQL源代码目录,with-mysql-bindir表示MySQL二进制可执行文件目录(也就是mysql_config所在目录),with-mysql-plugindir表示MySQL插件目录,如果不清楚这个目录在哪,可以按如下方法查询:
mysql> SHOW VARIABLES LIKE 'plugin%'; +---------------+-----------------------+ | Variable_name | Value | +---------------+-----------------------+ | plugin_dir | /usr/lib/mysql/plugin | +---------------+-----------------------+
运行命令后,如果你使用的是MySQL5.1.37版本的话,会遇到如下错误信息:
MySQL source version does not match MySQL binary version
明明我们的MySQL源代码版本和二进制版本都是5.1.37,为什么还会出现这个错误呢?通过查询HandlerSocket的编译脚本,发现原来它会检索MySQL源代码目录中的VERSION文件,可MySQL5.1.37的源代码目录里不知何故竟然没有这个文件,所以就报错了,既然知道了原因,那我们就照猫画虎做一个VERSION文件放到MySQL源代码目录,内容如下:
MYSQL_VERSION_MAJOR=5 MYSQL_VERSION_MINOR=1 MYSQL_VERSION_PATCH=37 MYSQL_VERSION_EXTRA=
再次运行configure脚本,应该就OK了,把剩下的步骤进行完:
shell> make shell> make install
接着需要配置一下HandlerSocket,编辑MySQL配置文件,加入如下内容:
[mysqld] loose_handlersocket_port = 9998 # the port number to bind to (for read requests) loose_handlersocket_port_wr = 9999 # the port number to bind to (for write requests) loose_handlersocket_threads = 16 # the number of worker threads (for read requests) loose_handlersocket_threads_wr = 1 # the number of worker threads (for write requests) open_files_limit = 65535 # to allow handlersocket accept many concurrent # connections, make open_files_limit as large as # possible.
此外,InnoDB的innodb_buffer_pool_size,或MyISAM的key_buffy_size等关系到缓存索引的选项尽可能设置大一些,这样才能发挥HandlerSocket的潜力。
注:apt包管理下的配置文件一般是/etc/mysql/my.cnf,否则一般是/etc/my.cnf
最后登陆MySQL并激活HandlerSocket插件:
mysql> INSTALL PLUGIN handlersocket soname 'handlersocket.so';
重启一下MySQL服务,如果没有问题,就能在MySQL里看到HandlerSocket的线程了:
mysql> SHOW PROCESSLIST;
也可以通过查询刚配置的端口是否已经被MySQL占用来确认是否安装成功:
shell> lsof -i :9998 shell> lsof -i :9999
完活儿!现在你的MySQL已经具备NoSQL的能力了!
实战
首先创建一个测试用的表:
CREATE TABLE IF NOT EXISTS `test`.`t` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `a` varchar(10) NOT NULL, `b` varchar(10) NOT NULL, PRIMARY KEY (`id`), KEY `a_b` (`a`,`b`) ) ENGINE=InnoDB;
注:理论上HandlerSocket支持MyISAM,InnoDB等各种引擎,不过推荐使用InnoDB。
HandlerSocket的协议非常简单,指令通过TAB分割,一行就是一个请求。本文用到了:
- 打开索引:P <索引标识> <数据库> <表> <索引> <字段>
- 插入数据:<索引标识> ‘+’ <参数个数> <参数1> … <参数N>
- 读取数据:<索引标识> <操作> <参数个数> <参数1> … <参数N> <条数> <偏移>
SQL原型:INSERT INTO test.t (id, a, b) VALUES (1, ‘a1′, ‘b1′), (2, ‘a2′, ‘b2′)
shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P 1 test t PRIMARY id,a,b 0 1 1 + 3 1 a1 b1 0 1 0 1 + 3 2 a2 b2 0 1 0
注:使用HandlerSocket时,因为没有实际运行SQL,所以Binlog记录的是Row格式。
SQL原型:SELECT id, a, b FROM test.t WHERE id = 1 LIMIT 1
shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P 1 test t PRIMARY id,a,b 0 1 1 = 1 1 1 0 0 3 1 a1 b1
SQL原型:SELECT id, a, b FROM test.t WHERE id >= 1 LIMIT 2
shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P 1 test t PRIMARY id,a,b 0 1 1 >= 1 1 2 0 0 3 1 a1 b1 2 a2 b2
SQL原型:SELECT id, a, b FROM test.t WHERE a = ‘a1′ AND b = ‘b1′ LIMIT 1
shell> telnet localhost 9999 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. P 1 test t a_b id,a,b 0 1 1 = 2 a1 b1 1 0 0 3 1 a1 b1
对HandlerSocket一个常见的误解是只能执行PRIMARY类型的KV查询,实际上只要支持索引,一般的简单查询它都能胜任,篇幅所限,这里就不多说了,如果你觉得直接操作telnet有些吃力,也可以使用自己熟悉的客户端来测试,官方文档里有介绍。
注:HandlerSocket作者写了一个不错的PPT可以参考:HandlerSocket plugin for MySQL
记:MySQL5.6提供原生的Memcached API,实际就是KV型NoSQL了,但HandlerSocket并不局限于KV形式,所以仍然有生存空间。
互联网技术发展犹如一列高速运行的火车,下一站:HandlerSocket!大家做好准备吧。
原文:http://huoding.com/2011/04/10/62
另外,rewrite时,默认会把查询字符带上的,加上问号即可解决。
假设要把 /question.php?qid=123 的地址跳转到 /question/123.html
rewrite ^ /question/$arg_qid.html redirect;
}
我们会发现地址变成 /question/123.html?qid=123
你要的参数都可以找到 $arg_qid ( $arg_变量名称 )
nginx里面,在后面加上问号就可以不带上查询字符了
rewrite ^ /question/$arg_qid.html? redirect;
}
对值有要求的,可以匹配 $args ,比如(复制别人的)
if ($args ~* "/?param1=val1¶m2=¶m3=[0-9]+¶m4=.+¶m5=[0-9]+") {
rewrite ^ http://www.example.com/newparam/$arg_param3/$arg_param4? last;
}
}
-rw-r--r-- 1 root root 22 Aug 21 00:50 a.html
-rw-r--r-- 1 root root 32 Aug 21 00:51 index.html
[root@aslibra ~]# find . -name "*.html" | xargs sed -i 's/192/9999/'
[root@aslibra ~]# cat *.html
sdfjsldjf
9999
sdfdfdf
sldkjflsdjf
ksdjfsjd 9999
sdfsdf
[root@aslibra ~]# find . -name "*.html" | xargs sed -i 's/9999/+++++/'
[root@aslibra ~]# cat *.html
sdfjsldjf
+++++
sdfdfdf
sldkjflsdjf
ksdjfsjd +++++
sdfsdf
上面代码在linux下正常,可在mac下不正常了:
sed: 1: "./a.html": invalid command code .
sed方式有点不一样,需要用 sed -iE ,当然,我们可以找到别的方式,比如perl(搜得):
perl -pi -e 's/9999/+++++/g'
下面我们看看怎么修改svn库的地址~
svn的组织方式是在目录下有.svn的目录,里面有一个entries文件,记录了svn的地址
windows下的乌龟提供了relocation功能,mac下的svn工具暂时没有发现
不过没关系,这个事情很简单
比如你的svn服务器调整了,从192.168.1.1更换为 svn.aslibra.com 里
我们先确认一下是否存在
#你会得到类似内容:
./.svn/entries:svn://lhq@192.168.1.1/server
我们运行如下命令修改:
OK~
正常的POST表单:
上传文件:
Array
(
[upload] => Array
(
[name] => test.txt
[type] => text/plain
[tmp_name] => /tmp/phpKDS0MR
[error] => 0
[size] => 335
)
)
简单的php处理代码:
if(isset($_FILES['upload'])){
@copy( $_FILES['upload']['tmp_name'], '/tmp/upload_'.$_FILES['upload']['name'] );
@unlink( $_FILES['upload']['tmp_name'] );
}






