我正在學習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