ContainiumReactor

Dev & Ops friendly microservices in Clojure, or Application Server As A Library

What is Containium?

Containium Reactor is a Clojure Application Server in Clojure with some truly unique features. A full deployment consists of three parts: core services we call Systems which your apps can use, your Clojure apps put in a special container, making it what we call Containium, and a Reactor process that runs these Systems and Containium.

Dev & Ops friendly

Configure the Systems (services) once: apps don't have to care about networking settings. Script deployments using simple commands over netcat or activation files.

Compose your own Application Server

Wheras projects like Tomcat and WildFly act like a framework, Containium Systems are built so that you can easily compose your own “Reactor”. Easily add custom shared Systems.

Adjust to different workloads

Pick and choose what System should run in each JVM, e.g. embed ElasticSearch and Cassandra or run them seperately, it doesn't matter to applications. This gives operations the power to adjust deployment to workloads with no application changes.

Simple System Design

Applications only need to implement a Component like start/stop protocol, receiving Systems and configuration as arguments. Quickly spin up Systems locally or during unit tests. All systems optional.

Shared Clojure Runtime

Blazing fast deployments. Once started, the Clojure runtime is loaded. Dependency isolated applications can communicate using Clojure data without serialization.

Simple Configuration as Data

Deploy your code once or as multiple instances. Simple “deployment descriptor“ (a Clojure map) allowing arbitrary per-instance configuration. Sane conventions reduce the amount of configuration needed.

Multiple Apps, Single nREPL

nREPL is just another optional System. Connect to a single nREPL socket and eval in every running application or the Application Server itself.

C*

Cassandra

Embedded Cassandra server or connect to an existing cluster? Both? Apps don't care, all they see is Cassandra. Unit test queries and run the same in production.

ElasticSearch

Embedded ElasticSearch server or connect to an existing cluster? Both? Apps don't care, all they see is ElasticSearch. Unit test queries and run the same in production. (hmm this sounds familiar)

Embedded Kafka Server

Did we mention Apache Kafka yet? It's awesome and another optional System. Unit test your queueing code using the real thing.

Asynchronous, daily rolling Ring logs into ElasticSearch.

The Ring-Analytics System stores requests and reponse ring maps directly and asynchronously in ElasticSearch. No HTTP server log parsing and other complications needed.

Zero Downtime Ring Handlers

New version? If the start function returns successfully, the global ring handler is atomically swapped. In progress requests of the old version simply continue until completed. Start fails? No sweat, existing version is still up!

Distributed Ring Sessions over Cassandra

Scale your applications by adding servers. Ring sessions are (de)serialized quickly using nippy and stored in Cassandra.

Configure and connect to SMTP servers once

Your application needs to send e-mail notifications otherwise known as SPAM? No problem! Postal System included.

Get Started

Running the Reactor on your machine

Until we release a standalone download you can simply clone the git repository and lein run. The full Reactor requires a running Apache Zookeeper server for the Kafka system.

Production ready Reactor (well, 0.1.0-SNAPSHOT)

Our Containium Reactor runs in production on SmartOS as an SMF service. We need some time to provide a nice example repository. Contact us if you’re interested.

To build a release:

lein do with-profile +aot compile, jar, libdir
mv target/containium*.jar lib/

To run it:

java -d64 -Djava.awt.headless=true -Dfile.encoding=UTF-8 -javaagent:jamm-0.2.5.jar '-XX:OnOutOfMemoryError=kill -9 %p' -cp /var/lib/containium/config:lib/* -server containium.core

Standalone Application

project.clj

(defproject my-project-using-containium "0.1.0-SNAPSHOT"
  :dependencies [
    [containium "0.1.0-SNAPSHOT" :exclusions [boxure/clojure]]]
  :main my-project.main/main)

main.clj

(ns my-project.main
  (:require [containium.standalone :as standalone]))

(defn start [systems conf & [routes]]
  (println "Starting with config:\n" (print-str conf)))

(defn stop [start-result]
  (printlin "Stopping"))

(defn app [request]
  {:status 200 :body "Hello world!"})

(defn main []
  (standalone/run
    ;; Define config for all the Systems you want here
    {:http-kit {:port 8080} :repl {:port 2121}}
    ;; The "deployment descriptor" of this app
    {:start start :stop stop :ring {:handler 'my-project/app}}))

Then just lein run and see your app start up.

For a more detailed example, read: Using Containium as a library.

License

The Containium source code is provided under the Mozilla Public License 2.0
Systems (like Cassandra, ElasticSearch, Kafka, Ring, ...) may use libraries that have other licenses.

© Copyright 2013-2017, the Containium Project Contributors.

Contact

Have a few questions? Need a little help getting up and running?
You can get free help from the Containium open source community.

Come talk to us!

Love it? Hate it? We’d like to know... Maybe.   Try us at the Gitter chat room.

Commercial support

We think community chat rooms are great, but perhaps you need something a little more serious? If you and your company are thinking of using Containium in production, we can help you out. Providing support, answering your questions, diagnose and patch bugs, etc.
Need to streamline some of your services and deployments? We can help develop custom Reactor Systems.

E-mail us today