Recent Changes - Search:

Domov

Predmety

Bakalárska práca

Diplomová práca



-----------------------

PmWiki

pmwiki.org

edit SideBar

NetProgramming

Seminár z programovania v sieťach


Budeme pracovať s AKKOU v SCALE.



NA STIAHNUTIE

Scala a ide založené na eclipse
http://scala-ide.org/

SBT - simple build tool. Zjednoduší nám prácu s knižnicami.
http://www.scala-sbt.org/

Akka knižnice. Nepotrebovali by sme to, keďže máme sbt, ale ťažko by sa písal kód, keď všetko hlási chybu atď... :)
Akka knižnice



ÚVOD


Scala - http://www.scala-lang.org/what-is-scala.html

def sortList(list: List[Int]): List[Int] = list match {
    case Nil => Nil
    case head :: tail => sortList(tail.filter(_ < head)) ::: head :: sortList(tail.filter(_ >= head))
  }


Akka - http://akka.io/





POĎME PROGRAMOVAŤ

Na úvod niečo zo Scaly.

Skúsme jednoduché metódy

def sqr(x:Int) = x*x;
def cube(x:Int) = x*x*x

Čo spraví toto?

def compose(f:Int=>Int,g:Int=>Int):Int=>Int=x=>f(g(x))

"Vytvoríme "compose" z funkcií f a g, dáme vstup int, výstup int a to tak, že x na vstupe sa zobrazí do f(g(x))..."

Skúsme to otestovať...

object Test4 extends App {
  def sqr(x:Int) = x*x;
  def cube(x:Int) = x*x*x
  def compose(f:Int=>Int,g:Int=>Int):Int=>Int=x=>f(g(x))

  val f = compose(sqr, cube)
  println(f(2))

  val a = List(1,2,3,4)
  println(a.map(f))
  println(a.map(cube).map(sqr))
}

Verím, že výsledok je podľa očakávaní. :)

Ešte jeden príklad k tomu divnému zápisu parametrov.

def addA(a:Int, b:Int)=a+b
  def addB(x:Int):Int=>Int = 
    y=>y+x

Obe funkcie robia to isté. Ako ich budeme volať?

object Test6 extends App {
  def addA(a:Int, b:Int)=a+b
  def addB(x:Int):Int=>Int = 
    y=>y+x

  val aa = addA(10,20)
  val bb = addB(10)(20)

  println(aa)
  println(bb)
}

To bolo niečo k Scale, prejdime už aj na Akku.




AKKA V SCALE


Spravíme si prakticky client-server aplikáciu. Najprv spravíme vzdialený server. Bude počúvať na IP 127.0.0.1 a na porte 5150. Na ňom bude aktor, ktorý ak dostane nejakú správu a je to string, tak odpovie správou "Hello from the RemoteActor".

Najprv si usporiadame adresár.

HelloRemote/
|-- build.sbt
|-- src
|-- main

    │   |-- java
    │   |-- resources
    │   │   +-- application.conf
    │   +-- scala
    │       +-- remote    (package, vytvorime z eclipsu)
    │           +-- HelloRemote.scala
    +-- test
        |-- java
        |-- resources
        +-- scala


Vytvoríme application.conf s takýmto obsahom.

# akka 2.1

akka {
  //loglevel = "DEBUG"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
   }
   remote {
     transport = "akka.remote.netty.NettyRemoteTransport"
     //log-sent-messages = on
     //log-received-messages = on
     netty {
       hostname = "127.0.0.1"
       port = 5150
     }
   }
}


Na rade je HelloRemote.scala. Vtvoríme package remote a v ňom Scala app, ktorú nazveme HelloRemote. Potrebujeme pridať 2 jarká kvôli akke: akka-aktor a akka-remote. (To by sme ani nemuseli, sbt sa o to postará, ale asi nechceme bez toho písať kód...) V triede budeme takto vytvárať aktora RemoteActor. Ako ho potom implementujeme?

package remote

import akka.actor._

object HelloRemote extends App  {
  val system = ActorSystem("HelloRemoteSystem")
  val remoteActor = system.actorOf(Props[RemoteActor], name = "RemoteActor")
  remoteActor ! "The RemoteActor is alive"
}

Úplne jednoducho. (Možno akurát tá Scalácka syntax. :) )

class RemoteActor extends Actor {
  def receive = {
    case msg: String =>
        println(s"RemoteActor received message '$msg'")
        sender ! "Hello from the RemoteActor"
  }
}


Celý kód pre túto triedu.

package remote

import akka.actor._

object HelloRemote extends App  {
  val system = ActorSystem("HelloRemoteSystem")
  val remoteActor = system.actorOf(Props[RemoteActor], name = "RemoteActor")
  remoteActor ! "The RemoteActor is alive"
}

class RemoteActor extends Actor {
  def receive = {
    case msg: String =>
        println(s"RemoteActor received message '$msg'")
        sender ! "Hello from the RemoteActor"
  }
}


A napokon ešte build.sbt, konfigurák pre sbt, aby vedelo odkiaľ a aké knižnice ťahať.

name := "HelloRemote"

version := "1.0"

scalaVersion := "2.10.1"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.1.1",
  "com.typesafe.akka" %% "akka-remote" % "2.1.1"
)


Ako to spustíme?

  1. Spustíme príkazový riadok.
  2. cd do projektového priečinka.
  3. start sbt
  4. V sbt zadáme run.

Server beží. (Pokiaľ sme nespravili chybu. :D )




Teraz je na rade klient. Postupujeme rovnakým spôsobom.

Vytvoríme priečinky.

HelloLocal/
|-- build.sbt
|-- src
|-- main

    │   |-- java
    │   |-- resources
    │   │   +-- application.conf
    │   +-- scala
    │       +-- local
    │           +-- Local.scala
    +-- test
        |-- java
        |-- resources
        +-- scala


Nasleduje napríklad application.conf.

# akka 2.1

akka {
  //loglevel = "DEBUG"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    transport = "akka.remote.netty.NettyRemoteTransport"
    //log-sent-messages = on
    //log-received-messages = on
    netty {
      hostname = "127.0.0.1"
      port = 0
    }
  }
}


Teraz "hlavná" časť - Local.scala. Opäť vytvoríme Scala app, tentoraz s názvom "Local" a v packagi local. Tam si vytvoríme aktora a pustíme ho. (Nezabudnime na jarká pokiaľ nechceme vidieť milión errorov.)

package local

import akka.actor._

object Local extends App {

  implicit val system = ActorSystem("LocalSystem")
  val localActor = system.actorOf(Props[LocalActor], name = "LocalActor")  // the local actor
  localActor ! "START"                                                     // start the action

}

Rovnako ho nasledovne implementujeme. Chceme, aby tento aktor poslal vzdialenému serveru správu "Hello from the LocalActor" a tiež aby 5-krát odzdravil správou "Hello back to you".

class LocalActor extends Actor {

  // create the remote actor (Akka 2.1 syntax)
  val remote = context.actorFor("akka://HelloRemoteSystem@127.0.0.1:5150/user/RemoteActor")
  var counter = 0

  def receive = {
    case "START" =>
        remote ! "Hello from the LocalActor"
    case msg: String =>
        println(s"LocalActor received message: '$msg'")
        if (counter < 5) {
            sender ! "Hello back to you"
            counter += 1
        }
  }
}

Celý kód pre Local.scala.

package local

import akka.actor._

object Local extends App {

  implicit val system = ActorSystem("LocalSystem")
  val localActor = system.actorOf(Props[LocalActor], name = "LocalActor")  // the local actor
  localActor ! "START"                                                     // start the action

}

class LocalActor extends Actor {

  // create the remote actor (Akka 2.1 syntax)
  val remote = context.actorFor("akka://HelloRemoteSystem@127.0.0.1:5150/user/RemoteActor")
  var counter = 0

  def receive = {
    case "START" =>
        remote ! "Hello from the LocalActor"
    case msg: String =>
        println(s"LocalActor received message: '$msg'")
        if (counter < 5) {
            sender ! "Hello back to you"
            counter += 1
        }
  }
}


Napokon build.sbt.

name := "HelloLocal"

version := "1.0"

scalaVersion := "2.10.1"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.1.1",
  "com.typesafe.akka" %% "akka-remote" % "2.1.1"
)

A spustíme, najprv server a potom rovnako klienta z druhej konzoly (!).



ROZŠÍRENIE O UKONČENIE KOMUNIKÁCIE


Skúsme našu aplikáciu ešte vylepšiť a to tak, že po 5 pozdraveniach ukončíme lokálneho aktora a dáme vedieť vzdialenému aktorovi o tom, že končíme. Ten napíše, že na neho pripojený aktor sa odpojil.





Zdroje:
http://doc.akka.io/docs/akka/snapshot/scala/actors.html

http://alvinalexander.com/scala/simple-akka-actors-remote-example

http://alvinalexander.com/scala/akka-remote-sending-objects-messages

Edit - History - Print - Recent Changes - Search
Page last modified on October 26, 2015, at 12:34 AM