開眼!JavaScript を読んでみた!

最近イメチェンをして襟足がなくなってしまったメガネです。

先日会社で隣に座っている社員さんから、JavaScriptの本を借りて読んでみたら、目から鱗だったのでざっくり感想を書いてみる。

最初に感想をいってしまうと、この本はJavaScriptの暗黙な部分を分かりやすく説明してくれてるなーって感じがしました。

1.javascriptは全てがオブジェクトではなかった!

javascriptで文字列を扱いたい場合は以下のような書き方があります。
Stringオブジェクト変数と文字列リテラル変数で動作の違いを検証したいと思います。

1
2
3
4
5
// Stringオブジェクト  
var str1 = new String("Hello World");

// 文字列リテラル
var str2 = "Hello World";

検証1. 変数の型を出力する

1
console.log(typeof str1);

出力結果:
object

1
console.log(typeof str2);

出力結果:
string

まぁ、ここまではなんとなく理解できる。

検証2. lengthメソッドを使って文字列の長さを取得する

1
console.log(str1.length);

出力結果:
11

これもオブジェクトのメソッドが使われてんだなーと、まぁわかる。

1
console.log(str2.length);

出力結果:
11

おや?あれ?str2はstringなのでプリミティブ型※1のはず。。。
length以外にもStringオブジェクトのメソッド全部使えちゃうけどなんでたー(?_?)

※1. プリミティブ型: 数字とか文字とかの基本的な値

以下サイトから引用

文字列リテラルのメソッド

文字列リテラルのメソッドを呼び出すと、一時的に文字列のラッパー オブジェクトに変換されます。 文字列リテラルは、その作成に new 演算子が使用されているかのように扱われます。

つまり、実行時にオブジェクトがつくられて、実行が終わったらオブジェクトは破棄されるってことなのかー。

javascriptは全てがオブジェクトではなく、オブジェクトのように振る舞うことができる言語なのね!!

2.プリミティブ型とオブジェクトの違い

比較
プリミティブ: 値を比較
オブジェクト: 参照を比較

1
2
3
4
var num1 = new Number(10);
var num2 = new Number(10);

console.log(num1 == num2);

出力結果:
false

1
2
3
4
5
6
var num1 = new Number(10);
var num2 = new Number(5);

num2 = num1;

console.log(num1 == num2);

出力結果:
true

値が違くてもオブジェクト型は参照を比較するので結果はtrueになる

3.所感

もっとjavascriptの本質に触れたい!という方は必読です。
本自体は薄いですが、かなり内容が濃くなっています。

apacheのKeepAliveをそれなりに考えてみた

5年以上apahce使ってるけどKeepAliveの設定ってあまり気にすることなかった。ていうか、そこまで巨大なサービスを運用する機会がなかったからとりえずonにしとけばいいんじゃね!?ぐらいなもんではい。。。

では、実際になぜKeepAliveが必要なのかhttpの仕様をみながらお話していきます。

注)KeepAliveはHTTP/1.1より実装された機能なので以下はHTTP/1.1を前提にお話いたします。 apacheをスレッドベースで動作させる方法もありますが、プロセスベースで検証します。

httpはステートレス・プロトコル

ステートレス・プロトコル(stateless protocol)とは状態を持たないプロトコルのことで、必要なレスポンスをかえしたら即時に切断される。サーバ側はどこの誰がリクエストしているかも知らないし、クライアントがどういう状態かもわからない。

つまり一人の人が100回アクセスしてこようがサーバー側では100回違う人がアクセスしてきてるという認識だ。

逆に状態を持つプロトコルでステートフル・プロトコル(stateful protocol)というものもある。
例えば、FTPは任意のホスト間のファイル転送を行いますが、クライアントからの接続要求によって通信が開始され、クライアントから明示的に切断要求がない限り通信状態が保持される。
一度接続を確立すると「あのファイルが欲しい」「このファイルをアップロードしたい」「ファイルを削除したい」等の処理を対話的に行う。
特定少数のユーザーしか使わないのに、通信のリクエストが入る度に認証処理をしてたら効率が悪いですね。

「えぇーーでもECサイトとかだとログイン状態保持してんじゃん!」

それは毎回クライアントから私こういうものですけどーっていうID(SESSION ID)を渡しつづけているからなのです。
そのIDをもとにサーバー側であー○○さんね!
てなかんじでリクエストの度にクライアントからIDを渡すことで、擬似的にステートフルなサービスを実現している。

なぜhttpはステートレスなのか?

ステートフルはクライアントが明示的に切断しないと接続が残りつづけるので、webページみたいな不特定多数からのアクセスに対しては不向きだ。 仮にhttpがステートフルだったら100万アクセスあったら100万個のコネクションを維持しないといけなくなる。。。 これではリクエストをさばききれないので、うけたらさっさと切断してしまったほうがいいわけです(笑)

実際のお店で例えてみる

webページってcssとかjsとか画像とか1ページ読み込むだけでたくさん通信してるし、ECサイトなんかだと購入途中でつながりにくくなるのも嫌だからやっぱりある程度接続しててもらったほうがいいんじゃない?

実際にお店で買い物をした場合で例えてみよう。
大行列の10人はいるお店で何かものを買おうとしたとき、商品を手にするたびに最後尾から並びなおすということがおきたらどうだろう?
買う気失せますね(笑)

そこで一時的にコネクションを維持しといてあげるよっていうのがKeepAliveだ。

○KeepAliveの設定項目
・KeepAlive On
接続を維持するかどうか

・MaxKeepAliveRequests 100
接続してから切断するまでに受け付けるリクエストの数
(商品100個とったら強制退出させるわ数)

・KeepAliveTimeout 15
接続しているセッションからのリクエストが来なくなってから切断するまでの待ち時間
(最後に商品を手にしてから15秒たったら強制退出させるわ秒数)

通信の状態を確認

実際にKeepAliveを設定した場合にサーバー側でコネクションが維持されているのかを確認したいと思う。

○検証内容

・画像(aa.jpg)を一つだけ埋め込んだindex.html にアクセスし、index.htmlの読み込みに1通信、画像の読み込みに1通信、計2通信を発生させKeepAliveがOnの時にコネクションが使い回されているかどうか確認する。

※KeepAliveの設定は上記であげているがここでは純粋にコネクションの動きだけを見たいので、KeepAliveのOnとOffだけで違いをみることにします。
※apacheの設定のみでKeepAliveを無効にできない(1つのコネクションでいくつリクエストを処理するかはブラウザ依存のため)ため、curlにて検証

■KeepAlive Off

【netstat実行結果】

1
2
3
Proto Recv-Q Send-Q Local Address Foreign Address State  
tcp 0 0 ::ffff:192.168.0.3:http XXXX.XXXX.XXXX.XXXX:62207 TIME_WAIT
tcp 0 0 ::ffff:192.168.0.3:http XXXX.XXXX.XXXX.XXXX:62209 TIME_WAIT

【パケットキャプチャ】

■KeepAlive On

【netstat実行結果】

1
2
Proto Recv-Q Send-Q Local Address Foreign Address State  
tcp 0 0 ::ffff:192.168.0.3:http XXXX.XXXX.XXXX.XXXX:62134 ESTABLISHED

【パケットキャプチャ】

上記の結果からKeepAlive Onの時はTCPコネクションが再利用され、KeepAlive Offの場合は通信ごとにTCPコネクションがはられていることがわかる。

所感

1ページあたりの読み込むファイル数が多いページは リクエスト可能回数(MaxKeepAliveRequests)、コネクションを維持する秒数(KeepAliveTimeout)を少し長目にとるとかするといいのかも。 設定はサイトによって柔軟に変更するといいと思います。