AMさて、おまたせ致しました。本日より、JJUGで発表したGrizzlyについて紹介したいと思います。I/Oを使って記述された汎用的なネットワークサーバエンジンです。GlassFishとは独立して単体で使用することができます。Grizzlyは独自の進化を遂げていっています。現在、Grizzlyの最新バージョンは1.7.3.1です。1.0.x(1.0.19)について紹介します。●Grizzly誕生の背景まず、Grizzlyのできあがった背景について説明します。Grizzlyは元々GlassFishのHTTPをハンドリングするHTTPサーバを開発するプロジェクトとして開始しました。I/Oを使用して実現するHTTPサーバとして実験的に作成を開始しました。(Grizzly1.0.19でもHTMLの解析等で一部apacheのAPIを使用してます)そして開発を進めて行くに従い、Grizzlyの潜在能力の高さが判明してき、HTTPだけではなく、他のプロトコルも扱うことのできる汎用的なネットワークサーバエンジンになりえることが分かってきました。その結果、現在ではHTTP以外にTCP,UDPといった下位のレイヤープロトコルを始めとし、TLS,FTPやSIP等といったマルチプロトコルに対応するハイパフォーマンスなネットワークサーバエンジンになっています。仮に開発者が新たに独自のネットワークサーバを構築する必要がでてきた場合、GrizzlyのAPIを一部拡張して実装して頂くことでハイパフォーマンスな独自ネットワークサーバを構築することも可能になっています。GrizzlyのHTTPサーバエンジン以外の使用例として独自のsyslogサーバを構築することも可能になります。Grizzlyの背景とできることは上で説明しましたが、何故今ここでGrizzlyという新しいネットワークサーバエンジン(フレームワーク)が登場したのでしょうか。以下ではWebサーバの実装における過去の歴史とGrizzlyが登場した理由を説明します。サーバの実装における歴史Webサーバは古くはCERN,NCSA等といった所で作成されていましたが、Apacheでhttpdが作成された後はApacheにシェアを奪われていきました。httpdはプロセス起動型のサーバの実装になっていました。このプロセス起動型のサーバではHTTPクライアントであるブラウザからリクエストがくる度にhttpdのプロセスを起動しリクエスト数が多くなると子プロセスをfork()して処理を行っていました。当時のWebサーバは今程リクエスト数も多くなく、FastCGI等も無いこの時代にはサーバサイドで実行するプログラム(Perl,C等のCGI)もfork()して子プロセスで実行していました。プロセスのfork()はシステム(OS)に対して多大な負担を掛けます。そこで登場したのがマルチスレッド型のサーバです。マルチスレッド型のサーバでは単一のプロセス内でリクエスト毎にスレッドを起動し、各スレッドでHTTPの処理を行うことで、子プロセスを起動するよりシステムに対する負担は大幅に軽減するようになります。この頃になり、マルチスレッドサーバ上でサーバサイドで実行するプログラムとしてServletが脚光を浴びました。実際のWebサーバの実装は上に説明した程簡単ではありません。上記の図中にスレッドの起動プログラム例を記載していますが、Webサーバのように大量のリクエストを扱うようなプログラムの場合、accept()の処理は負荷はあまり掛からないのですが、スレッドの起動はaccept()の処理に比べ非常に負荷が高くなってしまいます。この状況ではパフォーマンスにボトルネックが生じます。そこで、スレッドの起動に関する問題を軽減する為に、実際のWebサーバではaccept()処理とスレッドの処理を分離し、間に接続キューを設けることでaccept()の処理を素早く受け流すことができるようになります。ServerはC++で上記のように実装)そして、実際にHTTPの処理を行うワーカスレッドが接続キューからコネクションを取得し、HTTPの処理を行うようになります。他のサーバの実装を細かく見たことはありませんが、恐らく現在のWebサーバの実装は似たような実装になっているのではないかと思います。I/O型サーバ)ソケット通信を行うプログラムを実装する場合、accept()やI/Oのread(),write()等を使用しますが、これらのメソッドは処理をブロックします。ServerSocket#accept()メソッドはクライアントが接続するまで待ち状態になり、クライアントからの接続があって初めてメソッドの処理を終了します。複数のクライアントからの接続を処理できるようにする為には、サンプルのようにスレッドを生成し実際の処理は別スレッドで行うように実装します。このような実装の場合、接続してくるクライアントの数が増えれば増える程、大量のスレッドが生成されることになります。スレッドが大量に生成される場合、大量のメモリが必要になってきます。下記のグラフではJavaでスレッド数を増やしていった場合に実際に必要なスレッドのスタックサイズを現していますが、これによると10,000スレッドを同時に生成した場合、約10Gバイトのメモリが必要になっています。2万スレッドになると約20Gバイトのメモリが必要になっていることがわかります。このように、単純にスレッドを増やしていくモデルのサーバはアクセス数が増えれば増える程大量のメモリを消費していくことがわかります。I/Oを使用して実装が施されています。I/Oを使用するとスレッドの作成数を減らすことができます。NIOではServerSocketChannel#accept()メソッドでaccept処理を行いますが、この処理はブロックしません。仮にこのメソッドが呼び出された時にクライアントからの接続がない場合は、すぐにnullを返します。ServerSocket#accept()メソッドのように処理をブロックしないので、クライアントのリクエスト毎に新たなスレッドを生成する必要もなくなります。言い換えると、ServerSocketChannel#accept()を呼び出した元のスレッドで引き続き処理を続けることができるようになります。複数のリクエストを処理するために、接続毎に新規スレッドを生成しなくてもよいようになります。Grizzlyの開発者の1人であるJean-Francoisは次のように述べています。「Grizzlyではたった30スレッドで10,000の接続を捌くことができます。I/Oで実装されているだけでもすごいのですがさらに、ARPも実装されています。ARPはComeのアプリケーションや、ビジネスプロセスの処理にとても時間が掛かるような場合、つまり長時間接続を保持しなければならないアプリケーションの動作も実現できるように実装されています。Processingに比べComet等のアプリケーションを実行する環境としても最適です。●まとめGrizzlyは汎用的なネットワークサーバエンジンです。独自にサーバを構築する際はGrizzlyのフレームワークを再利用することでハイパフォーマンスな独自サーバを構築することが可能になります。NIOで実装されARPに対応しているのでComet等のアプリケーションの実行環境としても最適です、そしてパフォーマンスも良いのです。GlassFish(Grizzly)を使用して新しい先進的なアプリケーションを作成してください。最後に、今回はGrizzlyの概要について紹介しました。GlassFish(Grizzly)が何故パフォーマンスがよいのかの概要を掴んでいただけたのではないかと思います。1.0.19)の見方を紹介します。9リリースプラン発表後に議論されている、スキーマやジェネリクスの扱いやツールの最新情報を紹介します。使用に同意したとみなされます。ポリシー%d人のブロガーが「いいね」をつけました。