Clusters and Policies
Now let’s bring the concept of the “cluster” back in.
We could wrap our appserver in the same DynamicCluster
we used earlier,
although then we’d need to define and configure the load balancer.
But another blueprint, the ControlledDynamicWebAppCluster
, does this for us.
It takes the same memberSpec
, so we can build a fully functional elastic 3-tier
deployment of our hello-world-sql
application as follows:
name: appserver-clustered-w-db
services:
- type: brooklyn.entity.webapp.ControlledDynamicWebAppCluster
initialSize: 2
memberSpec:
$brooklyn:entitySpec:
type: brooklyn.entity.webapp.jboss.JBoss7Server
brooklyn.config:
wars.root: http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.6.0/brooklyn-example-hello-world-sql-webapp-0.6.0.war
http.port: 8080+
java.sysprops:
brooklyn.example.db.url: $brooklyn:formatString("jdbc:%s%s?user=%s\\&password=%s",
component("db").attributeWhenReady("datastore.url"), "visitors", "brooklyn", "br00k11n")
- type: brooklyn.entity.database.mysql.MySqlNode
id: db
name: DB HelloWorld Visitors
brooklyn.config:
datastore.creation.script.url: https://github.com/apache/incubator-brooklyn/raw/master/usage/launcher/src/test/resources/visitors-creation-script.sql
This sets up Nginx as the controller by default, but that can be configured
using the controllerSpec
key. In fact, JBoss is the default appserver,
and because configuration in Brooklyn is inherited by default,
the same blueprint can be expressed more concisely as:
name: appserver-clustered-w-db-concise
services:
- type: brooklyn.entity.webapp.ControlledDynamicWebAppCluster
initialSize: 2
brooklyn.config:
wars.root: http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.6.0/brooklyn-example-hello-world-sql-webapp-0.6.0.war
http.port: 8080+
java.sysprops:
brooklyn.example.db.url: $brooklyn:formatString("jdbc:%s%s?user=%s\\&password=%s",
component("db").attributeWhenReady("datastore.url"), "visitors", "brooklyn", "br00k11n")
- type: brooklyn.entity.database.mysql.MySqlNode
id: db
name: DB HelloWorld Visitors
brooklyn.config:
datastore.creation.script.url: https://github.com/apache/incubator-brooklyn/raw/master/usage/launcher/src/test/resources/visitors-creation-script.sql
The other nicety supplied by the ControlledDynamicWebAppCluster
blueprint is that
it aggregates sensors from the appserver, so we have access to things like
webapp.reqs.perSec.windowed.perNode
.
These are convenient for plugging in to policies!
We can set up our blueprint to do autoscaling based on requests per second
(keeping it in the range 10..100, with a maximum of 5 appserver nodes)
as follows:
name: appserver-w-policy
services:
- type: brooklyn.entity.webapp.ControlledDynamicWebAppCluster
initialSize: 1
memberSpec:
$brooklyn:entitySpec:
type: brooklyn.entity.webapp.jboss.JBoss7Server
brooklyn.config:
wars.root: http://search.maven.org/remotecontent?filepath=io/brooklyn/example/brooklyn-example-hello-world-sql-webapp/0.6.0/brooklyn-example-hello-world-sql-webapp-0.6.0.war
http.port: 8080+
java.sysprops:
brooklyn.example.db.url: $brooklyn:formatString("jdbc:%s%s?user=%s\\&password=%s",
component("db").attributeWhenReady("datastore.url"), "visitors", "brooklyn", "br00k11n")
brooklyn.policies:
- policyType: brooklyn.policy.autoscaling.AutoScalerPolicy
brooklyn.config:
metric: $brooklyn:sensor("brooklyn.entity.webapp.DynamicWebAppCluster", "webapp.reqs.perSec.windowed.perNode")
metricLowerBound: 10
metricUpperBound: 100
minPoolSize: 1
maxPoolSize: 5
- type: brooklyn.entity.database.mysql.MySqlNode
id: db
name: DB HelloWorld Visitors
brooklyn.config:
datastore.creation.script.url: https://github.com/apache/incubator-brooklyn/raw/master/usage/launcher/src/test/resources/visitors-creation-script.sql
Use your favorite load-generation tool (jmeter
is one good example) to send a huge
volume of requests against the server and see the policies kick in to resize it.