Vert.x for World Domination


In this article I am going to show how I put Vert.x on my Raspberry Pis and my Mindstorm EV3.

The whole thing is the product of a long night of hacking so expect some updates to this article.

The associated project is on GitHub.


The core of my presentation Vert.x for World Domination was the setup I used to demonstrate the distribution capabilities of Vert.x.

What I wanted to do was a demo using “real life” conditions. No VMs or other tricks. I got the basic idea from the setup Michael uses to demo Hazelcast (see some photos here)

The idea of a portable Raspberry Pi cluster stuck with me and I built my somewhat smaller version.

The Brain

And here it comes, the portable brain:

IMG_2113

 

Parts list

  • 2 x Raspberry Pi Model B (inside the red lego-thing)
  • 2 x Loglink WL0084A Wifi-adapters
  • TP-Link TL-WR702N (the small white/blue box on the left, a very compact Wifi-router)
  • EasyAcc 5A USB power adapter (the white box on the right, make sure to user the iPad-connectors to power the Pis)

Setup

Connect the Pis to the Wifi.

Slap Raspbian on the Pis, install the embedded JDK and put Vert.x on them.

The brain is good to go.

Robby

My fearsome battle robot Robby is up next.

It’s a custom EV3-bot. Go crazy on how you want it to look like but follow my instructions on how to get Vert.x up and running. That part took me a while.

 

 

IMG_2115

 

Parts list

  • The EV3 base package
  • TP-Link TL-WN725N USB-Wifi (Michael reported some issues on his EV3, works fine on mine)
  • A micro SD card

LejOS

With EV3 Lego provided everything to make it as easy as possible to get a custom OS on your mindstorm. The LejOS project is one of those. It is aimed at Java developers and provides everything needed to get going.

Simply follow the instructions from their Wiki to get everything set up. It’s that easy.

After connecting it to Wifi you should see something like this on the display:

IMG_2116

Vert.x

Here comes the tricky part. First of all: You will have to use a fat jar as LejOS doesn’t provide a Bash and renders the provided vert.x-startup-skripts useless.Copy the generated jar to your EV3 (ahem, the root-password is “”, so just hit enter when asked):

scp <fatjar>.jar root@<ip-of-ev3>:~

Copy the cluster.xml found in your local Vert.x-installation:

scp <vertx-dir>/conf/cluster.xml root@<ip-of-ev3>:~

Afterwards log into the EV3.

There’s two issues we will be solving:

  1. Vert.x won’t bind to the Wifi-address using the -cluster-host parameter
  2. Multicast is not working

Get a Vert.x instance running on your local machine, note down the IP-address and log into your EV3:

ssh root@<ip-of-ev3>

Now open the cluster.xml for editing (vi is installed and my weapon of choice).
Disable multicast and enable tcp-ip. Add the address of your local machine (192.168.2.20 in the example).
Uncomment the interfaces block and add the address of your EV3-Wifi (the one you used to log into it)

Afterwards the config should look something like this:


<join>
<multicast enabled=”false”>
<multicast-group>224.2.2.3</multicast-group>
<multicast-port>54327</multicast-port>
</multicast>
<tcp-ip enabled=”true”>
<interface>192.168.2.20</interface>
</tcp-ip>
<aws enabled=”false”>
<access-key>my-access-key</access-key>
<secret-key>my-secret-key</secret-key>
<region>us-east-1</region>
</aws>
</join>
<interfaces enabled=”true”>
<interface>192.168.2.101</interface>
</interfaces>

Now we need to modify the start skript. Add a new file called run.sh with the following content:

#! /bin/sh
. /etc/default/lejos
export LD_LIBRARY_PATH=${LEJOS_HOME}/libjna/usr/lib/arm-linux-gnueabi/:${LEJOS_HOME}/libjna/usr/lib/jni/
/home/root/lejos/ejre1.7.0_51/bin/java -jar <nameof-fat>.jar -cp . -cluster -cluster-host 192.168.2.101

Replace the IP-Adress with the one of your EV3-Wifi (the one you used to log into it) and replace <nameof-fat> with the name of your fat-jar.

Do a chmod +x run.sh

You are ready to go.

Use ./run.sh to start Vert.x and wait. It takes around 3 minutes for everything to come up so be patient.

This is the log-output I get when running everything ( => "Succeeded in deploying module"): 


root@EV3:~# ./run.sh
Apr 07, 2014 4:53:29 PM org.vertx.java.core.logging.impl.JULLogDelegate info
INFO: Starting clustering...
Apr 07, 2014 4:54:11 PM com.hazelcast.impl.AddressPicker
INFO: Interfaces is enabled, trying to pick one address matching to one of: [192.168.2.101]
Apr 07, 2014 4:54:12 PM com.hazelcast.impl.AddressPicker
INFO: Prefer IPv4 stack is true.
Apr 07, 2014 4:54:13 PM com.hazelcast.impl.AddressPicker
INFO: Picked Address[192.168.2.101]:5701, using socket ServerSocket[addr=/0.0.0.0,localport=5701], bind any local is true
Apr 07, 2014 4:54:35 PM com.hazelcast.system
INFO: [192.168.2.101]:5701 [dev] Hazelcast Community Edition 2.6.7 (20140210) starting at Address[192.168.2.101]:5701
Apr 07, 2014 4:54:35 PM com.hazelcast.system
INFO: [192.168.2.101]:5701 [dev] Copyright (C) 2008-2013 Hazelcast.com
Apr 07, 2014 4:54:36 PM com.hazelcast.impl.LifecycleServiceImpl
INFO: [192.168.2.101]:5701 [dev] Address[192.168.2.101]:5701 is STARTING
Apr 07, 2014 4:54:38 PM com.hazelcast.impl.TcpIpJoiner
INFO: [192.168.2.101]:5701 [dev] Connecting to possible member: Address[192.168.2.20]:5701
Apr 07, 2014 4:54:38 PM com.hazelcast.impl.TcpIpJoiner
INFO: [192.168.2.101]:5701 [dev] Connecting to possible member: Address[192.168.2.20]:5702
Apr 07, 2014 4:54:39 PM com.hazelcast.impl.TcpIpJoiner
INFO: [192.168.2.101]:5701 [dev] Connecting to possible member: Address[192.168.2.20]:5703
Apr 07, 2014 4:54:40 PM com.hazelcast.nio.ConnectionManager
INFO: [192.168.2.101]:5701 [dev] 59397 accepted socket connection from /192.168.2.20:5701
Apr 07, 2014 4:54:40 PM com.hazelcast.nio.ConnectionManager
INFO: [192.168.2.101]:5701 [dev] 44524 accepted socket connection from /192.168.2.20:5702
Apr 07, 2014 4:54:40 PM com.hazelcast.nio.ConnectionManager
INFO: [192.168.2.101]:5701 [dev] 33806 accepted socket connection from /192.168.2.20:5703
Apr 07, 2014 4:54:44 PM com.hazelcast.cluster.ClusterManager
INFO: [192.168.2.101]:5701 [dev]

Members [4] {
Member [192.168.2.20]:5701
Member [192.168.2.20]:5702
Member [192.168.2.20]:5703
Member [192.168.2.101]:5701 this
}

Apr 07, 2014 4:55:20 PM com.hazelcast.impl.LifecycleServiceImpl
INFO: [192.168.2.101]:5701 [dev] Address[192.168.2.101]:5701 is STARTED
Apr 07, 2014 4:55:36 PM com.hazelcast.util.HealthMonitor
INFO: [192.168.2.101]:5701 [dev] memory.used=5.6M, memory.free=3.3M, memory.total=8.9M, memory.max=29.0M, memory.used/total=63.02% memory.used/max=19.29% load.process=92.00%, load.system=100.00%, load.systemAverage=250.00% q.packet.size=2, q.processable.size=1, q.processablePriority.size=0, thread.count=19, thread.peakCount=19, q.query.size=0, q.mapLoader.size=0, q.defaultExecutor.size=0, q.asyncExecutor.size=0, q.eventExecutor.size=0, q.mapStoreExecutor.size=0
Apr 07, 2014 4:56:06 PM com.hazelcast.util.HealthMonitor
INFO: [192.168.2.101]:5701 [dev] memory.used=8.0M, memory.free=4.2M, memory.total=12.2M, memory.max=29.0M, memory.used/total=65.18% memory.used/max=27.42% load.process=93.00%, load.system=100.00%, load.systemAverage=281.00% q.packet.size=1, q.processable.size=1, q.processablePriority.size=0, thread.count=21, thread.peakCount=21, q.query.size=0, q.mapLoader.size=0, q.defaultExecutor.size=0, q.asyncExecutor.size=0, q.eventExecutor.size=0, q.mapStoreExecutor.size=0
Apr 07, 2014 4:56:37 PM com.hazelcast.util.HealthMonitor
INFO: [192.168.2.101]:5701 [dev] memory.used=9.9M, memory.free=2.3M, memory.total=12.2M, memory.max=29.0M, memory.used/total=81.41% memory.used/max=34.25% load.process=94.00%, load.system=100.00%, load.systemAverage=288.00% q.packet.size=0, q.processable.size=1, q.processablePriority.size=1, thread.count=21, thread.peakCount=21, q.query.size=0, q.mapLoader.size=0, q.defaultExecutor.size=0, q.asyncExecutor.size=0, q.eventExecutor.size=0, q.mapStoreExecutor.size=0
Apr 07, 2014 4:57:04 PM org.vertx.java.core.logging.impl.JULLogDelegate info
INFO: Succeeded in deploying module