2012-03-05 83 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