Cやってみよう #6
前年の続き
だいぶ間が空いてしまった。
2016年、restartです。
続けるように。
mod_vhost_maxclients.c
のソースを見ていきましょう。
174 for (i = 0; i < vhost_maxclients_server_limit; ++i) { 175 for (j = 0; j < vhost_maxclients_thread_limit; ++j) { 176 worker_score *ws_record = ap_get_scoreboard_worker(i, j); 177 #ifdef __APACHE24__ 178 char *client_ip = r->connection->client_ip; 179 #else 180 char *client_ip = r->connection->remote_ip; 181 #endif
- 174行目は
vhost_maxclients_server_limit
まで繰り返しの処理が開始 - 175行目は
vhost_maxclients_thread_limit
まで繰り返しの処理が開始- 例えば両方のlimitの値が10の場合は、
10*10=100
回、繰り返すわけですね。
- 例えば両方のlimitの値が10の場合は、
- 176行目が肝のようだ。
ap_get_scoreboard_worker
この処理で、apacheが持つscoreboardから値を取って
*ws_record
に値を入れている。
http://apache.org/server-status
↑のserver-statusをimageしとけばいいのだろうか。 - 178,180行目は、接続元のIPを取得している。
183 switch (ws_record->status) { 184 case SERVER_BUSY_READ: 185 case SERVER_BUSY_WRITE: 186 case SERVER_BUSY_KEEPALIVE: 187 case SERVER_BUSY_LOG: 188 case SERVER_BUSY_DNS: 189 case SERVER_CLOSING: 190 case SERVER_GRACEFUL:
ws_record->status
のstatusで分岐をおこない、以下の状態の時にカウントをしている
#define SERVER_BUSY_READ 3 /* Reading a client request */ #define SERVER_BUSY_WRITE 4 /* Processing a client request */ #define SERVER_BUSY_KEEPALIVE 5 /* Waiting for more requests via keepalive */ #define SERVER_BUSY_LOG 6 /* Logging the request */ #define SERVER_BUSY_DNS 7 /* Looking up a hostname */ #define SERVER_CLOSING 8 /* Closing the connection */ #define SERVER_GRACEFUL 9 /* server is gracefully finishing request */
ここからが本題なのです。
190 case SERVER_GRACEFUL: 191 /* check maxclients per vhost */ 192 if (strcmp(vhostport, ws_record->vhost) == 0) { 193 vhost_count++; 194 ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, ap_server_conf, "DEBUG: (increment %s): %d/%d", vhostport, 195 vhost_count, scfg->vhost_maxclients); 196 if (vhost_count > scfg->vhost_maxclients) { 197 if (scfg->dryrun > 0) { 198 ap_log_error( 199 APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, 200 "NOTICE: [DRY-RUN] [VHOST_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s", 201 vhostport, vhost_count, scfg->vhost_maxclients, client_ip, r->uri, r->filename); 202 } else { 203 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, 204 "NOTICE: [VHOST_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s", 205 vhostport, vhost_count, scfg->vhost_maxclients, client_ip, r->uri, r->filename); 206 } 207 return (scfg->dryrun > 0) ? DECLINED : HTTP_SERVICE_UNAVAILABLE; 208 } 209 210 /* check maxclients per ip in same vhost */ 211 if (scfg->vhost_maxclients_per_ip > 0) { 212 if (strcmp(client_ip, ws_record->client) == 0) { 213 ip_count++; 214 if (ip_count > scfg->vhost_maxclients_per_ip) { 215 if (scfg->dryrun > 0) { 216 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, "NOTICE: [DRY-RUN] [CLIENT_COUNT] return " 217 "503 from %s : %d / %d client_ip: %s uri: " 218 "%s filename: %s", 219 vhostport, ip_count, scfg->vhost_maxclients_per_ip, client_ip, r->uri, r->filename); 220 } else { 221 ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, 222 "NOTICE: [CLIENT_COUNT] return 503 from %s : %d / %d client_ip: %s uri: %s filename: %s", 223 vhostport, ip_count, scfg->vhost_maxclients_per_ip, client_ip, r->uri, r->filename); 224 } 225 return (scfg->dryrun > 0) ? DECLINED : HTTP_SERVICE_UNAVAILABLE; 226 } 227 } 228 } 229 } 230 break;
- 192行目でリクエストの
hoge.com:80
とscoreboardとが一致していればvhost_count++
をインクリメント。 196行目で設定されているlimit値を超えているかの判定を行っている。
超えている場合、以下の処理を行う- 197行目でドライランかの判定を行い、それぞれでログを出力している
- 207行目でドライランであれば
DECLINED
ドライランでなければ、HTTP_SERVICE_UNAVAILABLE = 503
となる
211行目移行は、同一のvhostに対して同じIPからのアクセスを制御する
こんな感じで、このモジュールは書かれていることが分かった。
一旦、おわりー
Cも時間を割けばわかるものなのですね。。 つぎは何しよう。