我正在学习Akka(2.0-M4)并试图理解remote actor deployment/creation的概念。Akka远程部署误解?
我假定远程部署通过在网络上发送actor代码然后在微内核上运行它来工作。这是正确的吗?
我问,因为我无法做到这一点。如果我下载示例here,则演员CreationApp可以工作,但前提是适当的jar放在微内核的lib目录中。否则,我会得到一个ClassNotFoundException。
我误解了远程演员的创作?
我正在学习Akka(2.0-M4)并试图理解remote actor deployment/creation的概念。Akka远程部署误解?
我假定远程部署通过在网络上发送actor代码然后在微内核上运行它来工作。这是正确的吗?
我问,因为我无法做到这一点。如果我下载示例here,则演员CreationApp可以工作,但前提是适当的jar放在微内核的lib目录中。否则,我会得到一个ClassNotFoundException。
我误解了远程演员的创作?
我觉得你误会了。远程部署将创建转发到远程计算机,但创建的Actor位于本地计算机上的ActorSystem内(用于所有意图和目的)。如果代码不在远程机器上,那么你的运气不好。
与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)
}
有趣,但是surley有很多安全问题?来电者如何进行身份验证? – 2014-05-01 09:11:18
是,阿卡不假装做远程类加载发送到RegistryActor在远程侧。 – 2012-03-05 23:42:04
换句话说,我仍然必须将二进制文件复制到远程计算机上,在PRIOR之前部署演员,对吧? – himekami 2015-08-10 21:17:41