{"id":11049,"date":"2013-02-23T09:00:00","date_gmt":"2013-02-23T08:00:00","guid":{"rendered":"http:\/\/pjagielski.github.com\/2013\/02\/23\/vertx-on-raspberry-pi"},"modified":"2023-04-27T11:32:55","modified_gmt":"2023-04-27T09:32:55","slug":"vert-x-on-raspberry-pi","status":"publish","type":"post","link":"https:\/\/touk.pl\/blog\/2013\/02\/23\/vert-x-on-raspberry-pi\/","title":{"rendered":"Vert.x on Raspberry Pi"},"content":{"rendered":"<h2 id=\"lightweight-jvm-web-server\">Lightweight JVM web server<\/h2>\n<p>Some people say that using Java on Raspberry Pi is a stupid idea. Sure, JVM uses a lot of system resources but when you can watch HD movies on RPi why don\u2019t run a tiny Java app? But I do mean <strong>really<\/strong> tiny &#8211; no Tomcat nor any other application server involved, no war and deployment stuff. That\u2019s why I came out with idea of using <a href=\"http:\/\/vertx.io\/\">vert.x<\/a> &#8211; a relatively new framework for writing modern web application. In this post I\u2019ll try to show lessons learned after developing a sample app using vert.x and then running it on the Raspberry Pi.<\/p>\n<h2 id=\"working-with-vertx-on-rpi\"><span id=\"working-with-vert-x-on-rpi\">Working with vert.x on RPi<\/span><\/h2>\n<p>Vert.x is <a href=\"http:\/\/nodejs.org\/\">node.js<\/a> on steroids for JVM. In addition to all the libs for the JVM it offers you a lot more:<\/p>\n<ul>\n<li>polyglot &#8211; write your application in any language that runs on the JVM (or mix a few)<\/li>\n<li>really simple programming model<\/li>\n<li>inter-app communication via event bus and shared data<\/li>\n<li>ease of scalability and concurrency handling<\/li>\n<\/ul>\n<p>If you want a gentle start in the world of vert.x I definitely suggest you reading the <a href=\"http:\/\/vertx.io\/manual.html\">manual<\/a> on project website.<\/p>\n<h3 id=\"installation\">Installation<\/h3>\n<p>First of all &#8211; install Java 8 early access build for ARM from <a href=\"http:\/\/jdk8.java.net\/fxarmpreview\">Oracle website<\/a>. Vert.x indeed requires Java 7, but the 8 build has a real hard float support.<\/p>\n<p>The easiest way to manage vert.x installation is to use <a href=\"http:\/\/gvmtool.net\/\">GVM<\/a>:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">curl -s get.gvmtool.net | bash\r\ngvm install vertx\r\n<\/pre>\n<\/div>\n<p>Now you should be able to run <code>vertx<\/code> from the command line.<\/p>\n<h3 id=\"development-process\">Development process<\/h3>\n<p>In my approach I\u2019m developing the app on my laptop and want to have straight path of running the code on RPI. Since I love the Intellij Idea 12 I put my sources into common maven\/gradle structure and use <code>Verticle<\/code> interface to get full benefits of my IDE: code completion, refactoring and testing support. I use Groovy as a language for my verticles but I want the sources to be compiled on my laptop instead of RPI which a bit improves startup time of the app.<\/p>\n<p>The examples for vert.x distribution are not reaaly development-friendly but I\u2019ve found great example of <a href=\"https:\/\/github.com\/rmangi\/vertx-groovy-starter\">Groovy starter project<\/a> on GitHub which introduces two huge ideas: separating configuration of the app in single JSON file and a <code>runVertx<\/code> gradle task to build and run the app in a single step. I also use the <a href=\"https:\/\/github.com\/vert-x\/mod-web-server\">web-server vert.x module<\/a> to serve static web files of the app frontend. So I have SockJS and REST verticles in the backend and JavaScript frontend in a single project root.<\/p>\n<p>Here is the final layout explained:<\/p>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">src\/main\/groovy - verticles code\r\n    App.groovy - app lancher\r\nsrc\/main\/test - verticles tests\r\nweb - frontend stuff\r\nbuild.gradle - gradle script with runVertx task\r\nrun.sh - script for running app on RPI (no compilation)\r\n<\/pre>\n<\/div>\n<p>And a typical development process looks like this:<\/p>\n<ul>\n<li>write verticles code (*)<\/li>\n<li>write unit tests for verticles (*)<\/li>\n<li>run the app on laptop and modify the frontend<\/li>\n<li>copy binaries to RPi and run the app from command line<\/li>\n<\/ul>\n<p>(*) change the order of these two for TDD ;)<\/p>\n<p>The only thing I\u2019m only struggling from is lack of runtime reloading of verticles. Maybe using JRebel could help there but I ain\u2019t got the licence (yet).<\/p>\n<p>You can see my example project <a href=\"https:\/\/github.com\/pjagielski\/vertx-raspberry-console\">here<\/a>.<\/p>\n<h2 id=\"benchmark\">Benchmark<\/h2>\n<p>I also did some benchmarking of vert.x app on RPI throughput. Sure, you cannot expect that single RPI could handle a lot of transactions per sec, so the test was just for fun. In the test I served a static CSS (bootstrap) and invoked a really simple REST resource (example <code>details\/Joe\/123<\/code> mapping from <code>RouteMatcher<\/code>). I used siege with 2 and 200 consumers and compared the results between the very.x (1 instance), node.js express and nginx (just for static CSS). I installed node.js 0.8.18 from binaries found <a href=\"https:\/\/gist.github.com\/adammw\/3245130\">here<\/a>.<\/p>\n<ul>\n<li>It is nice that serving static files is quite as fast as in the nginx. There is <a href=\"http:\/\/monkey-project.com\/benchmarks\/raspberry_pi_monkey_nginx\">a benchmark<\/a> showing that Monkey web server is a bit faster, but in my environment I wasn\u2019t able to achieve more than 45 req\/sec on nginx, so ~40 req\/sec on vert.x is really good result.<\/li>\n<li>Vert.x seems to be about 2-2.5 times faster than node.js with express. This is similar to Tim Fox\u2019 <a href=\"http:\/\/vertxproject.wordpress.com\/2012\/05\/09\/vert-x-vs-node-js-simple-http-benchmarks\/\">benchmark<\/a> with both node.js and vert.x in single instance. (BTW: I have no idea how to get 30k req\/sec on a workstation as in Tim\u2019s test).<\/li>\n<li>The benchmark shows that RPi is indeed a toy PC &#8211; on my workstation it\u2019s really easy to achieve thousands of requests per second. So forget about handling hundreds of requests per seconds on a single RPi instance.<\/li>\n<\/ul>\n<h2 id=\"a-bit-speeding-up-startup-time\">(a bit) Speeding up startup time<\/h2>\n<p>The thing that really puts node.js in front is the startup time. Java is slow at both JVM startup and while classloading. My first application deployed on RPi took about 30 sec to start, while on my laptop it was about 2-3 seconds. It is possible to cut it down to 18 seconds, here are a few hints:<\/p>\n<ul>\n<li>don\u2019t compile sources directly on RPi &#8211; build a jar on your workstation. In my setup I run the server from gradle on my laptop but also have a bash script to run it on raspberry which passes vert.x a <code>-cp<\/code> parameter pointing to builded jar.<\/li>\n<li>don\u2019t run a SockJS server when not needed. It tooks about 5 sec to start. You can disable it by setting <code>bridge<\/code> to false in mod-web configuration.<\/li>\n<li>you can write your own mod-web in just a few lines of code. You will save some milliseconds but also this setup allows you to pass custom RESTful routes to <code>RouteMatcher<\/code>. Look at this example:<\/li>\n<\/ul>\n<div class=\"highlight\">\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">def rm = new RouteMatcher()\r\nrm.get('\/details\/:user\/:id', { HttpServerRequest req -&gt;\r\n    req.response.end \"User: ${req.params()['user']} ID: ${req.params()['id']}\"\r\n} as Handler&lt;HttpServerRequest&gt;)\r\n\r\n\/\/ Catch \/ - serve the index page\r\nrm.get('\/', { HttpServerRequest req -&gt;\r\n    req.response.sendFile(\"web\/index.html\")\r\n} as Handler&lt;HttpServerRequest&gt;)\r\n\r\n\/\/ Catch all - just send the file from web directory\r\nrm.getWithRegEx('.*', { HttpServerRequest req -&gt;\r\n    req.response.sendFile \"web\/${req.path}\"\r\n} as Handler&lt;HttpServerRequest&gt;)    \r\n<\/pre>\n<\/div>\n<p>To debug the most time consuming steps on app startup, you should configure log4j logging. Vert.x outputs some info about deploying verticles, you can also put your own logging messages. Just copy log4j.jar to vert.x lib directory and add<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\">-Dorg.vertx.logger-delegate-factory-class-name=org.vertx.java.core.logging.impl.Log4jLogDelegateFactory<\/pre>\n<p>parameter in vert.x startup script.<\/p>\n<h2 id=\"sample-project\">Sample project<\/h2>\n<p>You can check these concepts by cloning a <a href=\"https:\/\/github.com\/pjagielski\/vertx-top-monitor\">top monitor<\/a> GitHub project. It is a <a href=\"http:\/\/shopify.github.com\/dashing\/\">Dashing<\/a>-inspired web app showing results from calling a <code>top<\/code> command by lucid <a href=\"http:\/\/anthonyterrien.com\/knob\/\">JQuery knobs<\/a>.<br \/>\nEvery 2 seconds stats from the <code>top<\/code> call are pushed through <code>eventBus<\/code> (and internally by SockJS) to frontend.<\/p>\n<p>The project itself it not smashing, you can just check the structure and the tests when I\u2019m mocking ARM-specific <code>top<\/code> command results. Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"Lightweight JVM web server Some people say that using Java on Raspberry Pi is a stupid idea. Sure,&hellip;\n","protected":false},"author":5,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[50,68,176],"class_list":{"0":"post-11049","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-development-design","7":"tag-groovy","8":"tag-java","9":"tag-javascript"},"_links":{"self":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11049","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/comments?post=11049"}],"version-history":[{"count":17,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11049\/revisions"}],"predecessor-version":[{"id":15676,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/posts\/11049\/revisions\/15676"}],"wp:attachment":[{"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/media?parent=11049"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/categories?post=11049"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/touk.pl\/blog\/wp-json\/wp\/v2\/tags?post=11049"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}