Fixed issue with shutting down cluster correctly + Improved chat sample README
This commit is contained in:
parent
6b4bceec00
commit
28041ec21c
6 changed files with 55 additions and 27 deletions
|
|
@ -4,7 +4,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>akka-core</artifactId>
|
||||
<name>Akka Actors, Remote Actors, Transactors and STM Module</name>
|
||||
<name>Akka Core - Actors, Remote Actors, Transactors and STM Module</name>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ import org.jboss.netty.handler.codec.compression.{ZlibEncoder, ZlibDecoder}
|
|||
*
|
||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
object RemoteNode extends RemoteServer(true)
|
||||
object RemoteNode extends RemoteServer
|
||||
|
||||
/**
|
||||
* This object holds configuration variables.
|
||||
|
|
@ -88,7 +88,8 @@ object RemoteServer {
|
|||
}
|
||||
|
||||
private val remoteActorSets = new ConcurrentHashMap[Address, RemoteActorSet]
|
||||
|
||||
private val remoteServers = new ConcurrentHashMap[Address, RemoteServer]
|
||||
|
||||
def actorsFor(remoteServerAddress: RemoteServer.Address): RemoteActorSet = {
|
||||
val set = remoteActorSets.get(remoteServerAddress)
|
||||
if (set ne null) set
|
||||
|
|
@ -98,6 +99,20 @@ object RemoteServer {
|
|||
remoteActorSet
|
||||
}
|
||||
}
|
||||
|
||||
def serverFor(hostname: String, port: Int): Option[RemoteServer] = {
|
||||
val server = remoteServers.get(Address(hostname, port))
|
||||
if (server eq null) None
|
||||
else Some(server)
|
||||
}
|
||||
|
||||
private[remote] def register(hostname: String, port: Int, server: RemoteServer) =
|
||||
remoteServers.put(Address(hostname, port), server)
|
||||
|
||||
private[remote] def unregister(hostname: String, port: Int) =
|
||||
remoteServers.remove(Address(hostname, port))
|
||||
|
||||
private[remote] def canShutDownCluster: Boolean = remoteServers.isEmpty
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -116,9 +131,8 @@ object RemoteServer {
|
|||
*
|
||||
* @author <a href="http://jonasboner.com">Jonas Bonér</a>
|
||||
*/
|
||||
class RemoteServer(val registerNodeInCluster: Boolean) extends Logging {
|
||||
class RemoteServer extends Logging {
|
||||
val name = "RemoteServer@" + hostname + ":" + port
|
||||
def this() = this(false)
|
||||
|
||||
private var hostname = RemoteServer.HOSTNAME
|
||||
private var port = RemoteServer.PORT
|
||||
|
|
@ -147,6 +161,7 @@ class RemoteServer(val registerNodeInCluster: Boolean) extends Logging {
|
|||
hostname = _hostname
|
||||
port = _port
|
||||
log.info("Starting remote server at [%s:%s]", hostname, port)
|
||||
RemoteServer.register(hostname, port, this)
|
||||
val remoteActorSet = RemoteServer.actorsFor(RemoteServer.Address(hostname, port))
|
||||
val pipelineFactory = new RemoteServerPipelineFactory(name, openChannels, loader, remoteActorSet.actors, remoteActorSet.activeObjects)
|
||||
bootstrap.setPipelineFactory(pipelineFactory)
|
||||
|
|
@ -156,7 +171,7 @@ class RemoteServer(val registerNodeInCluster: Boolean) extends Logging {
|
|||
bootstrap.setOption("child.connectTimeoutMillis", RemoteServer.CONNECTION_TIMEOUT_MILLIS)
|
||||
openChannels.add(bootstrap.bind(new InetSocketAddress(hostname, port)))
|
||||
isRunning = true
|
||||
if (registerNodeInCluster) Cluster.registerLocalNode(hostname, port)
|
||||
Cluster.registerLocalNode(hostname, port)
|
||||
}
|
||||
} catch {
|
||||
case e => log.error(e, "Could not start up remote server")
|
||||
|
|
@ -164,14 +179,13 @@ class RemoteServer(val registerNodeInCluster: Boolean) extends Logging {
|
|||
}
|
||||
|
||||
def shutdown = {
|
||||
RemoteServer.unregister(hostname, port)
|
||||
openChannels.disconnect
|
||||
openChannels.unbind
|
||||
openChannels.close.awaitUninterruptibly(1000)
|
||||
bootstrap.releaseExternalResources
|
||||
if (registerNodeInCluster) {
|
||||
Cluster.deregisterLocalNode(hostname, port)
|
||||
Cluster.shutdown
|
||||
}
|
||||
Cluster.deregisterLocalNode(hostname, port)
|
||||
if (RemoteServer.canShutDownCluster) Cluster.shutdown
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,28 @@
|
|||
Akka Chat Client/Server Sample Application
|
||||
|
||||
To run the sample:
|
||||
1. Run 'mvn install' (builds and deploys jar to AKKA_HOME/deploy)
|
||||
2. In another shell run 'java -jar ./dist/akka-0.6.jar' to start up Akka microkernel
|
||||
3. In the first shell run 'mvn scala:console -o'
|
||||
4. In the REPL you get execute:
|
||||
- scala> import se.scalablesolutions.akka.sample.chat._
|
||||
- scala> Runner.run
|
||||
5. See the chat simulation run
|
||||
6. Run it again to see full speed after first initialization
|
||||
First we need to download, build and start up Redis:
|
||||
|
||||
1. Download Redis from http://code.google.com/p/redis/downloads/list.
|
||||
2. Step into the distribution.
|
||||
3. Build: ‘make install’.
|
||||
4. Run: ‘./redis-server’.
|
||||
For details on how to set up Redis server have a look at http://code.google.com/p/redis/wiki/QuickStart.
|
||||
|
||||
Then to run the sample:
|
||||
|
||||
1. Set ‘AKKA_HOME’ environment variable to the root of the Akka distribution.
|
||||
2. Open up a shell and step into the Akka distribution root folder.
|
||||
3. Build Akka by invoking ‘mvn install -Dmaven.test.skip=true’. This will also bulid the sample application and deploy it to the ‘$AKKA_HOME/deploy’ directory.
|
||||
4. Run the microkernel
|
||||
export AKKA_HOME=...
|
||||
cd $AKKA_HOME
|
||||
java -jar ./dist/akka-0.6.jar
|
||||
5. Now start up a new shell and go down into the ‘./akka-samples/akka-sample-chat’ directory.
|
||||
6. Invoke ‘mvn scala:console -o’. This will give you a Scala REPL (interpreter) with the chat application and all its dependency JARs on the classpath.
|
||||
7. Simply paste in the whole code block with the ‘Runner’ object above and invoke ‘Runner.run’. This run a simulated client session that will connect to the running server in the microkernel.
|
||||
8. Invoke ‘Runner.run’ again and again…
|
||||
|
||||
Now you could test client reconnect by killing the running microkernel and start it up again. See the client reconnect take place in the REPL shell.
|
||||
|
||||
That’s it. Have fun.
|
||||
|
||||
|
|
|
|||
|
|
@ -187,7 +187,6 @@ object ChatService extends
|
|||
* Test runner emulating a chat session.
|
||||
*/
|
||||
object Runner {
|
||||
|
||||
// create a handle to the remote ChatService
|
||||
ChatService.makeRemote("localhost", 9999)
|
||||
ChatService.start
|
||||
|
|
|
|||
|
|
@ -53,12 +53,12 @@ object Config extends Logging {
|
|||
log.info("Config loaded from the application classpath.")
|
||||
} catch {
|
||||
case e: ParseException => throw new IllegalStateException(
|
||||
"Can't find 'akka.conf' configuration file." +
|
||||
"One of the three ways of locating the 'akka.conf' file needs to be defined:" +
|
||||
"\n\t1. Define '$AKKA_HOME' to the root of the Akka distribution." +
|
||||
"\n\t2. Define the '-Dakka.config=...' environment option." +
|
||||
"\nCan't find 'akka.conf' configuration file." +
|
||||
"\nOne of the three ways of locating the 'akka.conf' file needs to be defined:" +
|
||||
"\n\t1. Define 'AKKA_HOME' environment variable to the root of the Akka distribution." +
|
||||
"\n\t2. Define the '-Dakka.config=...' system property option." +
|
||||
"\n\t3. Put the 'akka.conf' file on the classpath." +
|
||||
"\n\tI have no way of finding the 'akka.conf' configuration file." +
|
||||
"\nI have no way of finding the 'akka.conf' configuration file." +
|
||||
"\nAborting.")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2
pom.xml
2
pom.xml
|
|
@ -508,8 +508,6 @@
|
|||
</plugin>
|
||||
</plugins>
|
||||
</reporting>
|
||||
<distributionManagement>
|
||||
</distributionManagement>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>release</id>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue