Port issue with remoting

750 views
Skip to first unread message

Bruce

unread,
Apr 10, 2014, 2:26:00 PM4/10/14
to akka...@googlegroups.com
Hi,

I have an issue related to ports when trying to remote (Scala 2.10.4, Akka 2.3.1).  This is stripped down code that doesn't actually do anything remotely itself.  When I set the port to 0 in the application.conf file, it finds a free port and works without throwing an exception, shown here as the result of running lsof -i -n -P  

com.apple 3205 username   10u  IPv4 0xdcc81blahblah      0t0  UDP *:*
java      4739 username   61u  IPv6 0xdcc81blahblah      0t0  TCP 127.0.0.1:57230 (LISTEN)
java      4739 username   63u  IPv6 0xdcc81blahblah      0t0  TCP [::1]:57229->[::1]:57228 (FIN_WAIT_1)
java      4739 username   81u  IPv6 0xdcc81blahblah      0t0  TCP 127.0.0.1:57231 (LISTEN)

If I then manually code the assigned port into my worker code (not included), I can send a message to the master and receive it no problem.  However, when I set the port to 2552, it throws a java.net.BindException: Address already in use.  My question is, why is it throwing this exception when the port wasn't bound prior to running the app?  It appears that the process itself is what's binding the port, as shown in the following.

com.apple 3205 username   10u  IPv4 0xdcc81blahblah      0t0  UDP *:*
java      4772 username   61u  IPv6 0xdcc81blahblah      0t0  TCP 127.0.0.1:2552 (LISTEN)
java      4772 username   63u  IPv6 0xdcc81blahblah      0t0  TCP [::1]:57237->[::1]:57236 (FIN_WAIT_1)

If I try to set the port in the application.conf file to what was previously assigned when setting the port to 0, I get the same behaviour as when I try to set it to 2552.  I get exactly the same behaviour regardless of whether I run this on my MacBook Pro Retina or Linux Server.

The code:

import akka.actor._
import akka.actor.SupervisorStrategy._
import scala.concurrent.duration._
import com.typesafe.config._
import scala.util._
import akka.event.Logging

class RemoteMaster() extends Actor {
   import context.dispatcher

   def receive = {
      case str:String => println("Message is " + str)
      case msg => println("RemoteMaster: Unhandled Message" + msg)
   }
}

object RemoteMaster {
   val config = ConfigFactory.load()
   val system = ActorSystem("system", config)
   val log = Logging(system.eventStream, "blah.remote.main")

   def main(args:Array[String]) {
      val config = ConfigFactory.load()
      val system = ActorSystem("system", config)
      val listener = system.actorOf(Props(new RemoteMaster),"rm")
      system.eventStream.subscribe(listener, classOf[DeadLetter])
      system.actorSelection("akka://system/user/rm") ! "Test"
   }
}

The application.conf:

akka {
  # Akka version, checked against the runtime version of Akka.
  version = "2.3.1"  # for regular use
  # Event handlers to register at boot time (Logging$DefaultLogger logs to STDOUT)
  event-handlers = ["akka.event.slf4j.Slf4jLogger"]
  # Log level used by the configured loggers (see "event-handlers") as soon
  # Options: ERROR, WARNING, INFO, DEBUG
  loglevel = "INFO"
 
  # Log level for the very basic logger activated during AkkaApplication startup
  # Options: ERROR, WARNING, INFO, DEBUG
  stdout-loglevel = "ERROR"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    enabled-transports = ["akka.remote.netty.tcp"]
    netty.tcp {
      hostname = "127.0.0.1"
      port = 2552
#      port = 0
    }
  }
}

Build.scala (ugly as hell):

import sbt._
import sbt.Keys._
import sbtassembly.Plugin._
import AssemblyKeys._
object ProjectBuild extends Build {
  val useConsole = SettingKey[Boolean]("use-console")
  val jvmOptions = Seq("-server","-Xms2g","-Xmx4g")
  lazy val root = Project(
    id = "Remote",
    base = file("."),
    settings = Project.defaultSettings ++ assemblySettings ++ Seq(
      name := "Remote",
      organization := "com.epoch6",
      scalaVersion := "2.10.4",
      scalacOptions ++= Seq( "-deprecation","-feature"),
      // run fork settings
      fork in run := true,
      javaOptions in run := jvmOptions,
      mainClass in (Compile, run) := Some("com.epoch6.remote.RemoteMaster"),
      testOptions += Tests.Setup( cl =>
         cl.loadClass("org.slf4j.LoggerFactory").
         getMethod("getLogger",cl.loadClass("java.lang.String")).
         invoke(null,"ROOT")
      ),
      // akka and atmos settings
      useConsole := false,
      credentials += Credentials(Path.userHome / "atmos.credentials"),
      resolvers += "Typesafe Repo" at "http://repo.typesafe.com/typesafe/releases/",
      resolvers += "Sonatype shapshot repo" at "https://oss.sonatype.org/content/repositories/snapshots/",
      libraryDependencies <++= useConsole { Dependencies.akka },
      ivyXML <<= useConsole { Dependencies.excludes },
      // library dependencies
      libraryDependencies ++= Dependencies.dependencies,
      // Fat jar settings
      jarName in assembly := "Remote.jar",
      test in assembly := {},
      mainClass in assembly := Some("com.epoch6.remote.RemoteMaster")
   )
 )
}
object Dependencies {
  object V {
    val Akka = "2.3.1"
  }
  val akkaSlf4j = "com.typesafe.akka" %% "akka-slf4j" % V.Akka
  val akkaTestkit = "com.typesafe.akka" %% "akka-testkit" % V.Akka
  val akkaActor  =  "com.typesafe.akka" %% "akka-actor" % V.Akka
  val akkaRemote  =  "com.typesafe.akka" %% "akka-remote" % V.Akka
  val akkaCluster  = "com.typesafe.akka" %% "akka-cluster" % V.Akka

  val originalAkka = Seq(akkaSlf4j, akkaTestkit, akkaActor, akkaRemote, akkaCluster)
  val dependencies = Seq(
    "joda-time" % "joda-time" % "1.6.2",
    "org.scalatest" % "scalatest_2.10" % "2.0.M8",
    "org.scalacheck" %% "scalacheck" % "1.10.1" % "test",
    "ch.qos.logback" % "logback-classic" % "1.0.7"
  )
  val normalExcludes = {
    <dependencies>
    </dependencies>
  }
  def akka(atmos: Boolean) = originalAkka
  def excludes(atmos: Boolean) = normalExcludes
}

The output when port set to 0:

sbt run
[info] Loading project definition from /Users/username/projects/Remote/project/project
[info] Loading project definition from /Users/username/projects/Remote/project
[info] Set current project to Remote (in build file:/Users/username/projects/Remote/)
[info] Running com.epoch6.remote.RemoteMaster 
[info] [INFO] [04/10/2014 14:18:51.535] [main] [Remoting] Starting remoting
[info] [INFO] [04/10/2014 14:18:51.691] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://sys...@127.0.0.1:59083]
[info] [INFO] [04/10/2014 14:18:51.692] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://sys...@127.0.0.1:59083]
[info] [INFO] [04/10/2014 14:18:51.718] [main] [Remoting] Starting remoting
[info] [INFO] [04/10/2014 14:18:51.727] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://sys...@127.0.0.1:59084]
[info] [INFO] [04/10/2014 14:18:51.727] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://sys...@127.0.0.1:59084]
[info] Message is Test

The exception thrown when port set to 2552:

[info] Loading project definition from /Users/username/projects/Remote/project/project
[info] Loading project definition from /Users/username/projects/Remote/project
[info] Set current project to Remote (in build file:/Users/username/projects/Remote/)
[info] Running com.epoch6.remote.RemoteMaster 
[info] [INFO] [04/10/2014 14:05:02.449] [main] [Remoting] Starting remoting
[info] [INFO] [04/10/2014 14:05:02.610] [main] [Remoting] Remoting started; listening on addresses :[akka.tcp://sys...@127.0.0.1:2552]
[info] [INFO] [04/10/2014 14:05:02.611] [main] [Remoting] Remoting now listens on addresses: [akka.tcp://sys...@127.0.0.1:2552]
[info] [INFO] [04/10/2014 14:05:02.637] [main] [Remoting] Starting remoting
[error] Exception in thread "main" org.jboss.netty.channel.ChannelException: Failed to bind to: /127.0.0.1:2552
[error] at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:272)
[error] at akka.remote.transport.netty.NettyTransport$$anonfun$listen$1.apply(NettyTransport.scala:392)
[info] [ERROR] [04/10/2014 14:05:02.649] [main] [Remoting] Remoting error: [Startup failed] [
[error] at akka.remote.transport.netty.NettyTransport$$anonfun$listen$1.apply(NettyTransport.scala:389)
[error] at scala.util.Success$$anonfun$map$1.apply(Try.scala:206)
[info] akka.remote.RemoteTransportException: Startup failed
[error] at scala.util.Try$.apply(Try.scala:161)
[info] at akka.remote.Remoting.akka$remote$Remoting$$notifyError(Remoting.scala:128)
[info] at akka.remote.Remoting.start(Remoting.scala:193)
[error] at scala.util.Success.map(Try.scala:206)
[info] at akka.remote.RemoteActorRefProvider.init(RemoteActorRefProvider.scala:184)
[error] at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
[info] at akka.actor.ActorSystemImpl.liftedTree2$1(ActorSystem.scala:617)
[error] at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
[info] at akka.actor.ActorSystemImpl._start$lzycompute(ActorSystem.scala:615)
[error] at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
[info] at akka.actor.ActorSystemImpl._start(ActorSystem.scala:615)
[error] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:67)
[info] at akka.actor.ActorSystemImpl.start(ActorSystem.scala:632)
[error] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:82)
[info] at akka.actor.ActorSystem$.apply(ActorSystem.scala:141)
[error] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:59)
[info] at akka.actor.ActorSystem$.apply(ActorSystem.scala:118)
[error] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:59)
[info] at com.epoch6.remote.RemoteMaster$.main(RemoteMaster.scala:28)
[info] at com.epoch6.remote.RemoteMaster.main(RemoteMaster.scala)
[error] at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
[error] at akka.dispatch.BatchingExecutor$Batch.run(BatchingExecutor.scala:58)
[info] Caused by: org.jboss.netty.channel.ChannelException: Failed to bind to: /127.0.0.1:2552
[error] at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
[info] at org.jboss.netty.bootstrap.ServerBootstrap.bind(ServerBootstrap.java:272)
[error] at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
[info] at akka.remote.transport.netty.NettyTransport$$anonfun$listen$1.apply(NettyTransport.scala:392)
[error] at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
[info] at akka.remote.transport.netty.NettyTransport$$anonfun$listen$1.apply(NettyTransport.scala:389)
[error] at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
[info] at scala.util.Success$$anonfun$map$1.apply(Try.scala:206)
[error] at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
[info] at scala.util.Try$.apply(Try.scala:161)
[error] at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
[info] at scala.util.Success.map(Try.scala:206)
[error] Caused by: java.net.BindException: Address already in use
[info] at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
[error] at sun.nio.ch.Net.bind(Native Method)
[error] at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:124)
[error] at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
[info] at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:235)
[info] at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32)
[error] at org.jboss.netty.channel.socket.nio.NioServerBoss$RegisterTask.run(NioServerBoss.java:193)
[info] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.processBatch$1(BatchingExecutor.scala:67)
[error] at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:372)
[info] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:82)
[error] at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:296)
[info] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:59)
[error] at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42)
[info] at akka.dispatch.BatchingExecutor$Batch$$anonfun$run$1.apply(BatchingExecutor.scala:59)
[error] at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
[info] at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72)
[error] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
[info] at akka.dispatch.BatchingExecutor$Batch.run(BatchingExecutor.scala:58)
[error] at java.lang.Thread.run(Thread.java:695)
[info] at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:41)
[info] at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:393)
[info] at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
[info] at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
[info] at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
[info] at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
[info] Caused by: java.net.BindException: Address already in use
[info] at sun.nio.ch.Net.bind(Native Method)
[info] at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:124)
[info] at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:59)
[info] at org.jboss.netty.channel.socket.nio.NioServerBoss$RegisterTask.run(NioServerBoss.java:193)
[info] at org.jboss.netty.channel.socket.nio.AbstractNioSelector.processTaskQueue(AbstractNioSelector.java:372)
[info] at org.jboss.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:296)
[info] at org.jboss.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42)
[info] at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
[info] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
[info] at java.lang.Thread.run(Thread.java:695)
[info] ]
[info] [INFO] [04/10/2014 14:05:02.655] [system-akka.remote.default-remote-dispatcher-7] [akka://system/system/remoting-terminator] Shutting down remote daemon.
[info] [INFO] [04/10/2014 14:05:02.656] [system-akka.remote.default-remote-dispatcher-7] [akka://system/system/remoting-terminator] Remote daemon shut down; proceeding with flushing remote transports.
[info] [INFO] [04/10/2014 14:05:02.662] [ForkJoinPool-5-worker-15] [Remoting] Remoting shut down
[info] [INFO] [04/10/2014 14:05:02.662] [system-akka.remote.default-remote-dispatcher-6] [akka://system/system/remoting-terminator] Remoting shut down.
Thanks,
Bruce

Roland Kuhn

unread,
Apr 10, 2014, 3:18:11 PM4/10/14
to akka-user
Hi Bruce,

ActorSystem #1

   val log = Logging(system.eventStream, "blah.remote.main")

   def main(args:Array[String]) {
      val config = ConfigFactory.load()
      val system = ActorSystem("system", config)

ActorSystem #2

Using the same configuration they will clash in the way you observe.

Now you might propose that Akka should see this and report it in a more direct fashion, but unfortunately that would require global shared mutable state in the JVM, which is something that we strictly avoid.

Regards,

Roland

--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to akka-user+...@googlegroups.com.
To post to this group, send email to akka...@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.



Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Reactive apps on the JVM.
twitter: @rolandkuhn


Bruce

unread,
Apr 10, 2014, 3:21:44 PM4/10/14
to akka...@googlegroups.com
Beautiful.  Thanks Roland.  I didn't see that I had defined it twice.

Cheers,
Bruce
Reply all
Reply to author
Forward
0 new messages