PHP の開発作業では、タイムアウト処理が使用されるシナリオが数多くあります。
1. 特定のバックエンド データ ソースが正常に取得されなかった場合。ページ全体の表示には影響しません
2. 1 つのページの処理パフォーマンスが低下して Web サーバーが他のページにアクセスできなくなることを防ぐために、いくつかのページ動作設定が設定されます。 🎜>3. 特定のアップロードまたは不確実な処理時間の場合、プロセス全体のすべてのタイムアウトを無制限に設定する必要があります。そうしないと、リンクの設定が不適切であると、原因不明の実行中断が発生します
4. 複数のバックエンド モジュール (MySQL、 Memcached、HTTP インターフェース) を防ぐため、単一インターフェースのパフォーマンスが低下し、フロント全体のデータ取得が遅くなり、ページを開く速度に影響を及ぼし、雪崩を引き起こします。
5. 。 。タイムアウトが必要な場面は多々あります
こういった箇所でタイムアウトの設定を考慮する必要がありますが、PHPにおけるタイムアウトはいくつかのカテゴリーに分かれており、それぞれの処理方法や方針が異なります。よく使われるものを「PHP タイムアウト処理のまとめ」にまとめました。
[Web サーバーのタイムアウト処理]
[Apache]
通常、パフォーマンスが高い場合、デフォルトのタイムアウト設定はすべて 30 秒ですが、ファイルのアップロードやネットワーク速度が非常に遅い場合、タイムアウト操作がトリガーされる可能性があります。
現在、apachefastcgiphp-fpm モードには 3 つのタイムアウト設定があります:
fastcgi タイムアウト設定:
次のように httpd.conf の fastcgi 接続構成を変更します:
コードをコピー コードは次のとおりです:
FastCgiExternalServer/home/forum/apache/apache_php/cgi-bin /php-cgi-socket/home/forum/php5/etc/php-fpm.sock
ScriptAlias/fcgi-bin/"/home/forum/apache/apache_php/cgi-bin/"
AddHandlerphp-fastcgi .php
Actionphp- fastcgi/fcgi-bin/php-cgi
AddTypeapplication/x-httpd-php.php
コードをコピーします コードは次のとおりです:
FastCgiExternalServer/home/forum/apache/apache_php/cgi-bin/ php-cgi-socket/home/forum/php5/etc/php-fpm.sock-idle -timeout100
ScriptAlias/fcgi-bin/"/home/forum/apache/apache_php/cgi-bin/"
AddHandlerphp-fastcgi.php
Actionphp-fastcgi/fcgi-bin/php-cgi
AddTypeapplication/x-httpd-php.php
コードをコピー コードは次のとおりです。
IdleTimeout アイドル時間制限
ProcessLifeTime プロセスの最長のライフ サイクル、期限切れ その後、無条件に強制終了
MaxProcessCount プロセスの最大数
DefaultMinClassProcessCount 最小各プログラムによって開始されるプロセスの数
DefaultMaxClassProcessCount 各プログラムによって開始されるプロセスの最大数
IPCConnectTimeout プログラム応答タイムアウト
IPCCommTimeout およびプログラム通信の最大時間 上記のエラーは、この値の設定が小さすぎることが原因で発生する可能性があります。
MaxRequestsPerProcess は、各プロセスが完了できる最大プロセス数です。
コードをコピー コードは次のとおりです:
#各キープアライブの最大リクエスト数、デフォルト値は 16 です。
server.max-keep-alive-requests=100
#キープアライブの最大待機時間、単位は秒、デフォルト値は 5
server.max-keep-alive-idle=1200
#lighttpd の作業サブプロセスの数、デフォルト値は 0、単一プロセス操作
server.max-worker=2
#ユーザーがリクエストを送信する際の最大一時停止時間 (秒単位) を制限します。
#ユーザーがリクエストの送信プロセス中に一時停止しすぎる場合 (リクエストは無効になります)。完了)、lighttpd は積極的に切断します
#デフォルト値は 60 (秒) です
server.max-read-idle=1200
#ユーザーが応答を受信するときの最大中間停止時間 (秒単位) を制限します。 ),
#応答を受信している間 (完了していない) にユーザーが長時間停止した場合、lighttpd は積極的に切断します
# デフォルト値は 360 (秒) です
server.max -write-idle=12000
#クライアント要求の読み取りのタイムアウト制限。単位は秒で、制限がないことを示すには 0 に設定されます。
#設定が max-read-idle より小さい場合、read-timeout が有効になります。
server. read-timeout=0
#クライアントに応答ページを書き込むためのタイムアウト制限 (秒単位)。制限なしを示すには 0 に設定します
#設定が max-write-idle 未満の場合、write-timeout
server.write-timeout=0
#mod_proxy_core を使用する場合のバックエンドとの対話時間の上限です。
server.max-connection- idle=1200
コードをコピー コードは次のとおりです:
http{
#Fastcgi: (バックエンド fastcgi に有効、fastcgi はプロキシ モードに属しません)
fastcgi_connect_timeout5;#Connection timeout
fastcgi_send_timeout10; #書き込みタイムアウト
fastcgi_read_timeout10;#読み取りタイムアウト
#プロキシ: (プロキシ/アップストリームに有効)
proxy_connect_timeout15s;#接続タイムアウト
proxy_read_timeout24s;#読み取りタイムアウト
proxy_send_timeout 10代; # 書き込みタイムアウト
}
コードをコピー コードは次のとおりです:
//...
ApacheMaxClients ディレクティブと同等の数を設定します。オリジナルのphp.fcgiの環境
任意の pm_style で使用されます。
#php-cgi プロセス数
その後ワーカープロセスが終了するまでのタイムアウト (秒)
'max_execution_time' オプションがスクリプトの実行を停止しない場合に使用する必要がありますなぜか
「0s」は「オフ」を意味します
#php-fpm リクエストの実行タイムアウト、0s はタイムアウトしないことを意味します。それ以外の場合はタイムアウトの秒数として Ns を設定します
単一のリクエストを処理するためのタイムアウト (秒)
'0s' はオフを意味します'
注:
php.ini には、PHP スクリプトの最大実行時間を設定できるパラメーター max_execution_time がありますが、php-cgi (php-fpm) では、このパラメーターは有効になりません。 PHP スクリプトの最大実行を実際に制御できる場合:
つまり、mod_php5.so モードを使用して max_execution_time を実行すると、有効になりますが、php の場合、-fpm モードで実行している場合は有効になりません。
詳細情報:
http://blog.s135.com/file_get_contents/
[ PHP ]
設定: php.ini
オプション:
max_execution_time=30
またはコードで設定します:
ini_set("max_execution_time",30);
set_time_limit(30);
注:
を 0 に設定すると、タイムアウトになることはありません。ただし、phpのsafe_modeがオンになっている場合、これらの設定は有効になりません。
効果は同じですが、php-fpm で request_terminate_timeout が設定されている場合、特定のコンテンツは php-fpm 部分を参照する必要があります。max_execution_time は有効になりません。
[バックエンドとインターフェースのアクセスタイムアウト]
[HTTP アクセス]
一般に、HTTP にはさまざまな方法でアクセスします。主に、curl、socket、file_get_contents() などのメソッドです。
相手のサーバーが応答しない場合、サーバー全体が簡単に停止してしまうため、http にアクセスする際のタイムアウトの問題も考慮する必要があります。
[CURL アクセス HTTP]
CURL は、HTTP プロトコル インターフェイスにアクセスするために一般的に使用される信頼性の高いライブラリ ライブラリであり、高いパフォーマンスといくつかの同時実行サポート機能を備えています。
CURL:
curl_setopt($ch,opt) は、主に以下を含むいくつかのタイムアウト設定を設定できます:
*(重要) CURLOPT_TIMEOUT は、cURL が実行できる最大秒数を設定します。
*(重要) CURLOPT_TIMEOUT_MS は、cURL が実行できる最大ミリ秒数を設定します。 (cURL7.16.2 で追加。PHP5.2.3 から利用可能。)
接続を開始するまでに CURLOPT_CONNECTTIMEOUT が待機する時間。0 に設定すると、無期限に待機します。
CURLOPT_CONNECTTIMEOUT_MS 接続試行を待機する時間 (ミリ秒単位)。 0 に設定すると、無限に待機します。 cURL7.16.2で追加されました。 PHP5.2.3から利用可能です。
CURLOPT_DNS_CACHE_TIMEOUT は、DNS 情報をメモリに保存する時間を設定します。デフォルトは 120 秒です。
curl の通常の第 2 レベルのタイムアウト:
$ch=curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt ($ch,CURLOPT_TIMEOUT,60);// 秒数を設定するだけです
curl_setopt($ch,CURLOPT_HTTPHEADER,$headers);
curl_setopt($ch,CURLOPT_USERAGENT,$define_vars['HTTP_USER_AGENT) ' ]);
curl の通常の第 2 レベルのタイムアウトを使用します:
curl_setopt($ch,CURLOPT_TIMEOUT,60);
curl がミリ秒のタイムアウトを必要とする場合は、次を追加する必要があります:
curl_easy_setopt(curl,CURLOPT_NOSIGNAL) ,1L) ;
または:
curl_setopt($ch,CURLOPT_NOSIGNAL,true); ミリ秒レベルのタイムアウト設定をサポートできます
curl のミリ秒レベルのタイムアウトの例:
コードをコピー コードは次のとおりです:
if(!isset($_GET['foo'])){
//クライアント
$ch=curl_init('http://example.com/');
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
curl_setopt($ch,CURLOPT_NOSIGNAL,1); ;//ミリ秒に注意してください。タイムアウトは設定する必要があります。
curl_setopt($ch,CURLOPT_TIMEOUT_MS,200); //cURL7.16.2 で追加されたミリ秒単位のタイムアウト。 PHP5.2.3 以降で利用可能
$data=curl_exec($ch);
$curl_error=curl_error($ch); ;
if($curl_errno>0){
echo "cURLError($curl_errno):$curl_errorn";
}else{
echo "Datareceived:$datan"; >}else{
//サーバー
sleep(10);
echo "完了"
}
?>
その他のヒント:
1. エクスペリエンスの概要によると、cURL バージョン >= libcurl/7.21.0 バージョンでは、ミリ秒のタイムアウトが確実に有効になることを覚えておいてください。
$tmCurrent=gettimeofday (); $intUSGone=($tmCurrent['sec']-$tmStart['sec'])*1000000 ($tmCurrent['usec']-$tmStart[' usec']);
if($intUSGone>$this->intReadTimeoutUS){returnfalse;
}
または、組み込みのストリーム処理関数 stream_set_timeout( ) と stream_get_meta_data() を使用して処理します:
//タイムアウト秒
$timeout=5;
$fp=fsockopen("example.com",80,$errno,$errstr,$timeout);
if($fp){
fwrite($fp,"GET/HTTP/1.0rn");
fwrite($fp,"Host:example.comrn"); fp,"Connection:Closernrn");
stream_set_blocking($fp,true);//重要、非ブロッキング モードに設定します
stream_set_timeout($fp,$timeout);//タイムアウトを設定します
$ info =stream_get_meta_data($fp);
while((!feof($fp))&&(!$info['timed_out'])){
$data.=fgets($fp,4096); 🎜 >$info=stream_get_meta_data($fp);
ob_flush;
flush();
if($info['timed_out']){
echo "ConnectionTimedOut!";
}else{
echo$data;
}
}
file_get_contents タイムアウト:
コードは次のとおりです。 $timeout=array(
'http'=>array(
'timeout'=> 5//設定 秒単位のタイムアウト
)
)
$ctx=stream_context_create($timeout);
$text=file_get_contents("http://example.com/",0, $ ctx);
?>
fopen タイムアウト:
コードは次のとおりです。 > $timeout=array(
'http'=>array('timeout'=>5//タイムアウトを秒単位で設定します
)
);
$ctx=stream_context_create($timeout);
if($fp=fopen("http://example.com/","r",false,$ctx)){
while($c=fread($fp,8192)){
echo$c;
}
?>
[MySQL]
php の mysql クライアントには、mysqli にも mysql にもタイムアウトを設定するオプションがありませんが、libmysql にはタイムアウト オプションが用意されていますが、それを非表示にします。 php 以上です。
PHP でこの操作を使用するには、いくつかの MySQL 操作定数を自分で定義する必要があります。
MYSQL_OPT_READ_TIMEOUT=11;
$mysqli=mysqli_init(); >$mysqli->options(MYSQL_OPT_READ_TIMEOUT,3 );
$mysqli->options(MYSQL_OPT_WRITE_TIMEOUT,1)
//データベースに接続します
$mysqli->real_connect("localhost") ,"root","root","test") ;
if(mysqli_connect_errno()){
printf("Connectfailed:%s/n",mysqli_connect_error());
}
//クエリを実行 sleep1 秒 タイムアウトなし
printf("Hostinformation:%s/n",$mysqli->host_info)
if(!($res=$mysqli-) >query('selectsleep(1)'))) {
echo "query1error:".$mysqli->error."/n";
}else{
echo "Query1:querysuccess/ n";
}
//スリープのクエリを 9 秒間実行するとタイムアウトになります
if(!($res=$mysqli->query('selectsleep(9)'))){
echo "query2error:".$mysqli->error."/ n";
}else{
echo "Query2:querysuccess/n";
$mysqli->close ();
echo "closemysqlconnection/n";
?>
http://blog.csdn.net/heiyeshuwu/article/details/ 5869813
【Memcached】
[PHP 拡張機能]
php_memcache クライアント:
接続タイムアウト: boolMemcache::connect(string$host[,int$port[,int$timeout ]])
明示的なタイムアウト設定パラメーターの取得または設定中に何も起こりません。
libmemcached クライアント: PHP インターフェイスには明らかなタイムアウト パラメーターがありません。
注意: したがって、PHP で Memcached にアクセスする場合は、いくつかの操作を自分でハックするか、オンライン パッチを参照する必要があるため、多くの問題が発生します。
[C&C アクセス Memcached]
クライアント: libmemcached client
//接続タイムアウトの作成 (Memcached への接続)
memcached_st*MemCacheProxy::_create_handle()
{
memcached_st*mmc=NULL;
if( _mpool!=NULL){//getfrompool
mmc=memcached_pool_pop(_mpool,false,&prc);
if(mmc==NULL){
__LOG_WARNING__("MemCacheProxy","gethandlefrompoolerror[%d]") ,(int)prc);
returnmmc;
}
memcached_st*handle=memcached_create(NULL);
__LOG_WARNING__(" ","create_handleerror");
returnNULL;
}
//接続/読み取りタイムアウトを設定します
memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_HASH,MEMCACHED_HASH_DEFAULT);
memcached_behavior_set(handle,MEMCACHED_BEHAVI) OR_NO_B ロック、_noblock) ;//タイムアウト設定を有効にするために、パラメータ MEMCACHED_BEHAVIOR_NO_BLOCK が 1 に設定されています。タイムアウトが設定されていない場合、タイムアウトは有効になりません。重要なときに雪崩が発生しやすくなります。
memcached_behavior_set(handle) ,MEMCACHED_BEHAVIOR_CONNECT_TIMEOUT,_connect_timeout);//接続タイムアウト
memcached_behavior_set(handle ,MEMCACHED_BEHAVIOR_RCV_TIMEOUT,_read_timeout);//読み取りタイムアウト
memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_SND _TIMEOUT, _send_timeout);//書き込みタイムアウト
memcached_behavior_set(handle, MEMCACHED_BEHAVIOR_POLL_TIMEOUT,_poll_timeout );
//一貫したハッシュを設定します
/ /memcached_behavior_set_distribution(handle,MEMCACHED_DISTRIBUTION_CONSISTENT);
memcached_behavior_set(handle,MEMCACHED_BEHAVIOR_DISTRIBUTION,MEMC) ACHED_DISTRIBUTION_CONSISTENT);
memcached_returnrc;
for(uinti=0) ;i<_server_count>rc=memcached_server_add(handle, _ips[i],_ports[i]);
if(MEMCACHED_SUCCESS!=rc){
__LOG_WARNING__("MemCacheProxy"," addserver[%s:%d] が失敗しました。",_ips[i],_ports [i]);
}
}
_mpool=memcached_pool_create(handle,_min_connect,_max_connect);
if( _mpool==NULL){
__LOG_WARNING__("MemCacheProxy","create_poolerror" );
returnNULL;
mmc=memcached_pool_pop(_mpool,false,&prc); =NULL){
__LOG_WARNING__("MyMemCacheProxy","gethandlefrompoolerror[%d ]",(int)prc);
}
//__LOG_DEBUG__("MemCacheProxy","gethandle[%p]", handle);
returnmmc;
}
//設定 キーがタイムアウトする (データを memcached に設定する)
boolMemCacheProxy::_add(memcached_st*handle, unsignedint*key, constchar*value,intlen) 、unsignedinttimeout)
{
memcached_returnrc;
chartmp[1024] ;
snprintf(tmp,sizeof(tmp),"%u#%u",key[0],key[1]) ;
//タイムアウト値があります
rc=memcached_set(handle, tmp,strlen(tmp),(char*)value,len,timeout,0);
if(MEMCACHED_SUCCESS!=rc) {
returnfalse;
}
returntrue;
}
//Memcache 読み取りデータ タイムアウト (未設定)
libmemcahed ソース コードのインターフェイス定義:
LIBMEMCACHED_APIchar*memcached_get(memcached_st*ptr,constchar*key,size_tkey_length,size_t*value_length,uint32_t *flags,memcached_return_t*error);
LIBMEMCACHED_APImemcached_return_tmemcached_mget(memcached_st*ptr,constchar*const*keys,const)サイズ_t*キーの長さ、サイズ_tキーの数);
<$host="127.0.0.1"; $port="80"; =15;//timeoutin秒
$socket=socket_create(AF_INET,SOCK_STREAM,SOL_TCP)ordie("Unabletocreatesocketn")
socket_set_nonblock($socket) //必ずブロッキング モードに設定してください
ordie("Unabletosetnonblockonsocketn");
$time=time();
//ループするたびに対応する値を減算します
while(!@socket_connect($socket,$host,$port) )//接続がない場合は無限ループが続きます
{
$err=socket_last_error($socket)
if($err==115||$err==114)
{
if((time()- $time)>=$timeout)// タイムアウトしたかどうかを確認する必要があるたびに
{
socket_close($socket)
die("Connectiontimedout.n");
sleep(1);
}
die(socket_strerror($err)."n");
socket_set_block($this->socket)/ / ブロックモードを復元
ordie("Unabletosetblockonsocketn")
;
2. アップグレード: PHP 独自の非同期 IO を使用して実装します (ミリ秒タイムアウト)
説明:
非同期 IO: 非同期 IO の概念は同期 IO の反対です。非同期プロシージャ呼び出しが発行された場合、呼び出し元は結果をすぐには取得しません。実際に通話を処理するコンポーネントは、通話が完了するとステータス、通知、コールバックを通じて発信者に通知します。非同期 IO は、ビットを小さなグループ (8 ビット、1 文字、またはそれ以上) に転送します。送信者はいつでもこれらのビットのグループを送信できますが、受信者はそれらがいつ到着するかわかりません。
多重化: 多重化モデルは複数の IO 操作を検出し、操作できるように操作可能なコレクションを返します。これにより、ブロッキング IO が各 IO をいつでも処理できないという判断と、システム リソースの非ブロッキング占有が回避されます。
socket_select() を使用してタイムアウトを実装します。
socket_select(...,floor($timeout),ceil($timeout*1000000));
select の機能: タイムアウトをマイクロ秒レベルに設定できます。 !
socket_select() のタイムアウト コードを使用します (理解するには、非同期 IO プログラミングの知識が必要です)
コードをコピーします コードは次のとおりです
プログラミング呼び出しクラスプログラミング#
$server=newServer;
for(;;){ <🎜; >foreach($select->gt ;can_read(0)as$socket){
if($socket==$client->socket){
//NewClientSocket
$select->add( socket_accept($client->socket));
}
else{
//$socket に何かあります
}
}
? >非同期多重化IOとタイムアウト接続処理クラスのプログラミング
classselect{
var$sockets;
functionselect($sockets){
$this->sockets=array ();
foreach($socketsas$socket){
$this->add($socket);
}
}
functionadd($add_socket){
array_push( $this-> ;sockets,$add_socket);
}
functionremove($remove_socket){
$sockets=array()
foreach($this->socketsas$socket); 🎜>if( $remove_socket!=$socket)
$sockets[]=$socket;
}
$this->sockets=$socket;
functioncan_read($timeout; ){
$read=$this->sockets;
socket_select($read,$write=NULL,$excel=NULL,$timeout);
return$read
; >functioncan_write($ timeout){
$write=$this->sockets;
socket_select($read=NULL,$excel,$timeout);
return$write; 🎜>}
}
?>
[C&C でのタイムアウト実装]
通常、LinuxC/C では、alarm() を使用できます。タイマー メソッドを設定して第 2 レベルのタイムアウトを実現するか、select()、poll()、epoll() などの非同期多重 IO を使用してミリ秒レベルのタイムアウトを実現します。これを実現するために、セカンダリのカプセル化された非同期 IO ライブラリ (libevent、libev) を使用することもできます。
1. アラーム内のシグナルを使用してタイムアウト (第 2 レベルのタイムアウト) を実装します。
説明: Linux カーネルの接続タイムアウトは、通常 75 秒です。接続から早く戻るために、10 秒などの短い時間を設定できます。ここでは、信号処理メカニズムを使用し、アラームを呼び出し、タイムアウト後に SIGALRM 信号を生成します (select を使用して実装することもできます)
接続設定タイムアウトのコード例を実装するには、alarym 秒を使用します:
staticvoidconnect_alarm(intsigno) { debug_printf("SignalHandler") ; return; }
//アラームタイムアウト接続実装staticvoidconn_alarm()
{
Sigfunc*sigfunc;//既存の信号処理関数
sigfunc=signal(SIGALRM) ,connect_alarm);// 信号処理関数 connect_alarm を作成し、(存在する場合) 既存の信号処理関数を保存します
inttimeout=5
// 目覚まし時計を設定します
if(alarm(timeout)!= 0){
// ...目覚まし時計が設定され、処理されました
}
//接続操作を実行します
if(connect(m_Socket,(structsockaddr*)&addr,sizeof(addr) )<0){
if(errno ==EINTR){// エラー番号が EINTR に設定されている場合は、タイムアウトが中断されたことを意味します。
debug_printf("Timeout"); >