Fork me on GitHub

Hurricane

A scalable, extensible, distributed messaging system.

View Project on GitHub » Download Hurricane »

Performance

Built for speed, Hurricane can send and receive as many as the network can handle. Hurricane is so fast that it can do an entire process-to-process round-trip in 60 microseconds.

Clustering

Clustering is provided out of the box with the distribution manager. Even in huge clusters, each node only needs to be configure to talk to one other node—the rest is magic.

Scatter-Gather

Hurricane ships first-class support for the powerful Scatter-Gather pattern of service communication. Give each message a unique tag and the responses are guaranteed to arrive in-order.

Concurrency

Hurricane acts as your concurrency framework. With Scatter-Gather support, easily distribute work over any number of processes. Suddenly, parallelism is easy and bug-free.

Rails and Django

Really any WSGI or Rack enabled framework. Drivers and handlers are provided so that your Favorite™ Python or Ruby Framework can be hooked up to Hurricane to serve HTTP requests.

Language Support

The Hurricane project current ships drivers for Ruby, Python, PHP, and Java. Interested in support for your language? Please contribute—your help makes a difference!

Fault Tolerance

Out of the box, messaging works over TCP and over Standard I/O. With Standard I/O-based messaging, Hurricane will manage and restart broken processes automatically.

Extensibility

At startup, Hurricane loads and compiles each piece of itself. Any number of "after-factory" modules can be added simply by configuring a path for each custom module.

Open Source

Hurricane is created, developed, and shared with the world under the New BSD License. Go ahead and do something great with it, and while you're at it, please contribute—your help makes Hurricane better.



Getting Started

For Hurricane itself, Erlang R14B01+ is recommended. To get additional HTTP features, grab a copy of MochiWeb.

# First set everything up

$ curl 'https://nodeload.github.com/icheishvili/hurricane/zipball/master' > hurricane.zip
$ unzip hurricane.zip
$ mv icheishvili-hurricane* hurricane
$ cd hurricane
$ curl 'https://nodeload.github.com/mochi/mochiweb/zipball/master' > mochiweb.zip
$ unzip mochiweb.zip
$ mv mochi-mochiweb* mochiweb
$ cd mochiweb
$ make
$ cd ..
$ ./run.escript examples/basic.config

# Now you're ready to run the demos in the examples directory


Ruby

The Ruby driver is compatible with Ruby 1.8.6+. Included is the Erlang Codec, Hurricane Gateway Tools, and Rack Handler.

require 'hurricane'

gateway = Hurricane::Gateway.new(Erlang::SocketWrapper.new('localhost', 3000))
loop do
  request = Hurricane::Message.new()
  request.type = 'request'
  request.destination = 'time_server'
  request.tag = 0
  request.data = nil

  gateway.do_send(request)
  p gateway.do_recv()
end

Run your favorite Rack-enabled Ruby framework:

rackup --server Hurricane


Python

The Python driver is compatible with Python 2.4+. Included is the Erlang Codec, Hurricane Gateway Tools, and WSGI Server.

from hurricane import Gateway, Message
from hurricane.erl_codec import SocketWrapper

gateway = Gateway(SocketWrapper('localhost', 3000))
while True:
    message = Message()
    message.type = 'request'
    message.destination = 'time_server'
    message.tag = 0
    message.data = None
    gateway.send(message)
    print gateway.recv()

Run your favorite WSGI-enabled Python framework:

Create myapp.py:

import os
import sys

sys.path.append('/path/to/django/project')
os.environ['DJANGO_SETTINGS_MODULE'] = 'mydjangoproject.settings'

from django.core.handlers.wsgi import WSGIHandler
application = WSGIHandler()

and then run:

hurricane_wsgi_server --app myapp


PHP

The PHP driver is compatible with PHP 5.3+. Included is the Erlang Codec and Hurricane Gateway Tools.

PHP is a platform that sees significant performance improvements when using Hurricane, due to the ability to have long-running processes.

<?php

require 'hurricane.php';

$gateway = new \Hurricane\Gateway(new \Erlang\SocketWrapper('localhost', '3000'));
while (true) {
    $request = \Hurricane\Message::create()
        ->setType('request')
        ->setDestination('time_server')
        ->setTag(0)
        ->setData(null);
    $gateway->send($request);
    $response = $gateway->recv();
    echo $response->getData() . PHP_EOL;


Java

The Java driver is written and tested using the OpenJDK. Included is the Erlang Codec and Hurricane Gateway Tools.

import org.hurricane.Gateway;
import org.hurricane.Message;

public class TcpExample {
    public static void main(String[] args) throws Exception {
        Gateway gateway = new Gateway("localhost", 3000);

        while (true) {
            Message request = new Message();
            request.setType("request");
            request.setDestination("time_server");
            request.setTag(0);
            request.setData("");

            System.out.println(request);
            gateway.send(request);
            System.out.println(gateway.recv());
        }
    }
}


Config Example

Here is a configuration example. It is usually the minimum amount of configuration needed to make Hurricane boot.

The compile_modules section lists all of the Erlang files to compile and load into Hurricane. To add custom modules to Hurricane, simply drop in the path to the module here.

The add_code_paths section lists all of the additional paths where Hurricane will search for code. For example, to enable HTTP support, the path to the compiled MochiWeb files is given.

The log_level section specifies the log level. The standard log levels are supported: emergency, alert, critical, error, warning, notice, info, debug

The start_modules section configures which modules to start with which options. Each module must have a start/1 function that gets called with the given args.

{
    compile_modules,
    [
        "erl_modules/hurricane.erl",
        "erl_modules/hurricane_config_server.erl",
        "erl_modules/hurricane_utils.erl",
        "erl_modules/hurricane_stdio_server.erl",
        "erl_modules/hurricane_tcp_server.erl",
        "erl_modules/hurricane_http_server.erl",
        "erl_modules/hurricane_log_server.erl",
        "erl_modules/hurricane_supervisor.erl",
        "erl_modules/hurricane_message_delegate.erl",
        "erl_modules/hurricane_distribution_manager.erl"
    ]
}.

{
    add_code_paths,
    [
        "mochiweb/ebin"
    ]
}.

{log_level, info}.

{
    start_modules,
    [
        [
            {module, hurricane_tcp_server},
            {args, [{listen_port, 3000}]}
        ]
    ]
}.


TCP Server

This is an example configuration fragment for the Hurricane TCP Server. Multiple of these can be started, but never on the same port.

The only option that this module currently takes is listen_port, which configures which port this instance of the TCP Server will listen on for incoming connections.

        [
            {module, hurricane_tcp_server},
            {args, [{listen_port, 3000}]}
        ]


STDIO Server

This is an example configuration fragment for the Hurricane STDIO Server.

The cmd option specifies which command to run to create a process that will be able to do messaging over Standard I/O.

The group_name option which message group the process(es) will belong to.

The port_timeout option specifies after how many milliseconds the process should be considered hung and restarted (when waiting for a reply). This is OPTIONAL (default: 10000)

The port_startup_timeout option specifies after how many milliseconds the process should be considered hung and restarted (when starting the process and waiting for the initial ready payload). This is OPTIONAL (default: 10000)

This module also shows Hurricane's ability to start many instances of a module. The count top-level module config specifies how many instances of a module to start. Usually, the default setting of 1 is fine, but with the STDIO server, it is how many copies of a message handler are run.

        [
            {module, hurricane_stdio_server},
            {
                args,
                [
                    {cmd, "/usr/bin/python examples/http_handler.py"},
                    {group_name, http_handler},
                    {port_timeout, 10000},
                    {port_startup_timeout, 1000}
                ]
            },
            {count, 2}
        ]


HTTP Server

This is an example configuration fragment for the Hurricane HTTP Server. Note that MochiWeb must be in the code load path.

The listen_port option configures which port this instance of the HTTP Server will listen on for incoming connections.

The server_name option configures the name of the HTTP Server (for use with handler applications). This is OPTIONAL (default: "localhost")

The handler_group option configures which process group will be used to handle HTTP requests. This is OPTIONAL (default: http_handler)

The response_timeout option specifies how many milliseconds to wait until considering a request to have timed out. This is OPTIONAL (default: 10000)

The static_dir option specifies which directory to serve static files out of. This is OPTIONAL (default: undefined)

        [
            {module, hurricane_http_server},
            {
                args,
                [
                    {name, some_name},
                    {listen_port, 8000},
                    {server_name, "localhost"},
                    {handler_group, http_handler},
                    {response_timeout, 10000},
                    {static_dir, "/tmp/"}
                ]
            }
        ]


Distribution Manager (Clustering)

This module provides full clustering for Hurricane. As long as every node in a cluster "sees" at least another node, the entire cluster will be operational and able to route messages around correctly.

The magic_cookie option configures the secret magic cookie value that has to match up between all nodes for them to be able to connect to each other.

The node_name option provides a unique name for this node.

The connect_nodes option specifies which other nodes to connect to. Note that single-quotes are used to specify the name of the other nodes as Erlang atoms.

        [
            {module, hurricane_distribution_manager},
            {
                args,
                [
                    {magic_cookie, the_magic_cookie},
                    {node_name, hurricane_node_1},
                    {connect_nodes, ['a_hurricane_node@a_hostname.local']}
                ]
            }
        ]