Peace and let's say no to flame wars, comrades! Don't get me wrong, Java is an awesome language, but if you have already started serious coding in Erlang, you will probably never look back. Or maybe you will occasionally, like I did few days back, when I was charged with the task of cloning ejabberd module by replacing mnesia with odbc calls.
It might sound like fairly routine task, and it was for the most part, except sometimes it's hard to reason about Erlang function output just by looking at the source code. Java methods, on the other hand, always have statically typed output, which obviously eliminates any guessing work. So, after few attempts trying to mentally trace some of mnesia transactions, I suddenly felt my brain overloaded and had to resort to debugging ejabberd from remote node :-) I had to recompile the module with -compile(export_all) in order to be able to try functions that contained mnesia code in Erlang shell and figure out their exact output. This, of course, is an intrusive action and assumes the source code is available.
It could have been much easier, though, if the code was accompanied by documentation markup. Having function specifications will hugely help anyone who will ever have to work with the code, including the owner. I'm now ready to make resolution to have specifications for every single function in my code, including non-API functions. By the way, exmpp team really impressed me by thoroughly following this path throughout entire code base.
To me, having to have function specs in the code, while being a good thing on its own, is a very small price for the feeling of liberation and increased performance that dynamic typing in Erlang gives you compared to a static one in Java.
In conclusion, check out much more comprehensive discussion of typing problem in Erlang.
XMPP and IM, Erlang and other functional languages, AWS and cloud; sharing thoughts and experience with like-minded professionals.
Friday, September 18, 2009
Monday, September 7, 2009
XMPP web demo: setting it up
I will describe the XMPP demo setup on AWS EC2, starting with Alestic Ubuntu karmic image (ami-19a34270). Hopefully, you should be able to adjust the process to your environment of choice.
sudo apt-get update && sudo apt-get upgrade
We'll need svn to checkout some stuff later:
apt-get install subversion
Then install Erlang (version R12B5 or newer; karmic has R13B01):
apt-get install erlang
Now, let's move on to exmpp. First, we need to install some libraries that exmpp is using for XML support:
apt-get install libxml2-dev
or, alternatively:
apt-get install libexpat1-dev
Update: the demo will work fine with libxml2, however, at the time of writing (Nov 07, 2009), if you're planning to use exmpp for other purposes, particularly, exmpp_session module, you're advised to install libexpat1-dev instead. See https://support.process-one.net/si/jira.issueviews:issue-html/EXMPP-16/EXMPP-16.html for details.
apt-get install libssl-dev
apt-get install pkg-config
Now, download the exmpp distribution and build:
wget http://download.process-one.net/exmpp/exmpp-0.9.1-r857.tar.gz
gunzip exmpp-0.9.1-r857.tar.gz
tar -xvf exmpp-0.9.1-r857.tar
./configure
make
sudo make install
At this point you may want to check if exmpp is in working condition. Start erl and at the prompt type:
1>exmpp:start().
ok
2>exmpp_xml:start_parser().
If response is similar to
{xml_parser,[{max_size,infinity},
{root_depth,0},
{names_as_atom,true},
{emit_endtag,false}],
#Port<0.747>},
then everything went fine and you can type q(). at the prompt to close Erlang shell.
Next, installing ejabberd. We need to add a Jabber domain name to /etc/hosts first.
The first line in /etc/hosts after editing will look something like (substitute zephyr to anything you like):
127.0.0.1 localhost.localdomain localhost zephyr.local
Note: You will be using this domain name in many places, so please make note of it; I will be using zephyr.local in this post going forward.
Download, unpack and launch ejabberd installer:
wget http://www.process-one.net/downloads/ejabberd/2.0.5/ejabberd-2.0.5-linux-x86-installer.bin.gz
gunzip ejabberd-2.0.5-linux-x86-installer.bin.gz
chmod 755 ejabberd-2.0.5-linux-x86-installer.bin
./ejabberd-2.0.5-linux-x86-installer.bin
Make default choices during installation; when asked about ejabberd server domain, enter host name you previously added to /etc/hosts (i.e. zephyr.local). Note default installation directory ( /opt/ejabberd-2.0.5 by default), you will need it shortly.
Once installation is completed, edit ejabberdctl.cfg by changing the very last line from:
ERLANG_NODE=ejabberd@localhost
to
ERLANG_NODE=ejabberd@zephyr.local
This is an important change, especially if you're planning to reuse your EC2 instance; I will omit the explanation for now.
Now, let's make sure ejabberd is good:
cd /opt/ejabberd-2.0.5/bin
./ejabberdctl start
./ejabberdctl status
You should see:
Node 'ejabberd@zephyr.local' is started. Status: started
ejabberd is running
Next step - configure external XMPP component on ejabberd side.
Open up ejabberd.cfg in /opt/ejabberd-2.0.5/conf with your editor (you may want to make a backup copy first), locate the line starting with {5269, ejabberd_s2s_in
and add service description after the closing curly bracket:
{5269, ejabberd_s2s_in, [
{shaper, s2s_shaper},
{max_stanza_size, 131072}
]},
{7047, ejabberd_service,
[{hosts, ["test1.zephyr.local"],
[{password, "secret"}]}]},
%%
%% ejabberd_service: Interact with external components (transports...)
%%
Save ejabberd.cfg and restart ejabberd:
/opt/ejabberd-2.0.5/bin/ejabberdctl restart
/opt/ejabbberd-2.0.5/bin/ejabberd status
Provided ejabberd has restarted successfully, let's create a bot account (it's curently being used to help with weazard registration):
/opt/ejabberd-2.0.5/bin/ejabberd register _weazard_bot zephyr.local weazard
We're done with ejabberd for now. Time to checkout our demo code:
mkdir weazard
cd weazard
svn co https://tagsahead.svn.beanstalkapp.com/erltwit/trunk/web
svn co https://tagsahead.svn.beanstalkapp.com/xmpp_component/trunk
Review config.js in web/js and adjust it, if needed.
Review weazard.app in xmpp_component/trunk/ebin and adjust it.
We will use nginx as our web server:
apt-get install nginx
Below is configuration fragment that has to be included (directly to /etc/nginx/nginx.conf or through include directive):
server {
listen 8000;
root /home/nginx/web/;
location /http-bind {
proxy_pass http://localhost:5280/http-bind/;
}
}
We'll need to move our web application to the place where nginx can access it, i.e. /home/nginx/web
The highlighted piece is necessary because due to Javascript security Strophe can't directly reach ejabberd's HTTP binding service.
Update: Starting ejabberd v 2.1.3 configuring proxy is not necessary, so you won't have to include the highlighted text above. You might still want to configure the proxy if your web clients are behind firewall with the BOSH port (default 5280) disabled. See http://rfid-ale.blogspot.com/2010/04/end-of-cross-domain-hassle-for-bosh.html for details.
We're done!
Start weazard XMPP component:
At the prompt, type:
If you see the line:
in the output, then weazard has managed to connect to ejabberd and is ready to push data to subscribers.
You're now ready to launch your browser and try:
http://yourhostname:8000/weazard.html
Can I congratulate you with running demo? I hope so, but if you are not there yet, fear not! As you can see, a lot of things can potentially go wrong. There's plenty of resources on configuring ejabberd/BOSH/nginx, and I'm here to help to the best of my abilities.
Setting up
Brace yourself, that's going to be a long one. Major components to install and configure are:
- Erlang environment
- exmpp
- ejabberd
- nginx
- and, of course, weazard itself
sudo apt-get update && sudo apt-get upgrade
We'll need svn to checkout some stuff later:
apt-get install subversion
Then install Erlang (version R12B5 or newer; karmic has R13B01):
apt-get install erlang
Now, let's move on to exmpp. First, we need to install some libraries that exmpp is using for XML support:
apt-get install libxml2-dev
or, alternatively:
apt-get install libexpat1-dev
Update: the demo will work fine with libxml2, however, at the time of writing (Nov 07, 2009), if you're planning to use exmpp for other purposes, particularly, exmpp_session module, you're advised to install libexpat1-dev instead. See https://support.process-one.net/si/jira.issueviews:issue-html/EXMPP-16/EXMPP-16.html for details.
apt-get install libssl-dev
apt-get install pkg-config
Now, download the exmpp distribution and build:
wget http://download.process-one.net/exmpp/exmpp-0.9.1-r857.tar.gz
gunzip exmpp-0.9.1-r857.tar.gz
tar -xvf exmpp-0.9.1-r857.tar
./configure
make
sudo make install
At this point you may want to check if exmpp is in working condition. Start erl and at the prompt type:
1>exmpp:start().
ok
2>exmpp_xml:start_parser().
If response is similar to
{xml_parser,[{max_size,infinity},
{root_depth,0},
{names_as_atom,true},
{emit_endtag,false}],
#Port<0.747>},
then everything went fine and you can type q(). at the prompt to close Erlang shell.
Next, installing ejabberd. We need to add a Jabber domain name to /etc/hosts first.
The first line in /etc/hosts after editing will look something like (substitute zephyr to anything you like):
127.0.0.1 localhost.localdomain localhost zephyr.local
Note: You will be using this domain name in many places, so please make note of it; I will be using zephyr.local in this post going forward.
Download, unpack and launch ejabberd installer:
wget http://www.process-one.net/downloads/ejabberd/2.0.5/ejabberd-2.0.5-linux-x86-installer.bin.gz
gunzip ejabberd-2.0.5-linux-x86-installer.bin.gz
chmod 755 ejabberd-2.0.5-linux-x86-installer.bin
./ejabberd-2.0.5-linux-x86-installer.bin
Make default choices during installation; when asked about ejabberd server domain, enter host name you previously added to /etc/hosts (i.e. zephyr.local). Note default installation directory ( /opt/ejabberd-2.0.5 by default), you will need it shortly.
Once installation is completed, edit ejabberdctl.cfg by changing the very last line from:
ERLANG_NODE=ejabberd@localhost
to
ERLANG_NODE=ejabberd@zephyr.local
This is an important change, especially if you're planning to reuse your EC2 instance; I will omit the explanation for now.
Now, let's make sure ejabberd is good:
cd /opt/ejabberd-2.0.5/bin
./ejabberdctl start
./ejabberdctl status
You should see:
Node 'ejabberd@zephyr.local' is started. Status: started
ejabberd is running
Next step - configure external XMPP component on ejabberd side.
Open up ejabberd.cfg in /opt/ejabberd-2.0.5/conf with your editor (you may want to make a backup copy first), locate the line starting with {5269, ejabberd_s2s_in
and add service description after the closing curly bracket:
{5269, ejabberd_s2s_in, [
{shaper, s2s_shaper},
{max_stanza_size, 131072}
]},
{7047, ejabberd_service,
[{hosts, ["test1.zephyr.local"],
[{password, "secret"}]}]},
%%
%% ejabberd_service: Interact with external components (transports...)
%%
Save ejabberd.cfg and restart ejabberd:
/opt/ejabberd-2.0.5/bin/ejabberdctl restart
/opt/ejabbberd-2.0.5/bin/ejabberd status
Provided ejabberd has restarted successfully, let's create a bot account (it's curently being used to help with weazard registration):
/opt/ejabberd-2.0.5/bin/ejabberd register _weazard_bot zephyr.local weazard
We're done with ejabberd for now. Time to checkout our demo code:
mkdir weazard
cd weazard
svn co https://tagsahead.svn.beanstalkapp.com/erltwit/trunk/web
svn co https://tagsahead.svn.beanstalkapp.com/xmpp_component/trunk
Review config.js in web/js and adjust it, if needed.
Review weazard.app in xmpp_component/trunk/ebin and adjust it.
We will use nginx as our web server:
apt-get install nginx
Below is configuration fragment that has to be included (directly to /etc/nginx/nginx.conf or through include directive):
server {
listen 8000;
root /home/nginx/web/;
location /http-bind {
proxy_pass http://localhost:5280/http-bind/;
}
}
We'll need to move our web application to the place where nginx can access it, i.e. /home/nginx/web
The highlighted piece is necessary because due to Javascript security Strophe can't directly reach ejabberd's HTTP binding service.
Update: Starting ejabberd v 2.1.3 configuring proxy is not necessary, so you won't have to include the highlighted text above. You might still want to configure the proxy if your web clients are behind firewall with the BOSH port (default 5280) disabled. See http://rfid-ale.blogspot.com/2010/04/end-of-cross-domain-hassle-for-bosh.html for details.
We're done!
Running demo
Start ejabberd:
/opt/ejabberd-2.0.5/ejabberdctl start (or restart, if it's already running);
Start nginx:
sudo /etc/init.d/nginx start (or restart, if it's already running);
Start weazard XMPP component:
cd ~/weazard/xmpp_component/ebin
erl -sname main -setcookie weazard
At the prompt, type:
1>application:start(weazard).
If you see the line:
Component : "test1.zephyr.local" started.
in the output, then weazard has managed to connect to ejabberd and is ready to push data to subscribers.
You're now ready to launch your browser and try:
http://yourhostname
Can I congratulate you with running demo? I hope so, but if you are not there yet, fear not! As you can see, a lot of things can potentially go wrong. There's plenty of resources on configuring ejabberd/BOSH/nginx, and I'm here to help to the best of my abilities.
Subscribe to:
Posts (Atom)