Open Gitter Chat

Microservices

Hazelcast® In-Memory Data Grid (IMDG) can be used as the backbone of a Microservices architecture. Hazelcast IMDG® is a simple, single JAR file with no external dependencies.

One of the core values of Hazelcast from its inception was simplicity and ease of use, and that still exists today. When you move an application or system into a distributed environment, having a simple and configurable backbone makes the task a lot easier.

Hazelcast is a library. Libraries are easier to use and understand enabling the development process to be more efficient. This simplicity and ease of use is a hallmark of Hazelcast and the reason it adapts well to the Microservices architecture.

Hazelcast IMDG is highly scalable (e.g. IMap and JCache). Hazelcast also supports other standard Java standard Collections such as Lists, Sets, Queues and some other constructs such as Topics and Ringbuffers, that can be easily leveraged for inter-process messaging. All of these attributes can offer functionality that is highly desirable within a Microservices platform.

Hazelcast IMDG can be deployed two ways:

  1. Embedded, where you add the JAR to your application and the Hazelcast Member instance is embedded in your application.
  2. Client-Server, where Hazelcast is run on its own. Here you can run Hazelcast from the command line, a Docker container or a cloud deployment such as AWS and Azure.

Code Examples

Java

package vertx;

import io.vertx.core.*;
import io.vertx.core.http.*;
import io.vertx.core.shareddata.AsyncMap;
import io.vertx.core.spi.cluster.ClusterManager;
import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager;

import java.util.Optional;
import java.util.function.Consumer;

public class VertxExample {

    public static void main(String[] args) {
        ClusterManager clusterManager = new HazelcastClusterManager();
        VertxOptions options = new VertxOptions().setClusterManager(clusterManager);

        Vertx.clusteredVertx(options, res -> {
            if (res.succeeded()) {
                Vertx vertx = res.result();
                vertx.deployVerticle(new Server());
            }
        });
    }

    public static class Server extends AbstractVerticle {
        @Override
        public void start() throws Exception {
            HttpServer httpServer = vertx.createHttpServer();
            httpServer.requestHandler(req -> {
                String key = req.getParam("key");
                req.response().setChunked(true);
                switch (req.method()) {
                    case GET:
                        map("my-map", map -> map.get(key, response(req)));
                        break;
                    case POST:
                    case PUT:
                        map("my-map", map -> map.put(key, req.getParam("value"), response(req)));
                }
            });
            httpServer.listen(8080);
        }

        private <T> Handler<AsyncResult<T>> response(HttpServerRequest req) {
            return res -> {
                HttpServerResponse response = req.response();
                if (res.succeeded()) response = response.setStatusCode(200).write(
                            Optional.ofNullable(res.result()).map(v -> v.toString()).orElse("null"));
                else response = response.setStatusCode(500).write(res.cause().toString());
                response.end();
            };
        }

        private void map(String mapName, Consumer<AsyncMap<String, String>> consumer) {
            vertx.sharedData().<String, String> getClusterWideMap(mapName, res -> {
                if (res.succeeded()) consumer.accept(res.result());
            });
        }
    }
}

Kotlin

package vertx

import io.vertx.core.*
import io.vertx.core.http.*
import io.vertx.core.shareddata.AsyncMap
import io.vertx.spi.cluster.hazelcast.HazelcastClusterManager

fun main(args: Array<String>) {
    val clusterManager = HazelcastClusterManager()
    val vertxOptions = VertxOptions().apply { this.clusterManager = clusterManager }

    Vertx.clusteredVertx(vertxOptions) { res ->
        res.result().deployVerticle(Server())
    }
}

class Server : AbstractVerticle() {
    override fun start() {
        vertx.createHttpServer().requestHandler { req ->
            val key = req.getParam("key")
            req.response().isChunked = true
            when(req.method()) {
                HttpMethod.GET ->
                    map("my-map") { it.get(key, response(req)) }
                HttpMethod.POST, HttpMethod.PUT ->
                    map("my-map") { it.put(key, req.getParam("value"), response(req)) }
            }
        }.listen(8080)
    }

    fun <T> response(req: HttpServerRequest): Handler<AsyncResult<T>> = Handler {
        val (statusCode, body) = if (it.succeeded()) 200 to it.result() else 500 to it.cause()
        req.response().setStatusCode(statusCode).write(body.toString()).end()
    }

    fun map(mapName: String, consumer: (AsyncMap<String, String>) -> Unit) =
            vertx.sharedData().getClusterWideMap<String, String>(mapName) { if (it.succeeded()) consumer(it.result()) }
}

Hazelcast IMDG