驚異的な問題.
5571 ワード
定義#テイギ#驚きのグループ問題とは、マルチスレッド(またはマルチプロセス)シーンで、あるリソースが利用可能になるのを待っている複数のスレッドがあり、このリソースが利用可能になると、このリソースを待っているすべてのスレッドが呼び出されますが、リソースは1つしかありません.他のスレッドは に失敗します.の驚きのグループ問題は、不要なスレッドの起動を招き、実際には1つのスレッドだけがこのリソースを取得できるので、理想的には1つのスレッドだけを起動すればよい.一方、複数のスレッドを起動することは、不要なスレッドスケジューリングをもたらし、システムオーバーヘッド をもたらす.
古典的なaccept驚群問題 Linuxの初期バージョンではaccept関数に驚異的な問題がありました は、親プロセスがsocket、bind、listenを介してリスニング記述子を作成し、forkが複数のサブプロセスを生成し、すべてのプロセスがacceptというリスニング記述子を有し、新しい接続が来ないときにブロックに陥るシーンを考慮する.新しい接続が来るたびに、acceptにブロックされているすべてのプロセスが起動し、そのうちの1つのプロセスacceptが正常に戻り、他のプロセスはEAGAINエラー を返します.上のシーンは古典的なaccept驚群問題 です.現在のLinuxバージョンでは、このようなaccept驚きの問題は存在しません.つまり、複数のプロセスがacceptにブロックされている場合、新しい接続の到来は1つのプロセスを呼び覚ますだけです.しかし、これは驚くべき問題が 解決されたという意味ではない.
epoll驚きの群れ上記のようにacceptシステム呼び出しには驚きの問題は存在しないが、epollには驚きの問題も存在する. 親プロセスがepoll_を介してリスニング記述子を作成するシーンを考慮ctlはこのリスニングソケットをepollに追加し、forkは複数のサブプロセスを出し、各サブプロセスはepoll_にある.waitでは、リスニング記述子を待つ読み取り可能なイベント(新しい接続が到来する)がブロックされ、新しい接続が到来すると、すべてのサブプロセスが起動します. Linuxカーネルはaccept驚き現象を処理したが、epoll驚き現象を処理しなかったのは、acceptが1つのプロセスでしか処理できないためかもしれない.epollが傍受する記述子は、ファイルが複数のプロセスによって読み書きされるなど、複数のプロセスによって処理される可能性があります.したがって、カーネルはepollの驚異的な群現象 を処理する必要があるか否かを判断できない.
Nginxによる驚きのグループ問題の処理 Nginxのポリシーは、同じ時点で唯一のworkerサブプロセスがWebポートを傍受することしかできないことを規定している.このとき、新しい接続イベントは1つのプロセスを呼び覚ますことしかできず、驚くべき現象は ではない. accept_を具体的に使用mutexロック方式 を実現上記のコードから、任意の時点でaccept_を取得できるプロセスは1つしかないことがわかります.mutexロック、accept_を取得mutexロックのプロセスはwebポートを傍受することができる.accept_を取得できませんでしたmutexロックのプロセスは、リスニングソケットをepollから 削除します.
古典的なaccept驚群問題
epoll驚きの群れ
Nginxによる驚きのグループ問題の処理
ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t* cycle)
{
/* accept_mutex , , 1; 0, */
if(ngx_shmtx_trylock(&ngx_accept_mutex)) {
/* accept_mutex , */
if(ngx_accept_mutex_held
&& ngx_accept_events == 0
&& !(ngx_event_flags & NGX_USE_RTSIG_EVENT)) {
return NGX_OK;
}
/* epoll */
if(ngx_enable_accept_events(cycle) == NGX_ERROR) {
/* */
ngx_shmtx_unlock(&ngx_accept_mutex);
return NGX_ERROR;
}
/* , */
ngx_accept_events = 0;
ngx_accept_mutex_held = 1;
return NGX_OK;
}
if(ngx_accept_mutex_held) {
/* epoll */
if(ngx_disable_accept_events(cycle) == NGX_ERROR) {
return NGX_ERROR;
}
ngx_accept_mutex_held = 0;
}
return NGX_OK;
}