Ubuntu: sudo apt-get install wget curl
OSX: sudo port install wget curl
$ wget http://sourceforge.net/projects/cloudi/files/latest/download -O cloudi-1.2.0.tar.gz
$ tar zxvf cloudi-1.2.0.tar.gz
$ cd cloudi-1.2.0/src
$ ./configure
$ make
$ sudo make install
$ cd ../..
$ sudo cloudi start
The CloudI tests are now running and consuming your available CPUs.
The Quick Start guide below shows how to create both an internal (Erlang) CloudI service and an external (Python) CloudI service.
$ mkdir cloudi-quickstart
$ cd cloudi-quickstart
$ cat << EOF > hello_world.erl
-module(hello_world).
-behaviour(cloudi_service).
%% cloudi_service callbacks
-export([cloudi_service_init/3,
cloudi_service_handle_request/11,
cloudi_service_handle_info/3,
cloudi_service_terminate/2]).
-include_lib("cloudi_core/include/cloudi_logger.hrl").
-record(state,
{
}).
cloudi_service_init(_Args, _Prefix, Dispatcher) ->
cloudi_service:subscribe(Dispatcher, "hello_world/get"),
{ok, #state{}}.
cloudi_service_handle_request(_Type, _Name, _Pattern, _RequestInfo, _Request,
_Timeout, _Priority, _TransId, _Pid,
#state{} = State, _Dispatcher) ->
{reply, <<"Hello World!">>, State}.
cloudi_service_handle_info(Request, State, _) ->
?LOG_WARN("Unknown info \"~p\"", [Request]),
{noreply, State}.
cloudi_service_terminate(_, #state{}) ->
ok.
EOF
$ erlc -pz /usr/local/lib/cloudi-1.2.0/lib/cloudi_core-1.2.0 hello_world.erl
You now have a compiled internal CloudI service which is ready to run. You can also provide an OTP application file with the same name, if the internal CloudI service has application dependencies.
While you are still in the cloudi-quickstart directory, use the CloudI Service API to run the internal CloudI service.
$ curl -X POST -d '"'`pwd`'"' http://localhost:6467/cloudi/api/erlang/code_path_add
$ cat << EOF > hello_world.conf
[{internal,
"/quickstart/hello/",
hello_world,
[],
lazy_closest,
5000, 5000, 5000, [api], undefined, 1, 5, 300, []}]
EOF
$ curl -X POST -d @hello_world.conf http://localhost:6467/cloudi/api/erlang/services_add
These HTTP requests communicate with src/lib/cloudi_services_internal/src/cloudi_service_http_cowboy.erl
which runs the cowboy HTTP webserver on port 6467, because of the default CloudI configuration (installed at /usr/local/etc/cloudi/cloudi.conf
). The request becomes a CloudI request, within the cloudi_service_http_cowboy
internal CloudI service, which is sent to src/lib/cloudi_services_internal/src/cloudi_service_api.erl
. The cloudi_service_api
internal CloudI service provides runtime configuration of CloudI.
You will notice that the syntax used to start the CloudI service in the hello_world.conf
file is the same as what is specified in the "services" section of /usr/local/etc/cloudi/cloudi.conf
.
$ curl http://localhost:6467/quickstart/hello/hello_world
Hello World!
The HTTP GET request has received the "Hello World!" message from your new internal CloudI service.
You can get the same behavior with an external CloudI service, which is written in a supported programming language, currently: C/C++, Java, Python, or Ruby.
While you are still in the cloudi-quickstart directory:
$ cat << EOF > hello_world.py
import sys
sys.path.append('/usr/local/lib/cloudi-1.2.0/api/python/')
from cloudi_c import API
class Task(object):
def __init__(self):
self.__api = API(0) # first/only thread == 0
def run(self):
self.__api.subscribe("hello_world_python/get", self.__hello_world)
result = self.__api.poll()
print 'exited:', result
def __hello_world(self, command, name, pattern, request_info, request,
timeout, priority, trans_id, pid):
return 'Hello World!'
if __name__ == '__main__':
assert API.thread_count() == 1 # simple example, without threads
task = Task()
task.run()
EOF
$ PYTHON_PATH=`which python`
$ PWD=`pwd`
$ cat << EOF > hello_world_python.conf
[{external,
"/quickstart/hello/",
"$PYTHON_PATH",
"$PWD/hello_world.py",
[],
none, tcp, 16384,
5000, 5000, 5000, [api], undefined, 1, 1, 5, 300, []}]
EOF
$ curl -X POST -d @hello_world_python.conf http://localhost:6467/cloudi/api/erlang/services_add
$ curl http://localhost:6466/quickstart/hello/hello_world_python
Hello World!
You may notice the port number 6466 is different from what was used for the internal CloudI service. This is a different instance of the cloudi_service_http_cowboy
internal CloudI service which forces all CloudI requests to be binary. All external CloudI services handle request
data and request_info
data as binary data, to simplify integration efforts and make service runtime more efficient.
You now have an external CloudI service written in Python which is able to perform the same task as your internal CloudI service (written in Erlang). You can use the same techniques to create other external CloudI services with new or pre-existing source code to gain fault-tolerance and scalability. Creating CloudI services makes integration tasks simpler and allows your software to grow without limitations!