タイプセーフスタック-JavaおよびScalaで簡単にスケーラブルなソフトウェアシステムを作成する機能を提供する最新のソフトウェアプラットフォーム。 スタックは、 Akka 2.0およびPlayframework 2.0フレームワークを含むJVM上で実行されます。 開発されたシステムの実質的に無制限のスケーラビリティを提供するプラットフォームのコアは、アクターライブラリであり、これはアクターモデルに基づいてマルチタスクを実装します。
俳優モデル
アクターモデルの厳密な定義、およびその歴史と基本的な概念は、 Wikipediaで見つけることができます。 つまり、アクターモデルは、周囲のすべてがアクターであるという哲学に基づいています。 これは、オブジェクト指向プログラミングの哲学に似ていますが、唯一の違いは、アクターモデルでは、原則としてオブジェクト指向プログラミングのようにプログラムが順次実行される場合、計算が本質的に時間的に一致することです。 アクターモデルには共有状態がなく、データは、あるアクターから別のアクターへのメッセージパッシングメカニズムを使用して交換されます。 各アクターには、受信メッセージのキューがあり、順番に処理されます。 共有状態がなく、メッセージが順次処理されるため、アクターモデルに基づくプログラムの計算の並列化が大幅に簡素化され、そのようなプログラムの信頼性が向上します。
あか
前述のとおり、AkkaはJVMにアクターモデルを実装します。 それ以外の場合、アクターはライトスレッド(緑のスレッド)と呼ばれます。 このようなフローは非常に軽量で、その数は1 GBのRAMあたり約270万に達し、1つのノードで送信されるメッセージの数は2,000万/秒を超えます。 ネットワークを介してアクターの相互作用を整理する可能性があり、開発されたアプリケーションの拡張性はほぼ無限になります。 Akkaの機能の詳細については、 公式Webサイトを参照してください 。
タイプセーフとAkkaの例
オリジナル: ここ
Typesafe StackでAkkaを使い始めるのはとても簡単です。 セットアッププロセスはスタックディストリビューションのダウンロードとインストールになります。 開発にはJavaとScalaの両方を使用できますが、後者を使用すると、プログラムが特にスリムで読みやすく、理解しやすくなるため、以下の例ではScalaを使用します。
問題の声明
この例では、アクターを使用してPIの数の値を計算します。 この操作ではプロセッサを集中的に使用するため、Akkaを使用すると、マルチコアマシンでスケーラブルな並列コンピューティングを実装できます。 使用されるアルゴリズムは十分に並列化されています。 各計算は独立しており、アクターモデルに完全に投影されます。 計算の式は次のとおりです。
メインアクターはこのシリーズをコンポーネントに分割し、計算のために各メンバーを補助アクターに送信します(シリーズの各メンバーに1つの補助アクター)。 計算が完了すると、各補助アクターは結果を主アクターに返します。 すべての計算の結果を受け取った後、メインアクターが回答を作成します。
プロジェクト作成
まず、 giter8テンプレートからプロジェクトを作成する必要があります(Typesafe Stackをインストールする必要があります):
c:\temp>g8 typesafehub/akka-scala-sbt
Akka 2.0 Project Using Scala and sbt
organization [org.example]: akka.tutorial
package [org.example]: akka.tutorial.first.scala
name [Akka Project In Scala]: PI Calculator
akka_version [2.0]:
version [0.1-SNAPSHOT]:
Applied typesafehub/akka-scala-sbt.g8 in pi-calculator
プロジェクトが作成されたので、プロジェクトフォルダーに移動します。
c:\temp>cd pi-calculator
コードの書き始め
まず、適切なフォルダー(
./src/main/scala/akka/tutorial/first/scala/
)に
./src/main/scala/akka/tutorial/first/scala/
ファイルを作成し、必要なライブラリーをインポートする必要があります。
import akka.actor._
import akka.routing.RoundRobinRouter
import akka.util.Duration
import akka.util.duration._
メッセージテンプレートの作成
上記で簡単に説明したアプリケーションのアーキテクチャを明確にします。 多くの
Worker
アクターを作成し、計算を初期化する
Master
アクターが1つあります。 これを行うために、彼はタスク全体を小さな操作に分割し、これらの操作をアクターの
Worker
送信します。 操作を実行した後、
Worker
アクターは集計の結果を返します。 計算が完了すると、
Master
アクターは
Listener
結果をアクターに送信し、アクターはそれを画面に表示します。
この説明に基づいて、システムで送信されるメッセージを作成します。
-
Calculate
-Master
アクターに送信して計算を開始します -
Work
-Master
Worker
アクターにアクターに送信され、実行される操作の説明が含まれています -
Result
-Worker
俳優からMaster
Worker
俳優に送信 -
PiApproximation
Master
アクターからListener
アクターに送信され、計算の結果と計算にかかった時間を含む
一般的な可変状態を排除するために、アクターに送信されるメッセージは不変でなければなりません。 Scalaでは、ケースクラスがこれに最適です。 また、メッセージの共通の基本特性を作成します。これは、メッセージの無制限な追加を防ぐために封印済みとして指定します。
封印された特性PiMessage ケースオブジェクトCalculateはPiMessageを拡張します ケースクラスWork(開始:Int、nrOfElements:Int)はPiMessageを拡張します ケースクラスResult(値:Double)はPiMessageを拡張します ケースクラスPiApproximation(pi:Double、duration:Duration)
Worker
アクターの作成
これで
Worker
アクターを作成できます。 これは、
Actor
トレイトを混合し、
receive
メソッドを定義する
receive
によって行われます。 このメソッドは着信メッセージハンドラです。
クラスWorkerはActorを拡張します{ // CalculatePiFor ... def receive = { ケース作業(開始、nrOfElements)⇒ 送信者! Result(calculatePiFor(start、nrOfElements))//作業を実行 } }
ご覧のとおり、
Work
メッセージハンドラーを追加しました。これは、
calculatePiFor
操作の完了後に
Result
応答メッセージを作成し、送信者に送り返します。 次に、
calculatePiFor
を実装し
calculatePiFor
。
def calculatePiFor(開始:Int、nrOfElements:Int):Double = { var acc = 0.0 for(i←start until(start + nrOfElements)) acc + = 4.0 *(1-(i%2)* 2)/(2 * i + 1) acc }
Master
アクターの作成
Master
アクターはもう少し複雑です 彼のコンストラクターでは、
Worker
アクター間の操作の分散を容易にするために循環ルーターが作成されます。
val workerRouter = context.actorOf( 小道具[Worker] .withRouter(RoundRobinRouter(nrOfWorkers))、name = "workerRouter")
ここで、
Master
アクター自身を作成します。 このアクターは、次のパラメーターで作成されます。
- nrOfWorkers-
Worker
アクターの数 - nrOfMessages-操作のチェーンの総数
- nrOfElements-各
Worker
アクターによって計算された1つのチェーン内の操作の数
したがって、次のコードがあります。
クラスマスター(nrOfWorkers:Int、 nrOfMessages:Int、 nrOfElements:Int、 リスナー:ActorRef)Actorを拡張する{ var pi:Double = _ var nrOfResults:Int = _ val start:Long = System.currentTimeMillis val workerRouter = context.actorOf( 小道具[Worker] .withRouter(RoundRobinRouter(nrOfWorkers))、name = "workerRouter") def receive = { //メッセージを処理します... } }
上記のパラメーターに加えて、
Listener
アクターへの参照である
ActorRef
オブジェクトが
Master
アクターに渡されます。 アクター間のメッセージの転送は、常にこのようなリンクを介して実行されることに注意してください。
しかし、それだけではありません。なぜなら メッセージハンドラーは実装しませんでした。これを作成します。
def receive = { 計算⇒ for(i←nrOfMessagesまで0) workerRouter! 作業(i * nrOfElements、nrOfElements) ケース結果(値)⇒ pi + =値 nrOfResults + = 1 if(nrOfResults == nrOfMessages){ //結果をリスナーに送信します リスナー! PiApproximation(pi、duration =(System.currentTimeMillis-start).millis) //このアクターとそのすべての監視対象の子を停止します context.stop(自己) } }
一般に、コードは明確である必要があります。計算が完了し、結果が出力された後、
context.stop(self)
コマンドで
Master
アクターが停止されることに注意してください。
Listener
アクターの作成
このアクターの実装は非常に簡単です。
Master
アクターから
PiApproximation
メッセージを受け取り、結果を出力し、アクターシステムを停止します。
クラスリスナーはアクターを拡張します{ def receive = { ケースPi近似(pi、期間)⇒ println( "\ n \ tPi近似:\ t \ t%s \ n \ t計算時間:\ t%s" .format(pi、期間)) context.system.shutdown() } }
アプリケーションオブジェクトの作成
これで、アプリケーションオブジェクトを記述するだけで、プログラムの準備が整いました。
オブジェクトPiはAppを拡張します{ 計算(nrOfWorkers = 4、nrOfElements = 10000、nrOfMessages = 10000) //アクターとメッセージ... def compute(nrOfWorkers:Int、nrOfElements:Int、nrOfMessages:Int){ // Akkaシステムを作成します val system = ActorSystem( "PiSystem") //結果を作成し、結果を出力します //システムをシャットダウンします val listener = system.actorOf(Props [リスナー]、名前= "リスナー") //マスターを作成します val master = system.actorOf(Props(new Master( nrOfWorkers、nrOfMessages、nrOfElements、listener))、 name = "master") //計算を開始します マスター! 計算する } }
アプリケーションの起動
sbtからアプリケーションを実行する最も簡単な方法。 これを行うには、アプリケーションのあるフォルダーに移動して、
sbt
コマンドを入力します。 次に、次の一連のコマンドを実行します。
c:\temp\pi-calculator>sbt
[info] Loading project definition from C:\temp\pi-calculator\project
[info] Set current project to PI Calculator (in build file:/C:/temp/pi-calculator/)
> compile
[success] Total time: 0 s, completed 20.03.2012 16:33:03
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.1415926435897883
Calculation time: 423 milliseconds
[success] Total time: 1 s, completed 20.03.2012 16:33:25
アクターの数を1に減らすと、結果が変わります。
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.1415926435897883
Calculation time: 1160 milliseconds
[success] Total time: 2 s, completed 20.03.2012 16:35:16
8に増やすと、結果は次のようになります。
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.1415926435897905
Calculation time: 388 milliseconds
[success] Total time: 1 s, completed 20.03.2012 16:36:55
テストが4核機械で実行された場合、結果は予測可能です。 したがって、アクターの数を16に増やしてもパフォーマンスはほとんど向上しません。
> run
[info] Running akka.tutorial.first.scala.Pi
Pi approximation: 3.141592643589789
Calculation time: 372 milliseconds
[success] Total time: 1 s, completed 20.03.2012 16:40:04
Play 2.0に関する投稿は近日中に公開されます。 頑張って