淘宝技术专家
对socket_read的返回值做下判断。如果返回-1,则对errno多下判断。socket_last_error() 方法获取errno。
给你一段用C语言写的示例。
执行命令 sestatus
如果输出内容不是 disabled
执行命令 setenforce disabled
一般编程语言都会有作用域的概念。如果,变量已经不再作用域了,变量所占用的资源还不释放,那就太浪费内存空间了。除非必要,否则会也不会干费力不讨好的事情。
贴一段代码。
输出结果
0
不错啊
其实主要是为了容灾,把数据把多地保存多份。如果一个地方数据出现问题,尽量能做到无缝切换。
你看下你的代码。连接数据库的时候主机名是不是写的 localhost? 如果是 你改成 127.0.0.1 试试。
有过简单的了解,他和nodejsyou很多相同的特点。如
1、事件驱动,异步执行,非阻塞IO
2、单进程单线程
更多信息可以查看 ReactPHP,PHP版的Node.js
开始,把php_tclip.h中的全局变量声明部分修改为如下:
ZEND_BEGIN_MODULE_GLOBALS(tclip)
CascadeClassifier face_cascade;
char *face_config_path;
ZEND_END_MODULE_GLOBALS(tclip)
结果报如下错误:
error: ‘CascadeClassifier’ does not name a type
看来这个类没有在头文件中声明。那就另辟蹊径,改为其它方式。把代码改为
ZEND_BEGIN_MODULE_GLOBALS(tclip)
void *face_cascade;
char *face_config_path;
ZEND_END_MODULE_GLOBALS(tclip)
然后在tclip.c中进行了如下修改:
1.首先定义了一个全局变量。
static CascadeClassifier face_cascade;
2.修改PHP_MINIT_FUNCTION(tclip)。代码如下:
PHP_MINIT_FUNCTION(tclip)
{
/* If you have INI entries, uncomment these lines */
REGISTER_INI_ENTRIES();
string face_config_path = (TCLIP_G(face_config_path) == "" || TCLIP_G(face_config_path) == NULL)? "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml" :TCLIP_G(face_config_path);
if( !face_cascade.load( face_config_path ) ){
php_error_docref(NULL TSRMLS_CC, E_WARNING, "can not load classifier file!%s", face_config_path.c_str());
return FAILURE;
}
TCLIP_G(face_cascade) = &face_cascade;
return SUCCESS;
}
调用全局对象的方式如下:
((CascadeClassifier *)TCLIP_G(face_cascade))->detectMultiScale( img_gray, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30) );
注意,php扩展想线程安全,那就用相关宏来访问全局变量。如上面的TCLIP_G(face_cascade)。
参考资料 php扩展中如何定义线程安全的全局对象
闲话少说,直接上代码:
下面是我在config.m4中写的自动加载opencv相关so库和头文件的代码。
dnl # --with-tclip -> check with-path
SEARCH_PATH="/usr/lib/pkgconfig" # 定义pkgconfig文件,即扩展名pc文件存放路径
SEARCH_FOR="opencv.pc" # 要寻找的文件
if test -r $PHP_TCLIP/$SEARCH_FOR; then #
TCLIP_DIR=$PHP_TCLIP
else # search default path list
AC_MSG_CHECKING([for tclip files in default path])
for i in $SEARCH_PATH ; do
if test -r $i/$SEARCH_FOR; then
TCLIP_DIR=$i
AC_MSG_RESULT(found in $i)
fi
done
fi
dnl
if test -z "$TCLIP_DIR"; then
AC_MSG_RESULT([not found])
AC_MSG_ERROR([Please reinstall the tclip distribution])
fi
OPENCV_FLAGS="pkg-config opencv --libs --cflags opencv
"
for i in $OPENCV_FLAGS;do
if test ${i:0:2} = "-I" ;then
PHP_ADD_INCLUDE(${i:2})
elif test ${i:${#i}-3} = ".so" ;then
dir_name=`dirname $i`
file_name=${i/$dir_name/}
file_name=${file_name/\/lib/}
file_name=${file_name/.so/}
PHP_ADD_LIBRARY_WITH_PATH($file_name,$dir_name,TCLIP_SHARED_LIBADD)
fi
done
示例代码:
/*
function curl($urls = array(), $callback = '')
{
$response = array();
if (empty($urls)) {
return $response;
}
$chs = curl_multi_init();
$map = array();
foreach($urls as $url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_TIMEOUT, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_NOSIGNAL, true);
curl_multi_add_handle($chs, $ch);
$map[strval($ch)] = $url;
}
do{
if (($status = curl_multi_exec($chs, $active)) != CURLM_CALL_MULTI_PERFORM) {
if ($status != CURLM_OK) { break; } //如果没有准备就绪,就再次调用curl_multi_exec
while ($done = curl_multi_info_read($chs)) {
$info = curl_getinfo($done["handle"]);
$error = curl_error($done["handle"]);
$result = curl_multi_getcontent($done["handle"]);
$url = $map[strval($done["handle"])];
$rtn = compact('info', 'error', 'result', 'url');
if (trim($callback)) {
$callback($rtn);
}
$response[$url] = $rtn;
curl_multi_remove_handle($chs, $done['handle']);
curl_close($done['handle']);
//如果仍然有未处理完毕的句柄,那么就select
if ($active > 0) {
curl_multi_select($chs, 0.5); //此处会导致阻塞大概0.5秒。
}
}
}
}
while($active > 0); //还有句柄处理还在进行中
curl_multi_close($chs);
return $response;
}
//使用方法
function deal($data){
if ($data["error"] == '') {
echo $data["url"]." -- ".$data["info"]["http_code"]."\n";
} else {
echo $data["url"]." -- ".$data["error"]."\n";
}
}
$urls = array();
for ($i = 0; $i < 10; $i++) {
$urls[] = 'http://www.baidu.com/s?wd=etao_'.$i;
$urls[] = 'http://www.so.com/s?q=etao_'.$i;
$urls[] = 'http://www.soso.com/q?w=etao_'.$i;
}
curl($urls, "deal");
参考资料 php实现并发处理之curl篇
有很多中方式,这里说一种cas的方式。
其实这里并不是严格的CAS,而是使用了比较交换原子操作的思想。
生成思路如下:
每次生成全局id时,先从sequence表中获取当前的全局最大id。然后在获取的全局id上做加1操作。把加1后的值更新到数据库。更新时是关键。
如加1后的值为203,表名是users,数据表结构如下:
CREATE TABLE SEQUENCE
(
`name` varchar(30) NOT NULL COMMENT '分表的表名',
`gid` bigint(20) NOT NULL COMMENT '最大全局id',
PRIMARY KEY (`name`)
) ENGINE=InnoDB
那么更新语句是。
update sequence set gid = 203 where name = 'users' and gid < 203;
sql语句的 and gid < 203 是为了保证并发环境下gid的值只增不减。
如果update语句的影响记录条数为0说明,已经有其他进程提前生成了203这个值,并写入了数据库。需要重复以上步骤从新生成。
代码实现如下:
//$name 表名
function next_id_db($name){
//获取数据库全局sequence对象
$seq_dao = Wk_Sequence_Dao_Sequence::getInstance();
$threshold = 100; //最大尝试次数
for($i = 0; $i < $threshold; $i++){
$last_id = $seq_dao->get_seq_id($name);//从数据库获取全局id
$id = $last_id +1;
$ret = $seq_dao->set_seq_id($name, $id);
if($ret){
return $id;
break;
}
}
return false;
}
更多方式,可以查看 数据库分表后,并发环境下,生成全局id生成的几种方式
nginx的ngx_http_limit_req_module模块限制了百度蜘蛛的抓取频率。每分钟允许百度蜘蛛抓取200次,多余的抓取请求返回503。
nginx的配置:
limit_req_zone $anti_spider zone=anti_spider:60m rate=200r/m;
limit_req zone=anti_spider burst=5 nodelay;
if ($http_user_agent ~* "baiduspider") {
set $anti_spider $http_user_agent;
}
参数说明:
指令limit_req_zone 中的rate=200r/m 表示每分钟只能处理200个请求。
指令limit_req 中的burst=5 表示最大并发为5。即同一时间只能同时处理5个请求。
指令limit_req 中的 nodelay 表示当已经达到burst值时,再来新请求时,直接返回503
IF部分用于判断是否是百度蜘蛛的user agent。如果是,就对变量$anti_spider赋值。这样就做到了只对百度蜘蛛进行限制了。