Over a million developers have joined DZone.

Service Discovery With Wildfly Swarm

Take advantage of WildFly's ability to interact with an enormous number of microservices.

Is iPaaS solving the right problems? Not knowing the fundamental difference between iPaaS and dPaaS could cost you down the road. Brought to you in partnership with Liaison Technologies.

Horizontal and elastic scaling is one of the cornerstones of microservices. The only thing better than 1 microservice is 100 of them all operating in unison. If your services can’t be scaled out horizontally, then you end up missing out on so many of the benefits that can be found in microservices.

Deploying multiple instances of a service is often the easiest part. It is knowing where all those instances are and being able to interact with them as they are created and destroyed in often unpredictable ways that is a bigger challenge.

One of the more interesting aspects of the WildFly Swarm project are the features that it offers that go beyond the WildFly application server. The WildFly application server is certainly capable of interacting with a huge range of services, but doesn’t make any “official” effort to support these. On the other hand, WildFly Swarm has embraced a lot of additional services, and often services not even developed as part of the JBoss universe, in order to provide the kind of functionality that developers need in a microservice environment.

One of these features is the notion of service discovery. In simple terms, service discovery is about microservices advertising their presence or absence to other services that rely on them. WildFly Swarm offers service discovery through a variety of libraries like JGroups, Consul and Zookeeper.

To demonstrate service discovery, let’s take a look at a simple application that implements JGroups to advertise the presence of each instance of the application to all other instances.

Our demo app will be a simple web page that makes use of the Topology JavaScript library that is included as part of WildFly Swarm.

The build script for our application includes a number of Swarm fractions including JSF, Weld (CDI), JGroups, Topology and the Topology web app library. This will allow us to build a web application and participate in a collection of advertised services using the JGroups and Topology fractions.

buildscript {
    repositories {
        mavenLocal()
        mavenCentral()
    }

    dependencies {
        classpath "org.wildfly.swarm:wildfly-swarm-plugin:1.0.0.Beta2"
    }
}

group 'com.matthewcasperson'
version '1.0-SNAPSHOT'

apply plugin: 'war'
apply plugin: 'wildfly-swarm'

swarm {
    mainClassName = "com.matthewcasperson.swarmdemo.MyMain"
}

sourceCompatibility = 1.8

def swarmVersionBeta1 = '1.0.0.Beta1'

repositories {
    mavenCentral()
    mavenLocal()
    maven {
        url 'http://repository.jboss.org/nexus/content/groups/public-jboss'
    }
    maven {
        url 'https://maven.repository.redhat.com/nexus/content/repositories/public'
    }
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    compile 'org.wildfly.swarm:bootstrap:' + swarmVersionBeta1
    compile 'org.wildfly.swarm:jsf:' + swarmVersionBeta1
    compile 'org.wildfly.swarm:weld:' + swarmVersionBeta1
    compile 'org.wildfly.swarm:jgroups:' + swarmVersionBeta1
    compile 'org.wildfly.swarm:topology-webapp:' + swarmVersionBeta1
    compile 'org.wildfly.swarm:topology-jgroups:' + swarmVersionBeta1
}

// For heroku
task stage {
    dependsOn build
}


To provide some visual feedback as services are created and destroyed, we have a simple JSF web page that will display the details of any services. Note that we have referenced the /topology/topology.js script, which is something that the topology-webapp fraction provides.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Topology Example</title>
    </h:head>
    <h:body>
        <h2>Topology Example</h2>
        <div id="topology"></div>

        <script src="/topology/topology.js"></script>
        <script src="/demo.js"></script>
    </h:body>
</html>


Most of the logic for responding to service events is handled in the demo.js file. We are provided a simple callback that is triggered when services are added to or removed from the network.

var Topology = topology();

var topologyDiv = document.getElementById("topology");

// listen for changes to the service topology
// and update our component on change
Topology.onTopologyChange(function(topology) {
    var topologyTable = "<table>";

    for (var property in topology) {
        if (topology.hasOwnProperty(property)) {
            topologyTable += "<tr>";

            topologyTable += "<td>";
            topologyTable += property;
            topologyTable += "</td>";

            topologyTable += "<td>";
            for (var i = 0; i < topology[property].length; ++i) {
                topologyTable += topology[property][i].endpoint + "<br/>";
            }
            topologyTable += "</td>";

            topologyTable += "</tr>";
        }
    }

    topologyTable += "</table>";

    topologyDiv.innerHTML = topologyTable;
});


We have a custom main method, in which we build up our web application, and advertise it on the network. The code for advertising a Swarm archive comes from the documentation.

package com.matthewcasperson.swarmdemo;

import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.wildfly.swarm.container.Container;
import org.wildfly.swarm.topology.TopologyArchive;
import org.wildfly.swarm.undertow.WARArchive;

import java.io.File;

/**
 * Swarm entry point
 */
public class MyMain {

    private static final String WEBAPP_SRC = "src/main/webapp";


    public static void main(final String... args) throws Exception {

        // Instantiate the container
        final Container container = new Container();

        final WARArchive deployment = ShrinkWrap.create(WARArchive.class);
        deployment.setWebXML(new File(WEBAPP_SRC, "WEB-INF/web.xml"));
        deployment.addAsWebResource(new File(WEBAPP_SRC, "demo.js"));
        deployment.addAsWebResource(new File(WEBAPP_SRC, "index.xhtml"));

        // advertise this deployment as `sampleapp`
        deployment.as(TopologyArchive.class).advertise("sampleapp");

        container.start();
        container.deploy(deployment);
    }
}


This code pulls in all the aspects of advertising services and responding to changes in the available services on the network. The next step is to start up multiple instances of our applications and watch the web pages as it responds to the changing availability of services.

To start the first instance of the application, run this command. You need to specify the swarm.bind.address system property. We have used the IP address of 192.168.0.1 here, but your local IP address is probably something else. If you don’t specify it, Swarm will default to accepting connections on 0.0.0.0, which means “all interfaces” to Swarm, but has no meaning to JGroups. Since JGroups is responsible for forming clusters on the network, we are forced to define an actual interface that JGroups can communicate over.

java -Dswarm.bind.address=192.168.0.1 -Djava.net.preferIPv4Stack=true -jar build/libs/swarmdemo5-swarm.jar


To start the second instance of the application, run this command. The swarm.port.offset system property means that this instance of the application will bind to a different set of ports that the first instance. Without this offset, the second instance would clash ports.

java -Dswarm.bind.address=192.168.0.1 -Dswarm.port.offset=100 -Djava.net.preferIPv4Stack=true -jar build/libs/swarmdemo5-swarm.jar


With two instances of this application booted up, this is what I see on my local PC.

Screen Shot 2016-04-03 at 7.16.38 PM.png

If I shutdown one instance, the web page is updated almost instantly.

Screen Shot 2016-04-03 at 7.18.09 PM.png

Having access to the network details of our services makes it possible to distribute work in an intelligent way during runtime.

You can access the source code for this application from GitHub.

Discover the unprecedented possibilities and challenges, created by today’s fast paced data climate and why your current integration solution is not enough, brought to you in partnership with Liaison Technologies.

Topics:
java ,wildfly swarm ,wildfly

Published at DZone with permission of Matthew Casperson, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}