PHP多线程模块pthreads的使用

最近开发一个项目,需要在一个周期内执行许多个类似的任务。

印象中的PHP无法异步执行代码,所以计划使用PHP格式化MySQL的数据,然后提交给Bash Shell Script处理,毕竟在Bash Shell下,可以利用许多GNU程序的组合来实现我的需求,更重要的是在命令末尾加一个”&”符号,即可把任务丢到后台执行,立刻开始下一个任务,最后一切就绪后再提交结果给PHP收尾。

不得不说这是一个很糟糕的方案,虽然数据经过PHP初步格式化,但Shell Script仍然要使用一部分文字处理工具处理数据,其中可能因为某个字段数据比较特殊而出错,由于执行任务需要调用多个程序,效率低下,部分程序之间要使用管道,这些都增加了大量的服务器CPU以及物理内存资源的消耗,更烦的是要循环查询是否所有线程都已经结束工作……

为了让任务能高效率完成,于是寻找了一下有关PHP多线程的解决方案,发现原来PHP有一个提供多线程功能的模块——pthreads。

PHP官方对pthreads模块的介绍:

pthreads is an Object Orientated API that allows user-land multi-threading in PHP. It includes all the tools you need to create multi-threaded applications. PHP applications can create, read, write, execute and synchronize with Threads, Workers and Threaded objects.

介绍说pthreads模块提供了所有构建多线程PHP应用程序所需的工具,果然是世界上最好的语言。

根据PHP官方的文档,使用pthreads模块,需要开启线程安全功能,也就是编译PHP的时候,必须加上参数–enable-maintainer-zts。

此外,开启pthreads模块后,无法使用CGI模式运行PHP。

从PECL可以取得pthreads源码,继而进行编译安装,如果安装了php pear,还可以通过pecl命令安装:

下面说说pthreads模块的使用。

这是pthreads模块提供的Thread类的概要:

可以看到Thread是继承了Threaded类,因此我们要使用多线程功能时,直接需要创建一个继承于Thread的类即可:

其中run()方法与start()方法是关键。

在需要创建线程执行任务时,调用的是start()方法,而start()又会调用run()方法。

例:

上面的代码,会另起一个线程,输出一个随机数字。

如果我要在十秒后才输出这个随机数字,而且要输出100次,传统来说,至少需要1000秒才能完成输出任务,但使用线程,可以让所有输出几乎同时在十秒完成。

例:

上面的代码,使用了数组,每个数组元素都是一个myclass类的对象,这些对象会同时(虽然创建对象,开始线程等操作也需要时间,但时间非常短,可以忽略)创建一百个线程,这一百个线程同时开始十秒的延迟,十秒后同时输出一个数字:

Pthreads

由于使用的是线程模式,创建一个PHP进程即可处理所有线程,现在无需额外格式化数据,使用PHP的函数实现了所需的功能,相比之前不仅多Bash进程,还多执行各种杂七杂八程序的方案,任务执行效率大大提高。

Nginx下简单实现MediaWIKI的伪静态

最近要写一个说明文档,于是就用上了MediaWIKI。

这东西默认情况下,文章地址格式为http://domain/index.php?title=标题。

如果要改成使用http://domain/标题 的方式访问,rewrite规则明显有点繁琐,除非使用 if -e判断文件是否存在,否则正则表达式的.*会把一切东西,包括静态资源也匹配进去。

想了想,于是决定把文章的地址都变成子目录的形式:http://domain/wiki/标题,这样的话伪rewrite规则就变得简单多了,对/wiki进行匹配即可,仅需一行代码:

然后修改MediaWIKI的配置文件LocalSettings.php,修改与文章地址有关的变量wgArticlePath的值(没有的话就加进去):

这样文章的地址格式就会变为/wiki/标题了

最后重启Nginx,再次访问WIKI:

Media WIKI

可以看到,文章的地址格式已成功变为/wiki/标题,且无发现错误。

WHMCS(PHP程序)防止IP欺骗(伪造X-Forwarded-For)

前面发布了一篇文章,讲述了多重代理时防止伪造X-Forwarded-For的方法。

那只是针对使用代理服务器的情况。虽然没使用代理服务器时,很少会出现这个问题,但是也不排除有些傻逼PHP程序,如果X-Forwarded-For的内容不为空,就会主动拿来当做访客真实IP。使用CDN的话,还能获取访客的正确IP,但是没使用CDN的话……

whmcs-ip

这岂不是让那些不法分子有机可乘了吗?

大名鼎鼎的WHMCS就是其中之一!

其实如果要解决这个问题,在该PHP程序中,把类似这样的代码删掉就行:

 

但是,上面所说到的WHMCS,并非开源PHP程序,使用过ioncube加密,除非decode了,否则要修改源程序删代码,是不太可能的。

不过幸运的是,WHMCS有唯一一个没有加密且全局都使用的文件:configuration.php

既然WHMCS要把变量$HTTP_X_FORWARDED_FOR的内容拿来做访客真实IP,那么我们只需在configuration.php里面把$remote_addr(前一篇文章已解释过$remote_addr)赋值给$HTTP_X_FORWARDED_FOR。在configuration.php的<?php    ?>之间加入以下代码:

最后顺便提一下:本文仅仅是针对未使用反向代理(CDN)的网站防止伪造IP。如果你使用的是虚拟主机,且有CDN,无法修改服务器配置文件,那么只能用那“高风险”的方法去获取访客真实IP了。

 

博客,三周年

三年前的昨天,是我的博客诞生之日。

如果没看到右边栏的倒计时已经变成“在XXXXX之前”了,我都没发现三周年已过……

博客如何诞生,谈了两年了,不想再说……

这一年里面,最最最最最感激的人,非飛天鼠莫属。在这可以估量的九个月中,他对我人生的影响,是无法估量的……

现实生活中,我比较内向,没什么朋友,除了和他聊天,就是和他聊天。不仅让我学会很多东西,同时还给我带来很多欢乐……

三言两语难说尽,此处省略大概一万字……

第二个要感谢的人,开玩笑。最让我印象深刻以及感动的是,新年期间,我没有向他提出任何的要求,更从来没有想过要别人给我东西,但是居然主动送了我一个QQ会员,这是前所未有的……

如果没有他特意留给我一个VPS,我也许至今都不会用Linux,不会搭建网站环境,更别谈卖虚拟主机了……

第三个要感谢的人,慕叶思晨

这家伙貌似很忙?经常用手机,都不好意思Q它。但是,我也得感谢他,他是个“媒人”,把我和飞天鼠牵到了一起……

I won’t forget you forever! Friendship will last forever!

 

 

一次有惊无险的数据恢复

昨晚逛自己博客的时候,发现单手摘JJ的头像变成“无头像”的那种了!

头像

查证了下,是缓存的问题,要解决?很简单,清除缓存就行了。结果由于一时粗心,误在博客的根目录执行了rm -rf *,然后Ctrl+F5。403!再次F5,403,F5,403,F5,403……

当时瞬间惊呆了!我干了啥?我在做梦吧!

不是做梦,没其他办法,唯一的希望就是数据恢复了!Linux上的数据恢复,我还没试过,不过,为了自己的博客,只能尽力而为了!

谷歌百度,尝试了debugfs,ext3grep。

debugfs,恢复的文件夹是一个文件……ext3grep,搞了一堆不知道啥,满屏幕的DDDDDDDDDDDDDDDDDDDDDDDDDDDDD……

ext3grep

 

看D看了半个多小时,结果啥都没……

 

正绝望时,找到了一个Extundelete,抱着希望,安装了!

安装好后,尝试着进行目录恢复:

执行后,看到我的网站文件几乎列都出来了!

Extundelete

 

然后进入保存被恢复文件的目录看了下:

success

可以看到,文件几乎全部回来了,不过对于我来说,最重要的是upload里面的图片!把wp-content/upload打包到本地,看了下,基本都在了!

最后,重装WordPress,把upload文件夹复制过去,安装好插件……

再次Ctrl+F5,熟悉的页面又回来了,没成功恢复的图片,就几张而已……

吃一堑长一智,为了避免类似的事情再次发生,从今天起,每天异地备份!