Service Discovery: Java, a Database App, and DC/OS
Service discovery is a key part of containerized components. As containers are born and destroyed, your app needs to find the moving parts. See how to do it in DC/OS.
Join the DZone community and get the full member experience.
Join For Freewhy service discovery?
an application typically consists of multiple components, such as an application server, a database, a web server, caching, and a messaging server. typically, multiple replicas of each component would run based upon the needs of your application. deploying this application using a container orchestration framework means that each replica would run as a container. so, an application is typically deployed as a multi-container application.
each container is assigned a unique ip address for its lifetime. but containers are ephemeral and may terminate and be rescheduled on a different host by the orchestration framework. a container is typically assigned a different ip address in that case. this means an application deployed in an application server cannot rely upon the ip address of the database. this is where service discovery is required.
so, multiple replicas of a component are assigned a logical name. for example,
web
for all the application server containers and
db
for all the database containers. now, an application can talk to the database containers using the logical service name. this allows the database containers to be rescheduled anywhere in the cluster, and also scale up and down dynamically.
let’s see how this can be accomplished in dc/os with a single instance of an application server and database server. this blog will use wildfly for the application server and couchbase for the database.
couchbase cluster on mesos with dc/os provides more details on how to set up a couchbase cluster on dc/os.
this blog will use the following main steps:
- setup dc/os cluster
- marathon application definition
- deploy the application
the complete source code used in this blog is at github.com/arun-gupta/dcos-java-database .
many thanks to @unterstein for creating the maven plugin and helping me understand the inner workings of dc/os.
set up the dc/os cluster
a dc/os cluster can be easily created using the cloudformation template . detailed instructions, including system requirements and screenshots and setup, are available at installing dc/os on aws .
your cloudformation output should look as shown:
note down the value shown for the keys
dnsaddress
and
publicslavednsaddress
. the value of the first key can be used to access
dc/os gui
and looks like:
configure dc/os cli as explained in here . in short, the following commands are used:
-
dcos config set core.dcos_url http://${dnsaddress}
replace${dnsaddress}
with the corresponding value from the cloudformation output. -
dcos auth login
-
dcos config show core.dcos_acs_token
. if not already done, clone the repo from github.com/arun-gupta/dcos-java-database . create a new file.dcos-token
and copy the output from the command in this file. -
dcos package install marathon-lb
marathon application definition
the marathon framework is used to schedule containers in dc/os. a marathon application can be defined by providing an application definition .
as mentioned earlier, this blog will show how a simple java application can talk to a database. we’ll use a java ee application deployed in wildfly and use couchbase as the database. the application definition looks like:
{
"id":"/webapp",
"apps":[
{
"id":"database",
"cpus":4,
"mem":4096,
"instances":1,
"container":{
"type":"docker",
"docker":{
"image":"arungupta/couchbase:travel",
"network":"user"
}
},
"ipaddress":{
"networkname":"dcos"
}
},
{
"id":"web",
"dependencies":[
"/webapp/database"
],
"cpus":2,
"mem":4096,
"instances":1,
"container":{
"type":"docker",
"docker":{
"image":"arungupta/wildfly-couchbase-javaee:travel",
"network":"user",
"portmappings":[
{
"hostport":0,
"containerport":8080,
"protocol":"tcp"
}
]
}
},
"ipaddress":{
"networkname":"dcos"
},
"env":{
"couchbase_uri":"database-webapp.marathon.containerip.dcos.thisdcos.directory"
},
"labels":{
"haproxy_0_vhost":"dcos-publicslavelo-dd2eggfvcja0-1604955948.us-west-1.elb.amazonaws.com",
"haproxy_group":"external"
}
}
]
}
what are the key points in this application definition?
-
the application has two containers:
database
andweb
. the web container has a dependency on the database container defined using thedependencies
attribute. -
the
database
container uses thearungupta/couchbase:travel
docker image. this image is created from github.com/arun-gupta/couchbase-javaee/tree/master/couchbase . it uses couchbase base image and uses the couchbase rest api to pre-configure the database. a sample bucket is also loaded in the database as well. -
the
web
container usesarungupta/wildfly-couchbase-javaee:travel
image. this image is created from github.com/arun-gupta/couchbase-javaee/blob/master/dockerfile . this is a java ee 7 application bundled in wildfly. the app usescouchbase_uri
as an environment variable to connect to the couchbase database. the value of this environment variable is configured to use dns service discovery and is derived as explained in virtual networks .
make sure to change the value of
haproxy_0_vhost
to match the value of
${publicslavednsaddress}
from the cloudformation output. the label
haproxy_0_vhost
instructs marathon-lb to expose the docker container, the wildfly application server in our case, on the external load balancer with a virtual host. the
0
in the label key corresponds to the serviceport index, beginning from 0. if you had multiple serviceport definitions, you would iterate them as 0, 1, 2, and so on.
deploying an internally and externally load-balanced app with marathon-lb
provide more details about how to configure marathon-lb.
service discovery and load balancing provide more details about service discovery and load balancing in dc/os.
deploy the application using maven
the application can be deployed using dcos-maven-plugin .
the plugin looks like:
<plugin>
<groupid>dcos</groupid>
<artifactid>dcos-maven-plugin</artifactid>
<version>0.2</version>
<configuration>
<dcosurl>http://dcos-elasticloadba-1th4txiu5p783-1163025470.us-west-1.elb.amazonaws.com/</dcosurl>
<deployable>group</deployable>
<ignoresslcertificate>true</ignoresslcertificate>
</configuration>
<executions>
<execution>
<id>dcos:deploy</id>
<phase>install</phase>
<goals>
<goal>deploy</goal>
</goals>
</execution>
</executions>
</plugin>
the main points in this fragment are:
- the plugin version is 0.2. that indicates the plugin is still in the early stages of development.
-
dcosurl
is the value of the${dnsaddress}
key from the cloudformation output. this address is used for deployment of the application. -
<deployable>
enables different types of deployments — app, group or pods. this element is a hint for the plugin and should likely go away in a future version as marathon api consolidates. follow #11 for more details.
other details and configuration about the plugin are at dcos-maven-plugin .
deploy the application:
mvn install
the following output is shown:
[info] --- dcos-maven-plugin:0.2:deploy (dcos:deploy) @ dcos-java-database ---
[info] about to execute dc/os deploy
[info] app definition: /users/arungupta/workspaces/dcos-java-database/app-definition.json
[info] dcos token: /users/arungupta/workspaces/dcos-java-database/.dcos-token
[info] dcos url: http://dcos-elasticloadba-1th4txiu5p783-1163025470.us-west-1.elb.amazonaws.com/
[info] ignore ssl certificate: true
[info] deployable: group
[info] response from dc/os [200] {"version":"2017-03-07t13:27:49.970z","deploymentid":"dbc80f96-28cb-4040-8d0d-78452e461ec1"}
here are some of the updated outputs from the dc/os console.
first, the updated services tab:
two applications are in the service:
the database application has one task:
the status of the database task:
logs from the database task:
it shows the output from couchbase rest api for configuring the server.
status of the web task:
logs from the web task:
it shows that the java ee application has been deployed successfully.
access the application:
curl http://dcos-publicslavelo-dd2eggfvcja0-1604955948.us-west-1.elb.amazonaws.com/airlines/resources/airline
the address is the value of the key
${publicslavednsaddress}
from the cloudformation output. a formatted output, for example with
jq
, looks like:
[
{
"travel-sample": {
"country": "united states",
"iata": "q5",
"callsign": "mile-air",
"name": "40-mile air",
"icao": "mla",
"id": 10,
"type": "airline"
}
},
{
"travel-sample": {
"country": "united states",
. . .
"icao": "rla",
"id": 1203,
"type": "airline"
}
}
]
that’s it!
as mentioned earlier, the complete source code used in this blog is at github.com/arun-gupta/dcos-java-database .
this blog showed how a simple java application can talk to a database using service discovery in dc/os.
for further information check out:
- dc/os docs
- couchbase on containers
- couchbase developer portal
- ask questions on couchbase forums or stack overflow
- download couchbase
Published at DZone with permission of Arun Gupta, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments