├── sigar
├── sigar-x86-winnt.dll
├── sigar-x86-winnt.lib
├── libsigar-ia64-linux.so
├── libsigar-pa-hpux-11.sl
├── libsigar-ppc-aix-5.so
├── libsigar-ppc-linux.so
├── libsigar-x86-linux.so
├── sigar-amd64-winnt.dll
├── libsigar-amd64-linux.so
├── libsigar-ia64-hpux-11.sl
├── libsigar-ppc64-aix-5.so
├── libsigar-ppc64-linux.so
├── libsigar-s390x-linux.so
├── libsigar-x86-solaris.so
├── libsigar-amd64-freebsd-6.so
├── libsigar-amd64-solaris.so
├── libsigar-sparc-solaris.so
├── libsigar-sparc64-solaris.so
├── libsigar-x86-freebsd-5.so
├── libsigar-x86-freebsd-6.so
├── libsigar-universal-macosx.dylib
└── libsigar-universal64-macosx.dylib
├── project
├── plugins.sbt
└── build.properties
├── activator.properties
├── .gitignore
├── src
├── main
│ ├── scala
│ │ └── com
│ │ │ └── boldradius
│ │ │ ├── sample
│ │ │ └── cluster
│ │ │ │ ├── SampleClusterApp.scala
│ │ │ │ ├── SampleClusterDefs.scala
│ │ │ │ ├── SampleClusterHttpRoute.scala
│ │ │ │ ├── SampleClusterFrontend.scala
│ │ │ │ └── SampleClusterBackend.scala
│ │ │ └── util
│ │ │ └── Json4sSupport.scala
│ └── resources
│ │ └── application.conf
└── test
│ └── scala
│ └── com
│ └── boldradius
│ └── sample
│ └── cluster
│ ├── HttpRouteSpec.scala
│ └── FrontendSpec.scala
├── tutorial
└── index.html
└── LICENSE
/sigar/sigar-x86-winnt.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/sigar-x86-winnt.dll
--------------------------------------------------------------------------------
/sigar/sigar-x86-winnt.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/sigar-x86-winnt.lib
--------------------------------------------------------------------------------
/sigar/libsigar-ia64-linux.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-ia64-linux.so
--------------------------------------------------------------------------------
/sigar/libsigar-pa-hpux-11.sl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-pa-hpux-11.sl
--------------------------------------------------------------------------------
/sigar/libsigar-ppc-aix-5.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-ppc-aix-5.so
--------------------------------------------------------------------------------
/sigar/libsigar-ppc-linux.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-ppc-linux.so
--------------------------------------------------------------------------------
/sigar/libsigar-x86-linux.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-x86-linux.so
--------------------------------------------------------------------------------
/sigar/sigar-amd64-winnt.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/sigar-amd64-winnt.dll
--------------------------------------------------------------------------------
/sigar/libsigar-amd64-linux.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-amd64-linux.so
--------------------------------------------------------------------------------
/sigar/libsigar-ia64-hpux-11.sl:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-ia64-hpux-11.sl
--------------------------------------------------------------------------------
/sigar/libsigar-ppc64-aix-5.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-ppc64-aix-5.so
--------------------------------------------------------------------------------
/sigar/libsigar-ppc64-linux.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-ppc64-linux.so
--------------------------------------------------------------------------------
/sigar/libsigar-s390x-linux.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-s390x-linux.so
--------------------------------------------------------------------------------
/sigar/libsigar-x86-solaris.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-x86-solaris.so
--------------------------------------------------------------------------------
/sigar/libsigar-amd64-freebsd-6.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-amd64-freebsd-6.so
--------------------------------------------------------------------------------
/sigar/libsigar-amd64-solaris.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-amd64-solaris.so
--------------------------------------------------------------------------------
/sigar/libsigar-sparc-solaris.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-sparc-solaris.so
--------------------------------------------------------------------------------
/sigar/libsigar-sparc64-solaris.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-sparc64-solaris.so
--------------------------------------------------------------------------------
/sigar/libsigar-x86-freebsd-5.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-x86-freebsd-5.so
--------------------------------------------------------------------------------
/sigar/libsigar-x86-freebsd-6.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-x86-freebsd-6.so
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 |
2 | resolvers += Classpaths.typesafeResolver
3 |
4 | addSbtPlugin("org.scala-sbt.plugins" % "sbt-onejar" % "0.8")
5 |
--------------------------------------------------------------------------------
/sigar/libsigar-universal-macosx.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-universal-macosx.dylib
--------------------------------------------------------------------------------
/sigar/libsigar-universal64-macosx.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/boldradius/akka-adaptive-cluster-aws/HEAD/sigar/libsigar-universal64-macosx.dylib
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | #Activator-generated Properties
2 | #Wed Dec 17 14:53:53 UTC 2014
3 | template.uuid=7193124a-3994-4b10-8b01-a17f75ed2ea4
4 | sbt.version=0.13.1
5 |
--------------------------------------------------------------------------------
/activator.properties:
--------------------------------------------------------------------------------
1 | name=akka-http-adaptive-cluster-aws
2 | title=Akka cluster with adaptive group strategy
3 | description=A seed microservice with Akka 'adaptive group' cluster and instructions for AWS configuration.
4 | tags=akka-http,akka,cluster,microservice,starter,seed,scala,cake,pattern
5 | authorTwitter=boldradius
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 | *.log
3 | *.classpath
4 | *.cache
5 | *.project
6 | *.settings
7 | # sbt specific
8 | .cache/
9 | .history/
10 | .lib/
11 | .idea/
12 | dist/*
13 | target/
14 | lib_managed/
15 | src_managed/
16 | project/boot/
17 | project/plugins/project/
18 |
19 | # Scala-IDE specific
20 | .scala_dependencies
21 | .worksheet
22 | *.sc
23 |
--------------------------------------------------------------------------------
/src/main/scala/com/boldradius/sample/cluster/SampleClusterApp.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.sample.cluster
2 |
3 | import com.typesafe.config.ConfigFactory
4 |
5 | object SampleClusterApp {
6 | def main(args: Array[String]): Unit = {
7 |
8 | // starting 3 backend nodes and 1 frontend node
9 | SampleClusterBackend.main(Seq("2551").toArray)
10 | SampleClusterBackend.main(Seq("2552").toArray)
11 | SampleClusterBackend.main(Array.empty)
12 | SampleClusterFrontend.main(Array.empty)
13 | }
14 |
15 | }
--------------------------------------------------------------------------------
/tutorial/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Introduction
4 | A seed 'one action' microservice using akka-http, akka cluster with adaptive-group strategy along with link to instructions how to install, configure and run the cluster on AWS instances.
5 |
6 |
23 |
24 |
--------------------------------------------------------------------------------
/src/main/scala/com/boldradius/sample/cluster/SampleClusterDefs.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.sample.cluster
2 |
3 | import scala.language.implicitConversions
4 |
5 | object SampleClusterDefs {
6 |
7 | case class GetActorMetrics()
8 |
9 | trait MetricsT
10 | case class NoMetricsPresent() extends MetricsT
11 | case class Metrics(address: String, timestamp: Long, cpu: Double) extends MetricsT
12 |
13 | case class SimpleClusterResponse(status: String, details: ResponseDetails)
14 |
15 | sealed trait ResponseDetails
16 | case class MetricsDetails(metrics: MetricsT) extends ResponseDetails
17 | implicit def Metrics2ResponseDetails(metrics: MetricsT) = MetricsDetails(metrics)
18 | case class ErrorDetails(message: String) extends ResponseDetails
19 | implicit def Throwable2ResponseDetails(error: Throwable) = ErrorDetails(error.getMessage())
20 |
21 | val ActorSystemName = "ClusterSystem"
22 | val FrontendActorName = "sampleClusterFrontend"
23 | val FrontendActorRoleName = "frontend"
24 | val BackendRouterName = "sampleClusterBackendRouter"
25 | val BackendActorName = "sampleClusterBackend"
26 | val BackendActorRoleName = "backend"
27 | }
--------------------------------------------------------------------------------
/src/main/scala/com/boldradius/sample/cluster/SampleClusterHttpRoute.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.sample.cluster
2 |
3 | import akka.http.marshalling._
4 | import akka.http.model._
5 | import akka.http.server.Directives._
6 | import akka.http.server.Route
7 | import akka.stream.FlowMaterializer
8 | import akka.util.Timeout
9 | import akka.pattern.ask
10 | import scala.concurrent.ExecutionContext.Implicits.global
11 | import scala.concurrent.duration._
12 | import scala.language.postfixOps
13 | import akka.actor.ActorRef
14 | import SampleClusterDefs._
15 | import akka.cluster.NodeMetrics
16 | import scala.util.Success
17 | import scala.util.Failure
18 | import com.boldradius.util.Json4sSupport
19 |
20 | trait SampleClusterHttpRoute extends Json4sSupport {
21 |
22 | implicit val timeout = Timeout(3 seconds)
23 |
24 | def route(frontendActor: ActorRef)(implicit fm: FlowMaterializer): Route = {
25 |
26 | get {
27 | path("cluster") {
28 | onComplete((frontendActor ? GetActorMetrics()).mapTo[MetricsT]) {
29 | case Success(metrics) =>
30 | complete(SimpleClusterResponse("success", metrics))
31 | case Failure(f) =>
32 | complete(SimpleClusterResponse("error", f))
33 | }
34 | }
35 | }
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/src/main/resources/application.conf:
--------------------------------------------------------------------------------
1 |
2 | akka {
3 | actor {
4 | provider = "akka.cluster.ClusterActorRefProvider"
5 | }
6 | remote {
7 | log-remote-lifecycle-events = off
8 | netty.tcp {
9 | hostname = "127.0.0.1"
10 | port = 0
11 | }
12 | }
13 |
14 | cluster {
15 | seed-nodes = [
16 | "akka.tcp://ClusterSystem@127.0.0.1:2551",
17 | "akka.tcp://ClusterSystem@127.0.0.1:2552"]
18 |
19 | auto-down-unreachable-after = 10s
20 | }
21 | }
22 |
23 | # //#min-nr-of-members
24 | akka.cluster.min-nr-of-members = 3
25 | # //#min-nr-of-members
26 |
27 | # //#role-min-nr-of-members
28 | akka.cluster.role {
29 | frontend.min-nr-of-members = 1
30 | backend.min-nr-of-members = 2
31 | }
32 | # //#role-min-nr-of-members
33 |
34 | # //#adaptive-router
35 | akka.actor.deployment {
36 | /sampleClusterFrontend/sampleClusterBackendRouter = {
37 | router = adaptive-group
38 | # metrics-selector = heap
39 | # metrics-selector = load
40 | # metrics-selector = cpu
41 | metrics-selector = mix
42 | nr-of-instances = 100
43 | routees.paths = ["/user/sampleClusterBackend"]
44 | cluster {
45 | enabled = on
46 | use-role = backend
47 | allow-local-routees = off
48 | }
49 | }
50 | }
51 | # //#adaptive-router
52 |
--------------------------------------------------------------------------------
/src/test/scala/com/boldradius/sample/cluster/HttpRouteSpec.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.sample.cluster
2 |
3 | import org.junit.runner.RunWith
4 | import org.scalatest.junit.JUnitRunner
5 | import akka.actor.{ Actor, ActorRef, Props }
6 | import akka.http.model._
7 | import akka.http.testkit._
8 | import org.scalatest._
9 | import scala.concurrent.duration._
10 | import SampleClusterDefs._
11 | import akka.cluster.NodeMetrics
12 | import akka.actor.Address
13 | import akka.testkit.TestActorRef
14 |
15 | @RunWith(classOf[JUnitRunner])
16 | class HttpRouteSpec extends FlatSpecLike
17 | with ScalatestRouteTest
18 | with MustMatchers
19 | with BeforeAndAfterAll
20 | with SampleClusterHttpRoute {
21 |
22 | override def afterAll() {
23 | system.shutdown()
24 | }
25 |
26 | /* Should be set!
27 | ** Otherwise returns:
28 | ** 'Request was neither completed nor rejected within 1 second'.
29 | */
30 | implicit val routeTestTimeout = RouteTestTimeout(5.second)
31 |
32 | trait TestFrontend {
33 | val testResp = Metrics(address = "test", timestamp = 1L, cpu = 0.1)
34 | val testFrontendActor = TestActorRef(Props(new Actor {
35 | def receive = {
36 | case c: GetActorMetrics => sender() ! testResp
37 | }
38 | }))
39 | }
40 |
41 | "/cluster " should "return metrics" in new TestFrontend {
42 |
43 | Get(Uri("/cluster")) ~> route(testFrontendActor) ~> check {
44 |
45 | responseAs[Any] must be(Map("status" -> "success", "details" -> Map("metrics" -> Map("address" -> "test", "timestamp" -> 1, "cpu" -> 0.1))))
46 | }
47 |
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/test/scala/com/boldradius/sample/cluster/FrontendSpec.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.sample.cluster
2 |
3 | import org.junit.runner.RunWith
4 | import org.scalatest.junit.JUnitRunner
5 | import org.scalatest.BeforeAndAfterAll
6 | import org.scalatest.FlatSpec
7 | import org.scalatest.Matchers
8 | import akka.testkit.TestActorRef
9 | import akka.testkit.TestKit
10 | import akka.actor.ActorSystem
11 | import org.scalatest.FlatSpecLike
12 | import akka.pattern.ask
13 | import scala.concurrent.duration._
14 | import akka.util.Timeout
15 | import scala.util.Success
16 | import scala.util.Failure
17 | import akka.actor.Props
18 | import akka.actor.ActorContext
19 | import akka.testkit.TestProbe
20 | import akka.actor.ActorRef
21 | import akka.actor.Actor
22 | import SampleClusterDefs._
23 |
24 | @RunWith(classOf[JUnitRunner])
25 | class FrontendSpec
26 | extends TestKit(ActorSystem("TestSystem"))
27 | with FlatSpecLike
28 | with Matchers
29 | with BeforeAndAfterAll {
30 |
31 | override def afterAll() {
32 | system.shutdown()
33 | }
34 |
35 | class TestSampleClusterBackend(target: ActorRef) extends Actor {
36 | def receive = {
37 | case c: GetActorMetrics => target forward c
38 | }
39 | }
40 |
41 | trait TestBackend {
42 | val backendProbe = TestProbe()
43 | trait BackendRouterProviderTest extends BackendRouterProvider {
44 | def newBackendRouter(context: ActorContext) = context.actorOf(Props(new TestSampleClusterBackend(backendProbe.ref)))
45 | }
46 | }
47 |
48 | "GetActorMetrics message on frontend " should "triggers GetActorMetrics message on backend" in new TestBackend {
49 |
50 | val frontend = TestActorRef(Props(new SampleClusterFrontend with BackendRouterProviderTest))
51 |
52 | frontend ! GetActorMetrics()
53 |
54 | backendProbe.expectMsg(GetActorMetrics())
55 |
56 | }
57 | }
--------------------------------------------------------------------------------
/src/main/scala/com/boldradius/util/Json4sSupport.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.util
2 |
3 |
4 | import akka.http.marshalling._
5 | import akka.http.model._
6 | import akka.http.unmarshalling._
7 | import akka.stream.FlowMaterializer
8 | import org.json4s._
9 | import org.json4s.native.Serialization
10 | import org.json4s.native.Serialization.{read, write}
11 | import scala.language.implicitConversions
12 |
13 | import scala.concurrent.{Future, ExecutionContext}
14 | import scala.concurrent.duration._
15 |
16 | trait Json4sSupport {
17 |
18 | implicit val formats = DefaultFormats
19 | implicit val formatsNative = Serialization.formats(NoTypeHints)
20 |
21 | implicit def json4sFromRequestUnmarshaller[T:Manifest](implicit fm:FlowMaterializer, ex:ExecutionContext):FromRequestUnmarshaller[T] =
22 | new Unmarshaller[HttpRequest,T] {
23 | def apply(req: HttpRequest): Future[T] = {
24 | req.entity.withContentType(ContentTypes.`application/json`).toStrict(5.second)
25 | .map(_.data.toArray).map(x => read[T](new String(x)))
26 | }
27 | }
28 |
29 | implicit def json4sFromResponseUnmarshaller[T:Manifest](implicit fm:FlowMaterializer, ex:ExecutionContext):FromResponseUnmarshaller[T] =
30 | new Unmarshaller[HttpResponse,T] {
31 | def apply(res: HttpResponse): Future[T] = {
32 | res.entity.withContentType(ContentTypes.`application/json`)
33 | .toStrict(5.second).map(_.data.toArray)
34 | .map(x => read[T](new String(x)))
35 | }
36 | }
37 |
38 | implicit def json4sToEntityMarshaller[T <: AnyRef]:ToEntityMarshaller[T] =
39 | Marshaller.withFixedCharset[T, MessageEntity](MediaTypes.`application/json`,HttpCharset.custom("*"))( tp =>
40 | HttpEntity(write[T](tp)))
41 |
42 |
43 | implicit def json4sToHttpEntityMarshaller[T <: AnyRef](t:T):ResponseEntity = HttpEntity(MediaTypes.`application/json`, write[T](t))
44 |
45 |
46 |
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/scala/com/boldradius/sample/cluster/SampleClusterFrontend.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.sample.cluster
2 |
3 | import scala.concurrent.duration._
4 | import com.typesafe.config.ConfigFactory
5 | import akka.actor.Actor
6 | import akka.actor.ActorLogging
7 | import akka.actor.ActorSystem
8 | import akka.actor.Props
9 | import akka.routing.FromConfig
10 | import akka.actor.ReceiveTimeout
11 | import akka.http.Http
12 | import akka.http.server.Directives._
13 | import akka.stream.FlowMaterializer
14 | import scala.concurrent.ExecutionContext.Implicits.global
15 | import akka.util.Timeout
16 | import akka.actor.ActorRef
17 | import akka.actor.ActorContext
18 | import akka.cluster.Cluster
19 | import scala.language.postfixOps
20 | import SampleClusterDefs._
21 |
22 | trait BackendRouterProvider {
23 | def newBackendRouter(context: ActorContext): ActorRef
24 | }
25 |
26 | trait BackendRouterProviderImpl extends BackendRouterProvider {
27 | def newBackendRouter(context: ActorContext) = context.actorOf(FromConfig.props(), name = BackendRouterName)
28 | }
29 |
30 | class SampleClusterFrontend() extends Actor with ActorLogging {
31 |
32 | this: BackendRouterProvider =>
33 |
34 | implicit val timeout = Timeout(5 seconds)
35 |
36 | val backendRouter = newBackendRouter(context)
37 |
38 | def receive = {
39 | case c: GetActorMetrics =>
40 | backendRouter.forward(c)
41 | case ReceiveTimeout =>
42 | log.info("Timeout")
43 | }
44 | }
45 |
46 | object SampleClusterFrontend extends SampleClusterHttpRoute {
47 | def main(args: Array[String]): Unit = {
48 |
49 | val host = if (args.isEmpty) "localhost" else args(0)
50 | val port = if (args.isEmpty || args.length == 1) 8080 else args(1).toInt
51 |
52 | val config = ConfigFactory.parseString(s"akka.cluster.roles = [$FrontendActorRoleName]")
53 | .withFallback(ConfigFactory.load("application"))
54 |
55 | implicit val system = ActorSystem(ActorSystemName, config)
56 | system.log.info("Sample Cluster System will start when there is a minimum number of backend members in the cluster.")
57 |
58 | Cluster(system) registerOnMemberUp {
59 | val frontEnd = system.actorOf(Props(new SampleClusterFrontend with BackendRouterProviderImpl), name = FrontendActorName)
60 | implicit val materializer = FlowMaterializer()
61 | Http().bind(host, port) startHandlingWith {
62 | logRequestResult("A") {
63 | route(frontEnd)
64 | }
65 | }
66 |
67 | }
68 |
69 | }
70 | }
--------------------------------------------------------------------------------
/src/main/scala/com/boldradius/sample/cluster/SampleClusterBackend.scala:
--------------------------------------------------------------------------------
1 | package com.boldradius.sample.cluster
2 |
3 | import scala.concurrent.Future
4 | import com.typesafe.config.ConfigFactory
5 | import akka.actor.Actor
6 | import akka.actor.ActorLogging
7 | import akka.actor.ActorSystem
8 | import akka.actor.Props
9 | import scala.util.Success
10 | import scala.util.Failure
11 | import akka.pattern.pipe
12 | import akka.cluster.Cluster
13 | import akka.cluster.ClusterEvent.ClusterMetricsChanged
14 | import akka.cluster.ClusterEvent.CurrentClusterState
15 | import akka.cluster.NodeMetrics
16 | import SampleClusterDefs._
17 |
18 | class SampleClusterBackend extends Actor with ActorLogging {
19 |
20 | val selfAddress = Cluster(context.system).selfAddress
21 |
22 | override def preStart(): Unit =
23 | Cluster(context.system).subscribe(self, classOf[ClusterMetricsChanged])
24 | override def postStop(): Unit =
25 | Cluster(context.system).unsubscribe(self)
26 |
27 |
28 | def receiveWithMetricsAvailable(nodeMetrics: NodeMetrics): Receive = {
29 | case c: GetActorMetrics =>
30 | sender() ! Metrics(address = nodeMetrics.address.toString, timestamp = nodeMetrics.timestamp, cpu = nodeMetrics.metric("cpu-combined").map(_.value.doubleValue()).getOrElse(-1.0))
31 | case ClusterMetricsChanged(clusterMetrics) =>
32 | clusterMetrics.filter(_.address == selfAddress) foreach { newNodeMetrics =>
33 | context.become(receiveWithMetricsAvailable(newNodeMetrics))
34 | }
35 | case state: CurrentClusterState => // ignore
36 | }
37 |
38 | def receive = {
39 | case c: GetActorMetrics => // didn't get first metrics
40 | sender() ! NoMetricsPresent
41 | case ClusterMetricsChanged(clusterMetrics) =>
42 | clusterMetrics.filter(_.address == selfAddress) foreach { newNodeMetrics =>
43 | context.become(receiveWithMetricsAvailable(newNodeMetrics))
44 | }
45 | case state: CurrentClusterState => // ignore
46 | }
47 | }
48 |
49 | object SampleClusterBackend {
50 | def main(args: Array[String]): Unit = {
51 | val port = if (args.isEmpty) "0" else args(0)
52 | val config = ConfigFactory.parseString(s"akka.remote.netty.tcp.port=$port").
53 | withFallback(ConfigFactory.parseString(s"akka.cluster.roles = [$BackendActorRoleName]"))
54 | .withFallback(ConfigFactory.load("application"))
55 |
56 | val system = ActorSystem(ActorSystemName, config)
57 | system.actorOf(Props(classOf[SampleClusterBackend]), name = BackendActorName)
58 | }
59 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
--------------------------------------------------------------------------------