Perl Hackers Hub

第29回 Perlプログラマのためのstrace入門ーWebアプリケーションをシステムコールレベルでデバッグしよう(2)

この記事を読むのに必要な時間:およそ 4 分

前回の(1)こちらから。

Webサーバが呼ぶシステムコール

(2)では,PSGIPerl Web Server Gateway Interface互換のアプリケーションサーバとしてStarmanやStarletなどを使っている場合に,それらのモジュールが処理する部分でのシステムコールについて解説します。

通常のアプリケーション開発では,⁠Starman/StarletやFCGIなどWebサーバとして動く部分」はあまり意識せず「自分が開発しているアプリケーション部分(Webアプリケーションフレームなども含む)⁠に意識が集中していることが多いでしょう。しかし,Webアプリケーションが発行するシステムコールという観点に立つなら,それらの間に区別はありません。straceを使ってトレースを行った場合も当然,アプリケーション内でのレイヤを問わず,時系列順に発行されたシステムコールが表示されます。

一般に,Perlで書かれたWebアプリケーションをstraceすると次のようなシーケンスが繰り返し見られます注4)⁠

accept(4, {sa_family=AF_INET, sin_port=htons(49150), sin_a
ddr=inet_addr("127.0.0.1")}, [16]) = 5
(中略)
read(5, "GET / HTTP/1.0\r\nHost: xxx-xxxxxx"..., 131072) = 308
(中略)
write(5, "HTTP/1.1 200 OK\r\nDate: Sun, 10 A"..., 2218) = 2218
close(5)                                  = 0
accept(4,

Webサーバはaccept(2)で待ち受け,リクエストが到着するまでブロックし,リクエストを受け付けた時点で処理がアプリケーション側に戻ります。上記のシーケンスでは,1回目のacceptの戻り値として5が返っていますが,この値がクライアント側のソケットを表すファイルディスクリプタとなります。

「UNIXではあらゆるものがファイルである」という思想めいた言葉を目にしたことがある人も多いかと思います。Linuxにおいても同様に,ディスクなどへのRead/WriteやネットワークソケットへのRead/Writeは,ファイルディスクリプタへのread(2),write(2)として表現されます。すなわち,HTTPクライアントからのリクエストを読み込み,レスポンスを返すということは,クライアント側のソケットを表すファイルディスクリプタに対してread(2),write(2)を行うのと同義になります。上記の例では,5を引数にread(2)やwrite(2)を呼び出し,最後にclose(2)を呼んでレスポンスの終わりとし,またaccept(2)を呼び出して次のリクエストを待ち受ける,という一連の流れを見ることができます。

利用しているWebサーバ実装によっては,これらのシステムコールの前段にselect(2)が挟まっていたり,epoll_wait(2)が絡んでいたりと,異なる処理シーケンスでリクエストを処理している場合もありますが,Webアプリケーションがリクエストを受けてレスポンスを返すまでの最も基本的な形はこれになります。

注4)
実際にはこれらのシステムコールの間にはほかのシステムコールが挟まります。

Webアプリケーションで注目すべきシステムコール

前節では「HTTPリクエストを受け付け,HTTPレスポンスを返す」という,Webアプリケーションとして最も本質的な部分のシーケンスに触れました。ただ実際のアプリケーションをstraceしてデバッグやパフォーマンスチューニングを行う場合に最も気になるのは,やはりその中間にある自分たちのサービスのために書かれた処理の部分です。

非常にざっくり分類すると,リクエスト/レスポンスの間に行われる処理は次の3つになります。

  • (a)ネットワークソケットを開き,読み取り,書き込む
  • (b)ファイルを開き,読み取り,書き込む
  • (c)リクエストの内容,および上記2つによって得られたデータに基づいて計算を行う

Perlで書かれたWebアプリケーションでは,データを永続化するためにMySQLやPostgreSQL,またはいわゆるNoSQLに類するデータベースを利用し,それら永続化データのキャッシュとしてmemcached,Redisなどを用いることが多いでしょう。それらミドルウェアへのアクセスはネットワークを経由して行われるため,straceから見ると(a)として観測されます。

また,リクエストの途中でログを書いたり,ファイルキャッシュにアクセスしたり,特定の設定ファイルを読み込むなどの操作は(b)として観測されます。

本節の以降では,⁠a)⁠b)の操作で利用されるシステムコールと,それに沿ったstraceの内容の読み方を解説します。⁠c)については,⁠a)などに比べると問題が起こりにくく,また問題があった場合もstraceによる調査ではなくほかのアプローチをとったほうがよい部分なので,本稿では触れません。

著者プロフィール

横江直輔(よこえなおすけ)

意識の低いエンジニア。仕事ではPerlとかJavaScriptとか書いたり。個人AndroidアプリをScalaでちょこちょこ作っていたが,最近Google Playのアカウントを剥奪された。

App Storeにも一個アプリを出したが放置状態。Objective-C忘れました。

Blog:http://zentoo.hatenablog.com/

コメント

コメントの記入