2012-03-05 79 views
1

我正在學習Akka(2.0-M4)並試圖理解remote actor deployment/creation的概念。Akka遠程部署誤解?

我假定遠程部署通過在網絡上發送actor代碼然後在微內核上運行它來工作。這是正確的嗎?

我問,因爲我無法做到這一點。如果我下載示例here,則演員CreationApp可以工作,但前提是適當的jar放在微內核的lib目錄中。否則,我會得到一個ClassNotFoundException。

我誤解了遠程演員的創作?

回答

10

我覺得你誤會了。遠程部署將創建轉發到遠程計算機,但創建的Actor位於本地計算機上的ActorSystem內(用於所有意圖和目的)。如果代碼不在遠程機器上,那麼你的運氣不好。

+0

是,阿卡不假裝做遠程類加載發送到RegistryActor在遠程側。 – 2012-03-05 23:42:04

+0

換句話說,我仍然必須將二進制文件複製到遠程計算機上,在PRIOR之前部署演員,對吧? – himekami 2015-08-10 21:17:41

4

與RMI相比,沒有內置機制將類代碼發送到遠程機器 。但阿卡讓你很容易做到這一點。

的ActorSystem可以與能夠加載必要的類類加載器來創建:

val system = ActorSystem(
       "TestSystem", 
       ConfigFactory.load(), 
       new ByteClassloader(
         Thread.currentThread().getContextClassLoader())) 

你的類加載器可與接受發送給它的類演員合作:

import akka.actor.Actor 

// messages with classcode 
case class RegisterRemoteMsg(name: String, clazzB: Array[Byte]) 

class RegistryActor extends Actor { 
    def receive = { 
    case RegisterRemoteMsg(name, bytes) => 
     ByteClassLoader.register(name, bytes) 
    } 
} 

該角色商店類在地圖中,類加載器從地圖中檢索類:

import java.net.URLClassLoader 
import java.net.URL 

class ByteArrayClassloader(parent: ClassLoader) extends URLClassLoader(Array[URL](), parent) { 
    import ByteClassLoader._ 
    override 
    protected def findClass(name: String) : Class[_] = { 
    var result = findLoadedClass(name); 
    if (result == null) { 
     try { 
      result = findSystemClass(name); 
     } catch { 
      case e: /* ignore */ 
     } 
    } 
    if (result == null) { 
     try { 
      val classBytes = registeredClasses(name) 
      result = defineClass(name, classBytes, 0, classBytes.length); 
     } catch { 
      case e: Exception => { 
      throw new ClassNotFoundException(name); 
      } 
     } 
    } 
    result; 
    }  
} 
object ByteClassLoader { 
    var registeredClasses : Map[String, Array[Byte]] = Map() 
    def register(name : String, classBytes : Array[Byte]) { 
    registeredClasses += (name -> classBytes) 
    } 
} 

請注意,發送端必須發送字節碼 - 不是類對象。 因爲 它們被「鏈接到」發送JVM中,所以類對象(classOf [SomeClass])不可序列化。

類代碼在磁盤上。請注意,一個scala類通常有一些嵌套的 類,它們位於不同的文件中。發送者可以通過找到所有必需的類 :

object LoadClassBytes { 
    def apply(clazz: Class[_]) : Map[String, Array[Byte]] = { 
    val basePath : Path = Paths.get(clazz.getProtectionDomain.getCodeSource.getLocation.toURI) 
    val relName = clazz.getName().replace('.', '/') 
    val fullPath = basePath.resolve(relName) 
    val fileName = fullPath.getFileName() 
    val fileNameHead = (fileName.toString()).split("\\.")(0) 
    val parentDir = fullPath.getParent() 

    var res : Map[String, Array[Byte]] = Map() 
    // find class file and class files of inner classes 
    val ds = Files.newDirectoryStream(
     parentDir, 
     new DirectoryStream.Filter[Path]{ 
      def accept(file: Path) : Boolean = file.getFileName().toString().matches(fileNameHead+"(\\$.+)?\\.class") 
     }) 
    try { 
     val iter = ds.iterator() 
     while (iter.hasNext()) { 
      val p = iter.next() 
      res += (((basePath.relativize(p)).toString().split("\\.")(0).replace('/', '.')) -> Files.readAllBytes(p)) 
     } 
    } finally { 
     ds.close 
    } 
    res 
    } 
} 

,並在RegisterRemoteMsg

val registryActorR = ... retrieve remote registry actor ... 
val classesToBeSent = LoadClassBytes(classOf[SomeClass]) 
for ((name, bytes) <- classesToBeSent) { 
    registryActorR ! RegisterRemoteMsg(name, bytes) 
} 
+0

有趣,但是surley有很多安全問題?來電者如何進行身份驗證? – 2014-05-01 09:11:18