mysql_fetch_array()函数参数
mysql_fetch_array() 函数从结果集中取得一行作为关联数组,或数字数组,或二者兼有
返回根据从结果集取得的行生成的数组,如果没有更多行则返回 false。
mysql_fetch_array(data,array_type)
array_type如下
MYSQL_ASSOC - 关联数组
MYSQL_NUM - 数字数组
MYSQL_BOTH - 默认。同时产生关联和数字数组
mysql_fetch_rows()函数参数
mysql_fetch_row() 函数从结果集中取得一行作为数字数组。
mysql_fetch_row(data)
从上面来看它们都是使用的数据指针。该数据指针是 mysql_query() 函数产生的结果了,但后面有一个参数是不一样的,mysql_fetch_array()有array_type参数而mysql_fetch_rows()没有。
那么用法有什么区别,下面看个例子
mysql_fetch_array()和mysql_fetch_rows()都能获取数据库的字段数据,具体区别可参照以www.111cn.net整理的实例:
mysql_fetch_array()函数例子
<?php
$sql=”select * from user “;
$query=mysql_query($sql);
$result=mysql_fetch_array($query);
echo $result[name];
echo $resutlt[password];
?>
mysql_fetch_rows()函数例子
<?php
$sql=”select * from user “;
$query=mysql_query($sql);
$result=mysql_fetch_rows($query);
echo $result[1];
echo $resutlt[2];
?>
总结,mysql_fetch_array()是数组并且可以关联数组,而mysql_fetch_rows是对象不能关联数组,区别就在这里了
如果我们配置不对可能导致大文件无法上传了,像nginx配置不当会导致nginx 502 bad 504 time-out问题了,下面我们一起来看问题的解决办法公共的环境前段
<form enctype="multipart/form-data" action="upload.php" method="POST">
<!-- MAX_FILE_SIZE must precede the file input field -->
<input type="hidden" name="MAX_FILE_SIZE" value="100000000" />
<!-- Name of input element determines name in $_FILES array -->
Send this file: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>
nginx+linux环境注意事项
php环境上传大文件需要注意的事项:
/usr/local/php/etc/php-fpm.conf.default
request_terminate_timeout = 0 //这个是fastcgi的执行时间,默认不限制的
client_max_body_size 256m;
fastcgi_buffer_size 256k;
fastcgi_buffers 16 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_connect_timeout 3000;
fastcgi_send_timeout 3000;
fastcgi_read_timeout 3000;
另外PHP也需要配置:
memory_limit 512M
max_execution_time 0
post_max_size 256M
upload_max_filesize 256M
apache+windows环境下注意事项
配置php.ini文件 (以上传500M以下大小的文件为例)
查找以下选项并修改->
file_uploads = On ;打开文件上传选项
upload_max_filesize = 500M ;上传文件上限
如果要上传比较大的文件,仅仅以上两条还不够,必须把服务器缓存上限调大,把脚本最大执行时间变长
post_max_size = 500M ;post上限
max_execution_time = 1800 ; Maximum execution time of each script, in seconds脚本最大执行时间
max_input_time = 1800 ; Maximum amount of time each script may spend parsing request data
memory_limit = 128M ; Maximum amount of memory a script may consume (128MB)内存上限
浏览器下PHP执行正常,在CMD报扩展加载错误,在dos的cmd模式下执行php,已加载的模块都不能使用。
解决过程方法:
1.在命令行执行php时,使用php --ini命令先行查看php加载的配置文件的地址
2.在PHP用浏览器形式访问PHP文件:
输出PHPinfo看看 加载的php.ini文件是否一致。
方法:
在命令行执行php时,使用php -c "php.ini文件所在文件夹地址"来运行php文件
使用php curl的方式调用对方提供的接口,收到了如下错误提示
HTTP Status 415
The server refused this request because the request entity is in a format not supported by the requested resource for the requested method.
Curl 的代码片段如下:
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_NOBODY, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_TIMEOUT, 120);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postData));
$data = curl_exec($ch);
curl_close($ch);
多次检查curl设置已经接口的说明没有发现问题。对方的服务器使用的是Tomcat 7, 一度怀疑是对方web配置有误,后来仔细研究文档,其中提到Response是jason格式文档,而上述curl中没有指定Request Header 信息, 所以尝试加入一个header, 结果问题解决。 代码如下:
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/json; charset=utf-8"));
一. 场景分析
业务服务压力比较大,想把一些占用资源的功能异步到远程处理,比如记录业务日志,文件加密,文件分发到其他文件服务器节点上,检查文件服务器是否已同步,对用户上传的图片进行剪裁生成多份缩略图,视频转换,静态内容生成,清除缓存等等,这些请求耗时长,占用系统资源大,影响业务正常访问。这些问题会经常遇到的,如果这些任务都在用户请求过程中完成,服务器撑不撑得住暂不考虑,单凭用户体验角度考虑来说,那是难以忍受的。
二. 解决之道
对于这种需求,我们可以通过分布式计算,对任务进行拆分,转移到多台服务器上进行异步或同步处理。分布式消息队列有多种实现方式如rabbitmq、gearman等。 在这里主要说gearman—分布式处理系统。gearman由三部分组成:Job server,worker server,client server。 任务服务器job server运行这gearmand进程,来负责处理应用的远程调用请求,并且维护计算任务;工作服务器worker server负责向job server注册函数等待领取任务并执行实际的计算,然后将结果返回给job server;客户端client server提供gearman client API给应用程序调用,API支持多种语言如C、php、perl、python、mysql udf、java、ruby、go等等,主要是向job server添加任务,
流程图如下:
客户端client server向gearman添加任务时,有三种模式:
1. 同步顺序处理 相当于消息队列,先进先出。
2. 同步并行处理 这种模式会阻塞后面的运行,将互不依赖的任务并行处理,大大缩短整体处理时间。
3. 异步后台处理 将耗时任务交给后台处理,不阻塞当前进程。
三. 应用实例
需要安装的模块有Mail::SendEasy、Gearman::Worker、Gearman::Client、JSON。
# perl -MCPAN -e 'install Mail::SendEasy Gearman::Worker Gearman::Client JSON'
或通过cpanm来安装
在使用异步处理之前,当我们要发送邮件时,会直接这么写,代码如下:
代码如下 | 复制代码 |
use strict; use Mail::SendEasy ; my $mail = new Mail::SendEasy( smtp => 'smtp.ttlsa.com' , user => 'service@ttlsa.com' , pass => 'QQ_qun:39514058', ); my $status = $mail->send( from => 'service@ttlsa.com' , from_title => $mail_title , to => $mail_to , subject => $mail_subject , msg => $mail_msg , html => "<b>$mail_msg</b>" , ); if (!$status) { print $mail->error ;} |
这存在一个问题, 会长期阻塞在send函数,而无限制等待下去, 直到超时,很可能会拖垮服务器的。我们可以使用gearman,来改变这种发送邮件的方式。第一步,创建一个worker实例SENDMAIL,并向job server注册,等待接收任务并执行发送邮件的操作。第二步,客户端只需要将发送邮件的任务丢给job server便退出,没你什么事了。上代码:
代码如下 | 复制代码 |
# vim work_SENDMAIL.pl use strict; use Mail::SendEasy ; use Gearman::Worker; use JSON; use Data::Dumper; my $gearman_server='127.0.0.1:4730'; my $worker=new Gearman::Worker; $worker->job_servers($gearman_server); $worker->register_function(SENDMAIL=>\&sendmail); $worker->work while 1; sub sendmail{ my $job=shift; my $param=$job->arg; my $json = JSON->new->allow_nonref; my $hash_ref=$json->decode($param); my $addr=$hash_ref->{'email'}; my $subject=$hash_ref->{'subject'}; my $msg=$hash_ref->{'msg'}; my $mail = new Mail::SendEasy( smtp => 'smtp.ttlsa.com' , user => 'service@ttlsa.com' , pass => 'QQ_qun:39514058', ); my $status = $mail->send( from => 'service@ttlsa.com' , from_title => $subject , to => $addr , subject => $subject , msg => $msg , html => "<b>$msg</b>" , ); if (!$status) { print $mail->error ;} } # vim gearman_client.pl use strict; use Gearman::Client; use JSON; my $gearman_server="127.0.0.1:4730"; my $worker='SENDMAIL'; my $data={}; $data->{'subject'} = "www.ttlsa.com --- Operation & Maintenance of Time To Live"; $data->{'msg'} = "Date: gettime() $data->{'email'} = '710117291@qq.com'; my $json = JSON->new->allow_nonref; my $param=$json->encode($data); gearman_add_job($gearman_server,$worker,$param,2); sub gearman_add_job { my $server=shift; my $function_name=shift; my $function_param=shift; my $level=shift or 1; my $gearman_client = Gearman::Client->new; $gearman_client->job_servers($server); if($level == 1){ my $result = $gearman_client->do_task($function_name,\$function_param,{}); } elsif($level == 2){ my $result = $gearman_client->dispatch_background($function_name, \$function_param,{}); } } sub gettime { my @time=(localtime)[5,4,3,2,1,0]; $time[0]+=1900; $time[1]+=1; return sprintf("%04u-%02u-%02u %02u:%02u:%02u",@time); } |
完成上面的改造不要认为解决了发送邮件会长期阻塞在send函数,而无限制等待下去的问题了。这其实只是解决了一部分,还有一个问题需要考虑进去,既然采用了异步方式,那么应用程序是不知道邮件是否发送成功的,因此需要记录任务执行的结果,可以将结果写入数据库,定期的对发送失败的邮件进行再次发送,或写个异常处理的worker,捕获发送邮件异常,进行多次尝试发送。
这种方案是我在捕获数据库备份过程中失败时,发邮件报警的应用。
通过这样的异步任务处理,可以很好的解决前面场景提到的问题,完全取决于如何应用gearman了。如有更好的应用可以相互交流。