This blog will show how a simple Java application can talk to a database or database as a service (DBaaS) using service discovery in DC/OS.

DC/OS logo

Why Service Discovery?

An application typically consist of multiple components such as an application server, a database, a web server, caching and 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 multi-container application.

Each container is assigned a unique IP address for its lifetime. But containers are ephemeral and may terminate and 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 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 application server and database server. This blog will use WildFly for application server and Couchbase for database.

Couchbase Cluster on Mesos with DC/OS provide more details on how to setup 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.

Setup DC/OS Cluster

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.

CloudFormation output looks as shown:

DC/OS Cluster CloudFormation Output

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:

DC/OS Cluster Console Default Output

Configure DC/OS CLI as explained in CLI. 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

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:

What are the key points in this application definition?

  • Application has two containers: database and web. The web container has a dependency on the database container defined using dependencies attribute.
  • database container uses arungupta/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 Couchbase REST API to pre-configure the database. A sample bucket is also loaded in the database as well.
  • web container uses arungupta/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 uses COUCHBASE_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 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.

Plugin looks like:

Main points in this fragment are:

  • Plugin version is 0.2. That indicates the plugin is still in early stages of development.
  • dcosUrl is the value of ${DnsAddress} key from CloudFormation output. This address is used for deployment of the application.
  • <deployable> element enables different types of deployment – 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:

The following output is shown:

Here are some of the updated output from DC/OS console.

First updated Services tab:
DC/OS Cluster Web Application

Two applications in the service:
DC/OS Cluster Web Application

Database application has one task:
DC/OS Cluster Web Application

Status of database task:Database Service Discovery

Logs from the database task:
DC/OS Cluster Web Application

It shows the output from Couchbase REST API for configuring the server.

Status of web task:
DC/OS Cluster Web Application

Logs from web task:
DC/OS Cluster WildFly Output

It shows that the Java EE application is deployed successfully.

Access the application:

The address is the value of the key ${PublicSlaveDnsAddress} from CloudFormation output. A formatted output, for example with jq, looks like:

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:

 

Author

Posted by Arun Gupta, VP, Developer Advocacy, Couchbase

Arun Gupta is the vice president of developer advocacy at Couchbase. He has built and led developer communities for 10+ years at Sun, Oracle, and Red Hat. He has deep expertise in leading cross-functional teams to develop and execute strategy, planning and execution of content, marketing campaigns, and programs. Prior to that he led engineering teams at Sun and is a founding member of the Java EE team. Gupta has authored more than 2,000 blog posts on technology. He has extensive speaking experience in more than 40 countries on myriad topics and is a JavaOne Rock Star for three years in a row. Gupta also founded the Devoxx4Kids chapter in the US and continues to promote technology education among children. An author of several books on technology, an avid runner, a globe trotter, a Java Champion, a JUG leader, NetBeans Dream Team member, and a Docker Captain, he is easily accessible at @arungupta.

4 Comments

  1. […] Service Discovery with Java and Database application in DC/OS explains why service discovery is an important aspect for a multi-container application. That blog also explained how this can be done for DC/OS. […]

  2. […] Service Discovery with Java and Database application in DC/OS explains why service discovery is an important aspect for a multi-container application. That blog also explained how this can be done for DC/OS. […]

  3. Hi Arun.

    I wondered why we can’t just use a load balancer like haproxy to do the service registration. It publishes a logical service name that would forward the request to one of the services available on cs/os. Why the fuss with service registration? It’s dynamic, it’s scalable and it’s technology transparent.

    Best regards, Alexander

Leave a reply