Home > 保険システム開発室NEWS > 月別一覧

2008年12月のあいそるニュース

休日に鍋パーティ

2008-12-29 07:45

今回は季節に見合った鍋パーティを社員の自宅を借りて開きました。

人数が多いので、下記の通り水炊きとキムチ鍋の2種類を用意しました。

下の写真は今回のパーティの目玉食材である東京Xという豚肉です。 購入したのはしゃぶしゃぶ用の肉でしたが、これは大好評でした。

若者が多いので肉がてんこ盛りの鍋となってしまいましたが、値段は店で食べるよりも破格の安さで済みました。

お腹いっぱいになった後はみんなでトランプに興じました。 最近はトランプといえばオンライン上でのゲームばかりで物理的にトランプをする機会が少なくなってきましたので、久しぶりで新鮮でした。

トランプに負けた人はお酒の買出しに行ったりして罰ゲームも楽しみました。

がしかし、この頃になるといつもは冷静な男性が酒に酔って故障し始めました。
いや、故障という程ではなかったのですが、誤作動が多く生じていました。今回は独身女性の部屋を借りてのパーティだったので、テンションが上がり過ぎてしまったようです。ヤレヤレでした(ーー;)

次は新年会を予定しています。楽しみです。

Posted by T.S

Webアプリケーションの排他制御

2008-12-28 11:15

Webに限ったことではありませんが、オンラインシステムにて排他制御をしたい場合はよくあります。 例えばWebオンライン上で複数のユーザが同じデータを更新することが出来るシステムは、なんらかの排他制御の仕組みを取り入れた方がよいでしょう。

今回は私たちがWebシステムを開発してきた中でのこのようなケースで有効な排他に関するテクニックをいくつかご紹介したいと思います。

前提

Webシステムで最も排他制御が必要な対象リソースはデータベースです。ここで申し上げる排他制御を行う対象はデータベースに存在するデータとします。

楽観的ロック

楽観的ロックとはデータそのものに対してはロックをせずに、更新するときにアプリケーションの方でデータ取得時と同じ状態であることを確認してから更新する仕組みです。

例えばWebオンライン画面にて下図のようにデータベースからデータを取得した後「編集」→「確認」→「更新」のように複数画面の遷移を伴う一連の処理では、この楽観的ロックを行います。

具体的には、左図の「編集」でデータベースからデータを取得する際に、そのデータの最終更新日も取得しておきます。

そして「更新」する際にデータベースに存在するデータの最終更新日を比較し、異なっていたら編集中に他のユーザが先に更新したと見なしてその更新は無効である旨をユーザに伝えます。

最終更新日を比較する方法で手っ取り早いのは、更新する条件に最終更新日を含めてしまうことです。SQLで表現すると以下のようになります。

UPDATE table SET field1 = 'date1', field2 = 'date2', last_update = SYSDATE
  WHERE id = 1000 and last_update = '2008/12/25 23:41:11'

このように更新する条件に最終更新日を含めてしまえば更新した際に更新件数が0件であった場合は、他のユーザが先に更新(もしくは削除)したと判断できます。

また上記のように手動で実装しなくても、自動的に楽観的ロックを行ってくれるデータベース関連のAPIやミドルウェアも存在するので、そちらを利用する方法もあります。

悲観的ロック

悲観的ロックとはデータを取得する際にロックをかけ、他のプロセスから更新を許さないという仕組みです。

例えば一度のトランザクションで、関連する複数のテーブルのデータを抽出し、その抽出結果を基にして更新する場合があります。その場合、複数のテーブルからデータを抽出し、各テーブルに対して更新が終わるまでは、それらのデータのまとまりは他のプロセスから抽出と更新がされていないと保障される必要があります。

具体的な例を挙げます。左図のような伝票テーブルとそれに紐付く明細テーブルを更新するアプリケーションがあったとします。

伝票テーブルの情報はWebオンライン上の複数の画面から同時に更新される可能性があり、併せてそれに紐付く明細テーブルのデータも自由に追加・更新・削除できる仕様とします。

また、伝票テーブルには明細の合計金額を保持する項目があるとします。つまり、明細の情報が変更されたり増減した場合は、伝票テーブルのレコードの合計金額もそれに合わせて更新する必要があるとします(このテーブル設計の良し悪しはまた別の話ということで。。)。
つまり、伝票テーブルと明細テーブルは常に整合性を取って更新する必要があるわけです。

更に厄介なことに、これらのデータはWebオンライン画面からだけではなく、日中に定期的に実行されるバッチ処理でも抽出・更新される可能性があるとします。

このような場合に、悲観的ロックを行います。

特にバッチ処理では先に申し上げた楽観的ロックを行うのは適切ではありません。オンライン画面での楽観的ロックであれば、競合を検出したエラー時にユーザに通知し再入力を促すことは出来ますが、バッチ処理ではエラーとなった場合は再実行をするなりの面倒な考慮が必要となるからです。

具体的な悲観的ロックの方法は、右図の通りアプリケーションが伝票または明細テーブルを処理する際に、Webもバッチ処理でも最初に伝票テーブルの対象レコードのロックを取得してから処理を行うというルールを決めます。

重要なのは更新する直前にロックをするのではなく、そのトランザクション内で伝票データを抽出する前に、伝票テーブルの対象レコードのロックを取得することです。

悲観的ロックを実現するには、データベースのロック機構をそのまま利用します。例えば、Oracleの場合はFOR UPDATE句でありSQL ServerやDB2の場合は、更新ロック(Uロック)等が適当です。
以下はOracleのFOR UPDATE句でロックを取得する例です。

SELECT * FROM table WHERE id = 1000 FOR UPDATE

先の楽観的ロックの例に出た左図のような「編集」→「確認」→「更新」のように遷移するWebオンライン画面のシステムで、バッチ処理も存在する場合は、オンラインでの「更新」の際に悲観的ロックも併用するようにします。
またバッチ処理では常に悲観的ロックを使用して更新します。

このようにWebでもバッチでも必ず伝票テーブルの対象レコードのロックを取得してから処理をする、というルールを徹底すれば正常に排他制御が働き不整合データができることはありません。

ただし、悲観的ロックではデッドロックに注意する必要があります。 先ほどからの例で言うと、一度のトランザクションで複数の伝票データを更新する可能性がある場合は注意が必要です。

具体的な例として左図の通り、①でWebオンラインが伝票テーブルのレコード1に対してロックを取得した後、②でバッチ処理が伝票テーブルのレコード3に対してロックを取得したとします。 ③でWebオンラインが同一トランザクションで伝票テーブルのレコード3に対してロックを取得しようとするのと、④でバッチ処理が伝票テーブルのレコード1に対してロックを取得しようとするのが重なり、デッドロックに陥る可能性があるということです。

デッドロックを防止する有効な手段としては、ロックを取得する際に順番付けのルールを決めるというのがあります。上記の例でいうと、伝票のレコード番号が小さいものからロックを取得するというルールを決めれば、バッチ処理は伝票テーブルのレコード3からではなくレコード1から取得しなければならず、デッドロックが発生しません。

上記のルールが徹底されればそれに越したことはありませんが、私たちがよくやる方法はロックを取得する際にタイムアウトを設けてしまうことです。こうすれば、上記のような状態に陥ってもタイムアウトが発生してデッドロックにはなりません。
以下はOracleのFOR UPDATE句でロックを取得する際に8秒のタイムアウトを設けた例です。

SELECT * FROM table WHERE id = 1000 FOR UPDATE WAIT 8

ただし、バッチ処理から行うロックにはタイムアウトは設けません。先に申し上げた通りバッチ処理でエラーとなった場合は再実行をするなりの面倒な考慮が必要であり、オンラインのように安易にエラーを発生させる事は出来ません。
よって私たちは、バッチ処理からのロックはタイムアウトを設けずに、オンラインからのロックだけにタイムアウトを設けます。つまりバッチ処理を最優先させるということです。
ただし、バッチ処理は複数同時に実行されることは無いというのが前提です。

まとめ

以上となりますが、私たちが排他制御を行う際のポイントをまとめると下記の通りとなります。

  • 複数のユーザが同じデータを同時に更新可能なWebオンラインでは楽観的ロックを行う
  • Webオンラインと同時にバッチ処理で更新される可能性がある場合は悲観的ロックも併用する
  • 悲観的ロックでは対象データの主となるテーブルのレコードのロックを取得する
  • 同一トランザクションで複数のデータに対して悲観的ロックを取得する場合はデッドロックに注意する

Posted by T.S

Javaの仮引数と実引数

2008-12-19 17:02

前回Javaというオブジェクト指向言語で初心者が犯しやすいポイントとして、Javaのスタックとヒープというお話をしました。
これに関連する話として、本日はJavaの引数に関して仮引数と実引数の動きを簡単にご説明したいと思います。

尚、以降の内容はJavaのスタックとヒープに関して理解していただいた方を前提として記述しております。まだ御覧になってない方は、先に、こちらをご確認いただければと思います。

実引数とは

実引数とは下記のサンプルコードでの、"st"と"sb"の変数を指します。つまりメソッドに渡す呼び出し元の引数のことです。

private void func1( ){

 String st = new String("IT");
 StringBuffer sb = new StringBuffer("ソリューション");

 func2( st, sb );
}

仮引数とは

仮引数とは下記のサンプルコードでの、"st"と"sb"の変数を指します。

private void func2( String st, StringBuffer sb ){

}

Javaでは引数の渡し方は、すべて「値渡し」

引数の仕組みは「参照渡し」や「値渡し」という言い方がありますが、Javaの場合は「値渡し」になります。 Javaの引数は「参照渡し」であると誤解していらっしゃる方が多いようですが、これらの言葉の定義は別にして まずはどのように動作しているかを以下にご説明いたします。

StringBufferを引数にした場合の例

まずはStringBufferを引数とした場合を例に、どのような動きをしているかをご説明します。

private void func1( )
 StringBuffer sb1 = new StringBuffer( "IT" );------ (1)
 func2( sb1 );------ (2)
 System.out.println( sb1 );------ (5)
}
private void func2( StringBuffer sb2 ){------ (3)
 sb2.append( "ソリューション部" );------ (4)
}

下図の通り、(1)でヒープ上にStringBufferのインスタンスが生成され、そこへのアドレスがスタック上の変数sb1に格納されます。

(2) (3) でfunc2メソッドが呼び出されます。Javaではこの時に実引数sb1のアドレスが仮引数sb2にコピーされます。
重要なのは、実引数sb1と仮引数sb2はスタック上では別の領域に存在しているが、格納されているアドレスは同じという事です。
実引数のアドレスのが仮引数にコピーされるので、「値渡し」なのです。

(4)でsb2の変数を使用して値を追加すると、sb1の変数から参照するインスタンスも値が追加される。

(5)でsb1の値を出力すると下記の通り、"ITソリューション部"と出力されます。

サンプルプログラムの実行結果
ITソリューション部

Stringを引数にした場合の例

Stringを引数にするとStringBufferとは異なった挙動を見せます。これはStringは不変オブジェクトであることに起因します。

サンプルプログラムの前に、Stringで重要な性質を以下にご説明します。

String st = "ITソリューション部"; (1)
String st = new String("ITソリューション部"); (2)

上記の(1)と(2)は同じ結果になります。つまり、(1)のようにStringクラスに文字列を代入するということはヒープ上に新しいインスタンスを生成するということになるのです。
※ただし、正確には(1)と(2)は結果に至るまでの挙動が異なります。(1)のように記述したほうがパフォーマンスは良いです。

上記のStringの性質を踏まえて、以下のサンプルプログラムをご説明します。

private void func1( )
 String st1 = "IT";------ (1)
 func2( st1 );------ (2)
 System.out.println( st1 );------ (5)
}
private void func2( String st2 ){------ (3)
 st2 = st2 + "ソリューション部";------ (4)
}

Stringで文字列の代入はインスタンスを生成することになりますので、下図の通り(1)でヒープ上にStringのインスタンスが生成され、そこへのアドレスがスタック上の変数st1に格納される。

(2) (3) でfunc2メソッドが呼び出され、実引数st1のアドレスが仮引数st2にコピーされます。

先に説明したStringの性質を踏まえると、(4)に見られる仮引数st2への代入はヒープ上に新しいインスタンスが生成され、スタックのst2はそこへのアドレスが上書きされてしまいます。 よって、下図の通りst1とst2はヒープ上の別のインスタンスを指すことになります。

(5)でst1の値を出力すると下記の通り、"IT"とだけ出力されます。

サンプルプログラムの実行結果
IT

Javaは「参照渡し」ではない

上記でご説明した通り、Javaの仮引数と実引数ではスタック上の物理的な領域は異なります。 仮引数と実引数はスタック上の同じ領域を指していると勘違いすることにより、大きなバグを生んでしまうことがあるので十分な注意が必要です。

補足

上記で説明した「実引数の値が仮引数にコピーされる」というのは、プリミティブ型の場合も同様です。 プリミティブ型の変数にはアドレスではなく値そのものが保持されていますので、値そのものがコピーされるということになります。

Posted by T.S

Javaのスタックとヒープ

2008-12-14 19:30

私達はJava言語を得意とした部隊ですが、このオブジェクト指向言語で初心者が犯しやすいポイントがいくつかあります。

その一つは「変数にはインスタンス自体ではなく、インスタンスへの参照先(アドレス)が保持されている」ということが理解できていないことにより、オブジェクトの属性値がいつの間にか変わってしまうといったような不可解なバグを生み出してしまう事です
このようなバグを入れてしまうのはJavaのスタックとヒープの動きが理解できていない為です。

そういう私も新人の頃に同様のバグを起こして大変苦労した経験があります。 よって弊社での新人研修では私は必ずこのスタックとヒープの動きを説明します。また、新人の記述したソースコードをレビューする際は忘れずにこの点をチェックしています。

以下に、Javaのスタックとヒープに関しての説明と犯し易い間違いを簡単に説明します。

スタックとヒープ

Javaのメモリ領域は、大きく分けて「スタック」と「ヒープ」の2つが存在します。

スタック
 ・主にローカル変数が扱われ、その中にはインスタンスへのアドレスが保持される。
  ※変数はアドレスを入れる箱を考えてください。
ヒープ
 ・インスタンスそのものが保持される。
SampleClass sclass = null; ------ (1)
sclass = new SampleClass(); ------ (2)

上記のサンプルコードを下図と共に説明します。
まず(1)で変数を定義した際にはスタック上にアドレスを入れる箱が生まれます。
次に(2)でインスタンスを生成した際にはヒープ上にそのインスタンスが生成され、そこへのアドレスが(1)で定義した変数の中にセットされます。

スタックとヒープ

間違えやすいコードの例

先の説明を踏まえて、初心者が間違えやすいコードは以下の通りとなります。

StringBuffer sb1 = null;
StringBuffer sb2 = null;
sb1 = new StringBuffer("あ"); ------ (1)
sb2 = sb1; ------ (2)
sb1.append("い"); ------ (3)
System.out.println(sb1);
System.out.println(sb2);

最初に変数sb1とsb2を宣言します。この時点ではスタック上にsb1とsb2の変数の領域だけが確保されます。中身に入るべきアドレスは空の状態です。

次に(1)でStringBufferのインスタンスを生成します。ここで、ヒープ上にStringBufferのインスタンスが生成され、そのインスタンスへのアドレスが変数sb1に保持されます。

次に(2)でsb1をsb2に代入しています。ここで初心者は勘違いを起こす事があります。 初心者はsb2にStringBufferのインスタンスそのものをコピーしたと思ってしまいます。具体的には "あ"という値を持つStringBufferのインスタンスがもう一つ出来たと思ってしまうのです。

しかし、実際は下図の通り先にヒープ上に生成されたStringBufferのインスタンスへのアドレスがコピーされたに過ぎません。 同じアドレスがsb1とsb2に保持されますので、そのアドレスが指すヒープ上のインスタンスは同じものなのです。

スタックとヒープ

(3)でsb1変数を使用して"い"という文字列を追加します。

最後にsb1とsb2の値をSystem.out()で出力しています。
このプログラムの作成者はsb1は"あい"でsb2は"あ"と出力されることを期待したとしても、実際には下記の通りどちらも"あい"と出力されます。

サンプルプログラムの実行結果
あい
あい

上記のようなバグはソースを一見しただけでは気づきにくく、また状況によって不具合の現象も一定ではない為、原因の特定に時間のかかるバグです。
私が新人の頃に同様のバグを出した当時はJavaが生まれて間もない頃だった事もあり、 ここで説明したスタックとヒープの動きを理解している人が少なかった為、 恥ずかしながら原因の究明に何日もかかってしまったのを憶えています。

補足

上記で説明した「変数にはアドレスが格納される」というのは、オブジェクト型の変数に限ります。 プリミティブ型の変数には、値そのものが保持され代入した際には値そのものがコピーされるので上記のような不具合は発生しません。
このオブジェクト型とプリミティブ型のメモリの管理方法の違いが初心者を混乱させてしまう一つの原因のようです。

このスタックとヒープに関連して初心者が陥りやすい同様の間違いとして、仮引数と実引数の話があります。 2008年12月19日にJavaの仮引数と実引数という記事も書きましたので、是非御覧ください。

Posted by T.S

システム開発とネーミング

2008-12-11 06:56

システム開発という仕事をしていると、何かに名前をつけなければならない事が多々あります。 何事も名前をつけるという行為は難しく悩ましいものです。
今回はシステム開発に纏わる「命名」という行為に関して少しお話したいと思います。

システム名

大規模なシステムではそのシステム自体に名前をつけることがよくあります。 「原価管理システム」とか「業務管理システム」というのではなく アメリカ人やイタリア人のような名前のついたシステムの開発に携わったことは何度かあります。
ジャストシステムの製品では「一太郎」とか「花子」等あえて日本人の名前を採用していたりするのは、日本企業ならではのこだわりが感じられ結構好きです。

ちなみに難易度が高い名前は、そのシステムの目的や理想のような英単語の頭文字をつなげて、最もらしい名前にすることだと思います。
これらの類では個人的にJSON(ジェイソン、JavaScript Object Notation)というデータフォーマットの名前が好きです。

開発しているシステムに名前をつけるということはいくつか利点があります。 例えば、「ディック」と命名されたシステムがあったとしたら「XXXシステム」とわざわざ呼ぶよりも「ディック」の方が会話がスムーズになりますし、何よりシステムに対して開発者の深い愛着が生まれます。

コードネーム

開発中の製品には名前とは別にコードネームが付いたりします。元々コードネームとは開発中の製品の機密保持が目的だったようですが、近年ではあえて一般に公開されることも多く、システムのバージョンを表す別名という意味合いが強くなってきています。

コードネームに限った事ではありませんが、一定のルールに則ってつけられる名前があります。コードネームで私が好きなのは2つあります。

一つはLinuxのディストリビューションの一つDebian GNU/Linuxのコードネームです。 Debianのコードネームは、下表の通り映画の「トイ・ストーリー」のキャラクタとなっています。woodyやsargeはよく利用しました。

バージョン コードネーム 説明
1.1 buzz バズ・ライトイヤー。主人公の宇宙飛行士。
1.2 rex レックス
1.3 bo ボー・ピープ
2.0 hamm ハム
2.1 slink スリンキードッグ
2.2 potato ミスターポテトヘッド
3.0 woody ウッディ
3.1 sarge 軍曹
4.0 etch エッチ・ア・スケッチ

もう一つ好きなのはJava開発者なら身近なEclipseのコードネームです。Eclipseのコードネームは木星の衛星の名前からつけられています。木星の衛星というチョイスはかなりナイスです。

バージョン コードネーム 説明
3.2 Callisto カリスト
3.3 Europa エウロパ
3.4 Ganymede ガニメデ

Eclipse ちなみにEclipseはもともとはIBMが開発した製品がベースとなっています(現在はオープンソースです)。 有名な話ですがEclipse(日食)というネーミングは、IBMがライバルのSun(太陽)との対立を表しているといわれていますが、 当然IBMは公式には否定しているようです。

ホスト名

私は社内にある数十台のサーバの面倒を見ていますが、以前は新しいサーバを立ち上げる際のホスト名の命名に悩みました。 例えば新しくWindowsPCを購入した際に、初期設定で「コンピュータ名」を何にしようか悩む方もいらっしゃると思います。しかしPCは後から簡単に変えられますが、サーバのホスト名の変更は、PCほど容易には出来ません。

一般的に多数のサーバのホスト名の命名には選択肢が豊富なシリーズものが好まれ、例えば「太陽系の惑星」、「星座」、「動物名」、「ギリシャ神話の神」等はサーバ管理者の間ではよく使われています。

まだ私がサーバ管理者になりたての頃に、これらサーバのホスト名の命名で失敗したことがあります。 ある大規模プロジェクトで開発サーバを何台も構築する必要が発生した際に、 理由は忘れましたが何故か「北斗の拳」のキャラクターから名前を拝借したことがありました(多分疲れていたのです)。 かなり前なので、全てを思い出せませんが以下のような感じだったと思います。

・raou(ラオウ)
・kokuou(黒王号)
・kaiou(カイオウ)
・ken(ケンシロウ)
・yuria(ユリア)
・jagi(ジャギ)  ←ジャギと命名されたサーバはかなりスペックが低い

今思うとかなり痛々しい名前でしたが、当時は名前を考える時間も勿体無いくらい忙しかったわけです。

幸い、開発プロジェクトが終了したらこれらのサーバも別の開発サーバに転用されていった為、 再インストールでホスト名も消えていったのですが、諸事情により「kokuou」サーバだけは ついこの間まで弊社の中で現役で稼動しておりました。

最近は社内のサーバのホスト名は、それなりの命名規則に則ってつけていたのですが この「kokuou」だけは数年間もずっとこの規則から外れたサーバとしてがんばっていました。

この「kukuou」サーバにログインする度に、「ああ、やっぱり名前は慎重に考えないとイカン」と身に染みていました。。。

開発資源のネーミング

システム開発者が日常的に悩むのは、設計時のデータベースの「テーブル名」や「フィールド名」、コーディング時の「変数名」「メソッド名」「クラス名」等の命名でしょう。
「ああー、こんなクラス名をどうするかで悩んでいる暇ねーのに!」という思いは誰もが経験した事があると思います。

これらの命名は英語にするか日本語にするかという選択や、言語によっても文化が異なり意外と奥深い話題です。
また大規模システム開発ではこれらは命名規約によって左右されますので、その規約を作る人の手腕によって大きく左右されます。(テーブル名やクラス名がID形式の命名規約は最悪です。)

この辺の話は書き出すとまた長くなってしまうので、また別の機会に続きを書きたいと思います。

Posted by T.S

IPv6のIPアドレス数はどのくらい多いのか

2008-12-07 01:07

IPとはインターネットプロトコル(Internet Protocol)のことで、インターネットの中核の技術です。ネットワークに参加している機器に割り振られる「IPアドレス」という言葉は、ネットワークに詳しくない方も聞いた事があると思います。

現在主流のIPのバージョンは4であり後継バージョンは6であることも有名です。それぞれ、IPv4(あいぴーぶいよん)、IPv6(あいぴーぶいろく)などと呼ばれています。

私のような業務アプリケーション開発を主にしているSEでもIPv6をよく見かけるようになりました。 家庭用のブロードバンドルータにも搭載していたり、Windows XPやVistaでも普通にIPv6を設定できます。しかし、未だに使用したことがありません。

かなり前からIPv4のIPアドレスが枯渇しそうだと言われておきながら、なかなかそのような状況になっていません。といいつつも、いよいよもうすぐ無くなるという話もチラホラ耳にします。
以前、社外のネットワーク研修を受けた際に講師の方がこの話題を取り上げていましたが、DHCP等のIPの動的割り振りやNATやIPマスカレードなどのアドレス変換技術が普及してIPアドレスが減るペースが落ちた事が、なかなか枯渇しない理由の一つだとその時にはおっしゃってました。
とはいっても地球の石炭や石油と一緒でいずれ無くなるだろうと思われるIPv4のIPアドレスですので、本日は後継バージョンのIPv6に関して少し書いてみたいと思います。

IPv6のIPアドレスはどのくらい多いのか

IPv6の仕様に関してはあらゆるサイトで説明されていますので、その辺は他のサイトにお任せして、月並みな話ですが現状のIPv4と最も大きな違いである数に関して比較してみたいと思います。

IPv4 232 4294967296個 約43億個
IPv6 2128 340282366920938463463374607431768211456個 約340澗(かん)個

それぞれの仕様上、定義できるIPアドレスの数は上記の表の通りとなります。 IPv6となると澗(かん)という聞いた事の無い桁が出てきます。兆という位の次は京(けい)というのは聞いたことがありますが、澗(かん)はその京の5つ上の位になります。

私が初めてIPv6の存在を知った当時に、新しいIPは地球上で人間が目に見える全ての物体に対してIPアドレスを割り振っても十分な数であると聞いた事があり、その時のインパクトが大きくて未だにその話は覚えております。

地球上で1cm四方で割り振れるIPv6のアドレスの数 実際IPv6は、地球の表面積1cm2当たり約6670京個のIPアドレスを割当てることができます。
※京(けい)は兆の次の位
つまり地球上の目に見える全ての物体に対してIPが割り振れるというのは本当で、 いやそんなもんではく地球上の全てのチリやホコリにIPを振っても十分だということです。

なぜIPv4の次がIPv6なのか

よく疑問に思うこととして、IPv4の次がv6で一体"v5"はどこへ行ってしまったのかという事です。実はIPv5もちゃんと存在しています。
IPは実験的に開発されたプロトコルでも、そのバージョンが割り当てられます。 つまり、IPv5は実験的なプロトコルで実用化されずに終わってしまったプロトコルということです。 具体的にはIPv5はST-II(stream protocol-II)という音声や動画を電送するためのプロトコルのようです。

IPv6はいつごろ生まれたのか

IPv6の原案が固まったのは1995年末、その後実用化に向けて動きが本格化したのは1998年ですので、その頃から既に10年以上前経過していることになります。
ちなみにIPv4は考案されたのが1970年代ですので、既に30年以上経っても現役バリバリの恐ろしい技術です。
※TCP/IPというプロトコルはもはや芸術と言っていいほど素晴らしいプロトコルであり、個人的に感動した仕組みがいくつかあるのでそれは別の機会でご紹介したいと思います。

現在の最新バージョンは

IPは実験的に開発されたプロトコルでも、そのバージョンが割り当てられると先ほど言いましたが、 実はv7、v8、v9も同じように割り当て済みです。 つまり、IPv6の後継バージョンはIPv10以降になる見込みとなります。

十分なIPアドレスの数は時代によって変わる

宇宙に飛び出した人類に必要なIPアドレスの数は想像を絶する IPアドレスの数は、IPv4が生まれた当時の状況では40億個で十分と考えられていただけに、 それを踏まえると340澗(かん)個という数が将来ずっと十分であるかは分かりません。 少なくともIPv6が現役の間はこの数で十分でしょうが、その先の未来では十分なIPアドレスの数は時代によって変わってくるのは当然です。

今の私たちの感覚ではIPv6のIPアドレスは無限に近い数です。上記では地球の表面積を例に表現しましたが、 現代のインターネットを中心とした科学技術のレベルでは地球を舞台にするのが適切だからです。

しかし人類の科学技術がずっと発達した未来、例えば医療のナノテクノロジーが更に進み、また宇宙開拓時代に突入している時代には必要なIPアドレスの数は想像を絶します。

このような考えは、1994年エープリルフール発行のRFC1606で取り上げられています。
※RFC1606ではIPv6ではなくIPv9に関しての話ということになっています。

RFC1606 「IPバージョン9の利用の歴史的概観」 : 原文  日本語訳

エープリルフール等に発行されるRFCはジョークRFCと呼ばれ、他にも沢山あり結構内容が面白いので、また別の機会にでも取り上げたいと思います。

Posted by T.S

MXレコードとスパムメール2

2008-12-05 07:14

2008年12月3日に公開したMXレコードとスパムメール1という記事の続きになります。

実際にスパムメールの件数を調査した結果

実際、MXレコードにて最も優先度の低いサーバにどのくらいスパムメールがダイレクトに届いているのか確認してみました。

ちなみに、確認を試みたメールサーバ環境は以下のような構成でした。

調査対象のメールサーバ構成
MX preference = 10, mail exchanger = mail1.example.jp ・・・優先度「高」のメールサーバ
MX preference = 20, mail exchanger = mail2.example.jp ・・・優先度「中」のメールサーバ
MX preference = 30, mail exchanger = mail3.example.jp ・・・優先度「低」のメールサーバ

優先度最低のメールサーバに届くスパムメールの割合 3日間調査を行ったのですが、上図の通り3台メールサーバが存在する環境にて、1つの公開メールアドレス宛に届いた「スパムメール」の件数と、そのスパムメールのうち最も優先度の低いメールサーバ(上図で緑の丸がついたサーバ)にダイレクトに届いたメールの件数は左図の通りでした。

左図の通り、スパムメールのうち約30%が直接優先度が最も低いメールサーバにダイレクトに届いていたことが分かりました。 もはやスパムメールを送信するサーバは、優先度(preference)は見ていないと思ったほうがよいでしょう。

更にMXレコードに最も優先度の低いメールサーバを追加した結果

実際に業務で使用しているメールサーバなので、現状のメール送受信業務に影響を与えないように下図のように、更に優先度が低いMXレコードを追加しました(追加したMXレコードのメールサーバは、下図の優先度「中高」と同じものとしました。)。

これも同様に3日間調査を行い、公開メールアドレス宛に届いた「スパムメール」の件数と、先の調査と同じメールサーバ(下図の緑の丸がついたサーバ)にダイレクトに届いたスパムメールの件数をカウントしました。
※無論MXレコードを追加した後に、設定したDNS情報が世界に浸透するまでしばらく期間を置いてから調査しました。

更にMXレコードを追加したメールサーバ構成
MX preference = 10, mail exchanger = mail1.example.jp ・・・優先度「高」のメールサーバ
MX preference = 20, mail exchanger = mail2.example.jp ・・・優先度「中高」のメールサーバ
MX preference = 30, mail exchanger = mail3.example.jp ・・・優先度「中低」のメールサーバ
MX preference = 40, mail exchanger = mail2.example.jp ・・・preference=20と同じサーバを追加

緑の丸がついたメールサーバに届くスパムメールの割合 結果は左図の通り、約30%から約13%に減少しました。

以上の結果から、MXレコード追加型のスパムフィルタサーバを導入したら、優先度が最も高いMXレコードにだけではなく 最も低いMXレコードにも設定しておくことが非常に有効であると考えられます。

しかし、完全にスパムメールの裏をかくことは出来ないようです。 恐らくですが、例えば3つ以上の優先度の異なるMXレコードが存在したら中間のメールサーバを狙うとか、MXレコードに登録されているメールサーバをランダムに選んで送信するとか、最近のスパムメール業者は色々な手を打っていると思います。

MXレコード追加型のスパムフィルタを導入したらこの設定をしないと損

というわけでMXレコード追加型のスパムフィルタを導入したら、上記のような設定をしないと損だということです。 100%の効果はありませんが、なんといってもノーコスト&ノーリスクハイリターンです。
もちろん弊社のメールサーバでもこの設定は取り入れています。

Posted by T.S

MXレコードとスパムメール1

2008-12-03 07:56

スパムメールが大きな問題となっている昨今ですが、非常に簡単にスパムフィルターを提供してくれるサービスが沢山存在します。 特に、自社のメールサーバのインフラに影響を与えずに簡単にスパムフィルターを利用させてくれるサービスの多くは、 スパムフィルターを搭載した業者のメールサーバをDNSサーバのMXレコードで最優先に設定して、そのフィルターを通過したメールが更に本当のメールサーバに転送する方式が多くなっています。

DNSのMXレコードやメールサーバの優先度に関しては、こちらのメールサーバとMXレコードという記事を御覧ください。

スパムフィルターサービス導入前の構成

例として下記の通りメールサーバが1台の一般的なメールサーバ構成があるとします。 この場合、MXレコードも1つのみ定義されている状態です。

スパムフィルターサービス導入前の構成図
MX preference = 10, mail exchanger = mail.example.jp ・・・運用中のメールサーバ

スパムフィルターサービス導入後の構成

簡単にスパムフィルターを提供してくれるサービスを利用し、 MXレコードを一つ追加し優先度の高いメールサーバをその会社のメールサーバに設定します。 スパムフィルターサービスを提供してくれるメールサーバは、 外部からメールを受信しスパム判定を行い、正常なメールであれば運用中のメールサーバに転送してくれます。

スパムフィルターサービス導入後の構成図
MX preference = 10, mail exchanger = spam.example.co.jp ・・スパムフィルタ業者のメールサーバ
MX preference = 20, mail exchanger = mail.example.jp ・・・・運用中のメールサーバ

スパムフィルターサービスを提供する業者のメールサーバは、スパムメールと判定した場合は、必要に応じてメールを破棄したりタイトルやヘッダーに印を追記したりしてくれます。
このように、DNSサーバにMXレコードを追加するだけで既存にインフラに殆ど手を加えることなく、簡単にスパムフィルターを導入できるのです。

優先順位の低いメールサーバをあえて狙うスパムメール

しかしこれには抜け穴がありまして、スパムメールを送信するメール送信サーバがルールに則って最も優先順位が高い(preferenceが小さい)メール送信サーバにメールを送信してくれないと意味がありません。 下図のようにあえて最も優先順位の低い(preferenceが大きい)メールサーバをダイレクトに狙ってメールを送信してくるスパムメールは実は沢山あります。

優先度の低いサーバを狙ったスパムメール

このようなスパムメールを防ぐ最も簡単な方法は、MXレコードに既存の運用中のメールサーバ情報を設定しないことです。 こうすれば、必ずスパムフィルターサービスを提供する業者のメールサーバを経由してメールが届きます。

しかし、MXレコードを複数用意することは障害対策には非常に有効です。MXレコードをスパムフィルターサービスの提供するメールサーバだけにした場合、万が一そのメールサーバに障害が発生した場合は、運用中のメールサーバにはメールが一切届きません。
MXレコードに運用中のメールサーバも登録しておけば、優先順位の高いメールサーバに障害が発生しても、とりあえず次の優先順位のメールサーバにメールは届きます。特にビジネスのツールとして重要なメールサーバは、可用性を第一に考えることも重要です。

優先順位の低いメールサーバをあえて狙うスパムメールの裏をかく

優先順位の低いメールをあえて狙ってくるスパムメールの対策にも有名な方法があります。 以下のようにMXレコードにて優先順位の最も低いメールサーバも、スパムフィルターサーバを指定するのです。 実は、私も以下の記事で知りました。
japan.internet.com 最新インターネットニュース:スパムからメールサーバーを守るには?

優先度の低いサーバを狙ったスパムメールの裏をかく
MX preference = 10, mail exchanger = spam.example.co.jp ・・スパムフィルタ業者のメールサーバ
MX preference = 20, mail exchanger = mail.example.jp ・・・・運用中のメールサーバ
MX preference = 99, mail exchanger = spam.example.co.jp ・・スパムフィルタ業者のメールサーバ

つまりpreference=10とpreference=99のメールサーバは全く同じサーバを指定しています。 これは費用が一切かからずMXレコードを1件追加するだけの素晴らしいアイデアだと思います。

補足

実際、MXレコードにて最も優先度の低いサーバにどのくらいスパムメールがダイレクトに届いているのか確認したことがあります。 その結果は2008年12月5日にMXレコードとスパムメール2として書きましたので、当記事の続きとして是非御覧ください。

Posted by T.S

品川まで散歩

2008-12-01 00:00

昼休みの散歩で今度は品川まで行ってみました。意外と近かったです。

ただ歩くだけではつまらないので、散歩の経路で絵や文字を描くことにしました。

今回は数字の「8」のつもりで歩いたのですが、スイミーの巨大魚みたいになってしまいました。

私たちの会社もスイミーのように知恵と勇気を振り絞って大企業並みのサービスを提供したいと思います(イイ話でまとまりました)。

Posted by T.S

このページの上部へ