Running a Java server on RedHat OpenShift DIY

von

I am involved in the Zentaur Server project. It is a brand new a lightweight HTTP server written in Java by Simone Tripodi. It is so easy that I immediately was attracted. In not time we agreed to rename it from SHS to Zentaur and put some more effort in it. Of course a web server implementation needs to serve its own web pages and so we were looking for a provider.

Red Hat provides OpenShift, which is a PaaS (Project as a Service) platform. Everybody can join there and create some apps for free (limited to three at the time of this writing). OpenShift seems to be very supportive to Open Source: they provide several “quick start” repositories on Github. As Red Hat is an open source company, it is not surprising that OpenShift itself is Open Source.

I was looking for a good while at OpenShift for my own App Time & Bill. But I don’t think it’s ready for production yet: I am in need of a price list. And another thing which prevents me to use it for mission critical apps: I need to learn more on scaling on OpenShift. Besides that, it is perfect for Zentaur Server. Why?

OpenShift provides you some “cartridges”, which allow you to get on speed with your app quickly. Basically you can say you can create an app, which is basically a git repository and a domain name. Then you add some functionality to it, like for example Wordpress, Jenkins or something else. In the Zentaur case we would need the DIY cartridge: Do it yourself. It allows me to run nearly everything I want: if it runs on Red Hat Enterprise 6, it runs on OpenShift. If that is not enough: with Open Shift you have access to SSH and can use GCC. That being said, OpenShift allows you to get started quickly and easily or to get some more complicated tasks done.

How is the workflow?

Basically you get a git repository from Red Hat OpenShift. You push to it and then OpenShift runs several git hooks. There are hooks for “pre-build”, “build”, “deploy”, “post-deploy”, “start” and “stop”. If you want to do something special you can add your commandos here. As we just want to try out Zentaur, I decided to commit everything we need to the repository. There might be other options for that. I found a “runtime” directory when exploring the folder structure with SSH. Guess, I can put my own runtime specifics there, without committing it to the repository.

Anyway, I want to use the commit, push and automatic deploy workflow.

How is it done?

Basically this is my code: OpenShift Demo. After I created my login, namespace and app with the Red Hat OpenShift command line client, I just cloned the repository OpenShift provides me.

I simply copied everything I needed to this repository and committed. I did not push yet, because it would not do anything except stopping and starting the default ruby server. To disable this server, you can force to close all app processes. Of course you can simply stop, but I didn’t care much on the test app and wanted to make sure everything is closed:

$> rhc app force-stop -a zentaur

Zentaur is my app name, as you might have guessed. Now, everything is stopped. You need to change your start hook afterwards, which would start the ruby server in case of a push. Here is the new code:

$OPENSHIFT_REPO_DIR/bin/shs -p 8080 -H $OPENSHIFT_INTERNAL_IP --sitedir $OPENSHIFT_REPO_DIR/site -t 20 -X > $OPENSHIFT_LOG_DIR/zentaur-server.log &

The shs script is starting Zentaur. The name is coming from the original name Simple HTTP Server, which has been changed to Zentaur recently. Therefore this scripts name will change in future. The interesting part here are the variables we need to use: $OPENSHIFT_REPO_DIR is the absolute path to my app. $OPENSHIFT_INTERNAL_IP is the IP I need to bind my server; otherwise it will not work. Same is with the port 8080. OpenShift is running behind a Proxy which uses this port and a specific IP to send requests.

This is actually much better and comfortable compared to for example Amazon EC2. I needed some time to figure out how to do port forwarding to get my Jetty server connected on port 8080. Well, EC2 is not PaaS, so yes, you get some comfort with OpenShift.

The rest is pretty Zentaur specific, like the folder in which my site resides or how many threads are used. Please mind the & sign at the end, which starts my process in the background.

The stop script is pretty simple too. There is room for improvement:

kill `ps -ef | grep org.nnsoft.shs.demo.SimpleHttpServerLauncher | grep -v grep | awk '{ print $2 }'` > /dev/null 2>&1
exit 0

Basically I am looking for a process number of my server (look at the class name) and, well, kill it. There are surely less drastic ways to do that, but for now I am happy.

Now we can commit everything and push it.

It should look similar to that:

$ git push
Counting objects: 9, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 520 bytes, done.
Total 5 (delta 3), reused 0 (delta 0)
remote: Stopping application...
remote: Done
remote: ~/git/zentaur.git ~/git/zentaur.git
remote: ~/git/zentaur.git
remote: Running .openshift/action_hooks/pre_build
remote: Running .openshift/action_hooks/build
remote: Running .openshift/action_hooks/deploy
remote: Starting application...
remote: Done
remote: Running .openshift/action_hooks/post_deploy
...

When pushing, OpenShift stops and starts the app. Some other hooks are executed too. You could run maven for example, or something else, like Flyway. However, for me start/stop is enough.

I have come so far, I want to look into my logfiles now. I could connect via SSH, but the Red Hat client tools are much more comfortable. Here we go:

$> rhc-tail-files -a zentaur

After entering my password, I will see something really nice:

12:12:40.022 [main] [INFO]
12:12:40.027 [main] [INFO]                          ''~``
12:12:40.027 [main] [INFO]                         ( o o )
12:12:40.027 [main] [INFO] +------------------.oooO--(_)--Oooo.------------------+
12:12:40.027 [main] [INFO]
12:12:40.028 [main] [INFO] shs-demo v0.1 (built on 2012-05-28T22:50:50+0200)
12:12:40.028 [main] [INFO]
12:12:40.028 [main] [INFO]                      .oooO                            
12:12:40.028 [main] [INFO]                      (   )   Oooo.                    
12:12:40.028 [main] [INFO] +---------------------\ (----(   )--------------------+
12:12:40.028 [main] [INFO]                        \_)    ) /
12:12:40.028 [main] [INFO]                              (_/
12:12:40.496 [main] [INFO] Initializing server using 20 threads...
12:12:40.497 [main] [INFO] Done! Initializing the SessionManager ...
12:12:40.500 [main] [INFO] Done! Binding host XXX.XXX.XXX.XXX listening on port 8080 ...
12:12:40.516 [main] [INFO] Done! Server has been successfully initialized, it can be now started
12:12:40.516 [main] [INFO] Server successfully started! Waiting for new requests...
12:12:50.484 [main] [INFO] Accepting new request from XXX.XXX.XXX.XXX

Heya, we made it! Zentaur is running! Lets send a request with the browser:

04:52:31.307 [main] [INFO] Accepting new request from XXX.XXX.XXX.XXX
04:52:31.309 [pool-2-thread-5] [DEBUG] < GET /css/bootstrap.min.css HTTP/1.0
04:52:31.309 [pool-2-thread-5] [DEBUG] < Accept-Language: en, *
04:52:31.309 [pool-2-thread-5] [DEBUG] < Host: zentaur-grobmeier.rhcloud.com
04:52:31.309 [pool-2-thread-5] [DEBUG] < Accept-Encoding: gzip
04:52:31.310 [pool-2-thread-5] [DEBUG] < Referer: http://zentaur-grobmeier.rhcloud.com/
04:52:31.310 [pool-2-thread-5] [DEBUG] < X-Forwarded-Server: zentaur-grobmeier.rhcloud.com
04:52:31.310 [pool-2-thread-5] [DEBUG] < X-Forwarded-For: XXX.XXX.XXX.XXX
04:52:31.310 [pool-2-thread-5] [DEBUG] < X-Forwarded-Proto: http
04:52:31.310 [pool-2-thread-5] [DEBUG] < User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.34 (KHTML, like Gecko) imgsizer Safari/534.34
04:52:31.310 [pool-2-thread-5] [DEBUG] < Accept: text/css, */*;q=0.1
04:52:31.310 [pool-2-thread-5] [DEBUG] < X-Forwarded-Host: zentaur-grobmeier.rhcloud.com
04:52:31.311 [pool-2-thread-5] [DEBUG] Choosing the right handler to dispatch /css/bootstrap.min.css request...
04:52:31.311 [pool-2-thread-5] [DEBUG] Request /css/bootstrap.min.css will be dispatched by org.nnsoft.shs.demo.FileRequestHandler
04:52:31.311 [pool-2-thread-5] [DEBUG] No default response configured to reply to status OK
04:52:31.317 [pool-2-thread-5] [DEBUG] > HTTP/1.0 200 OK
04:52:31.317 [pool-2-thread-5] [DEBUG] > Date: Tue, 26 Jun 2012 04:52:31 EDT
04:52:31.317 [pool-2-thread-5] [DEBUG] > Content-Length: 13536
04:52:31.318 [pool-2-thread-5] [DEBUG] > Content-Encoding: gzip
04:52:31.318 [pool-2-thread-5] [DEBUG] > Content-Type: text/css
04:52:31.318 [pool-2-thread-5] [DEBUG] > Server: Simple HttpServer
04:52:31.318 [pool-2-thread-5] [DEBUG] > Set-Cookie: SHSSESSIONID=de35a44c-799e-4dc7-8956-7a6e6b559911; Path=/; Domain=127.7.123.129; Port="8080"; Expires=Mon, 18 Jun 2012 03:49:44 EDT; HttpOnly
04:52:31.318 [pool-2-thread-5] [DEBUG] Request processed in 2ms

2ms - super-fast. As expected :-).You can look at the running app at http://zentaur-grobmeier.rhcloud.com/(Not longer working).

The whole code is located at GitHub. Once we have a proper version of Zentaur we’ll provide a better quick start sample for OpenShift. But of course you can already use that one, if you want to experiment. It is already supporting Velocity and JAXB.

Issues

Yesterday I had the issue that not all my requests are passed by the proxy. I needed to create a second tab and fire a second request to get both responses. Otherwise the proxy would return an error code after minutes. I have learned that the RedHat people are very responsive and nice with helping on IRC or the forum.

Today it suddenly worked so I blame yesterdays OpenShift upgrade to somehow impact the proxy.

A recommendation I got on the forum was to bypass the proxy and see if it helps. I note it here for others.

If you suspect its the proxy, you can bypass the proxy completely (remove it out of the mix) in a couple of ways:
  • 1. ssh into your app instance and use curl -vvv http://$OPENSHIFT_INTERNAL_IP:$OPENSHIFT_INTERNAL_PORT/ and see if that works
  • 2. You can do an rhc port-forward -a $app and then just connect to the http://$OPENSHIFT_INTERNAL_IP:$OPENSHIFT_INTERNAL_PORT/ on your local workstation.

Source: https://openshift.redhat.com/community/forums/openshift/diy-running-custom-java-server-hangs-somehow-on-proxy#comment-22046

Conclusion

After all this was an impressive first step into OpenShift. I got into it in no time. Time & Bill tells me I needed 100 minutes - this includes all the debugging work for the Proxy problem, which should be substracted. My estimation is that one can get to a running app in 30 minutes without having any clue about OpenShift. This is great. RedHat gets a +1 for the great proxy solution, which does not require me to deal with port forwarding directly. Another +1 for the great docs, the supportive Red Hat people and the ready-to-go cartridges. After all I am very happy and will follow OpenShifts progress more closely from now on.

Tags: #Java #Open Source #RedHat OpenShift

Newsletter

ABMELDEN