The main advantages of deploying your application using Apache instead
of using Rook from with R is stability.
Anecdotally, Rook is unstable and should not be left unsupervised.
Before long the server usually becomes
unresponsive. Apache, on the other hand, has several features which increase its stability, such as
Parallelization. Apache normally comes configured with modules such as prefork.c
which
maintains multiple children processes to handle incoming requests. If any child crashes the
parent process automatically respawns a new one. AnalysisPageServer
takes advantage of this even further and has the children kill themselves if they are using too much
memory (by sending themselves SIGUSR1
—this is an esoteric feature which an Apache process
interprets to mean "finish serving this request and then quit").
Aside from this, Apache is a fully mature piece of software, and many other tools are available for monitoring, logging, deployment, etc. You could also use mod_proxy to solve cross-domain issues for your services (e.g. if you want your search-aheads to be from another system).
The downsides of using Apache instead of Rook are much more complicated installation and initial setup, and slower server start/restart.
In short, Rook is the preferred deployment for prototyping, development, debugging. It could also be considered for single-user mode, where the only user of the web application is going to be the same person who is starting the server from within R, and who doesn't mind restarting it every time it crashes.
If other people are going to be using it, and in particular if you want it to keep running after you go home and on the weekends, you'll need to invest in setting up an Apache deployment.
The good news is that I'll show you how to do it through the next few steps of this document.
Hopefully this is already done for you. If you are running on OS X you probably already have it. If you are running any modern linux distro it probably comes installed, and if not there it can be installed with your package manager.
Go to http://rapache.net and follow the instructions there. A big shout-out to Jeff Horner who is the author of RApache (and Rook, by the way)...and who always answers his e-mails when I have questions!
We are going to create a few configuration-type files for the application so it is convenient to put them all the same directory. Let's create that directory.
library(AnalysisPageServer)
app.basedir <- "rapache-example"
dir.create(app.basedir)
app.basedir <- normalizePath(app.basedir)
app.basedir
## [1] "/tmp/RtmpOF0hTl/Rbuild522d3d0eea7d/AnalysisPageServer/vignettes/rapache-example"
First you'll create a startup script. This will consist of building an AnalysisPageRegistry
, then
from that an AnalysisPageRApacheApp
. and finally calling the special method add.handlers.to.global
of the
application object.
Here is an example. We'll use an example Registry that comes with AnalysisPageServer
:
library(AnalysisPageServer)
reg <- AnalysisPageServer:::trig.registry()
app <- rapache.app.from.registry(reg,
tmpdir = tempdir())
app$add.handlers.to.global()
Place this file in rapache-example/driver.R
.
It is good engineering to keep this script as lean as possible. A nice way to organize it is to develop an R package just for your application. It should provide a function that builds an AnalysisPageRegistry, and then you can also have a four-line script.
Putting any more logic in this driver script makes it difficult to test and maintain.
By "Location" here I mean the prefix of the URL. In the example for this
page we'll put it under /myapp
. That means that all of the resources
and URLs related to the application would start with something like
http://server-name.com/myapp
.
Next you'll need to customize the Javascript configuration file. There is an R function to
write this for you. We'll save it to rapache-example/config.js
.
app.prefix <- "/myapp"
config.lines <- config.js(app.prefix = app.prefix)
config.js.path <- file.path(app.basedir, "config.js")
writeLines(config.lines, file.path(app.basedir, "config.js"))
Next you'll have to set up an httpd.conf file for your server. The function apache.httpd.conf
can write this for you.
Let's put it next to the other files in rapache-example
.
One thing you'll need to know is the path to mod_R.so
, which is the RApache you just installed.
Usually this is in the directory with the other Apache extensions, and this is
reported by the apxs
or apxs2
executable, with arguments -q LIBEXECDIR
.
You might need to use the full path to this tool, which is sometimes installed
in /sbin
or /usr/sbin
. On my (OS X) laptop the full path is /usr/libexec/apache2/mod_R.so
.
Continuing our example:
driver.path <- file.path(app.basedir, "driver.R")
app.location <- "/myapp"
conf.lines <- apache.httpd.conf(driver.path = driver.path,
app.location = app.prefix,
config.js.path = config.js.path,
mod.R.path = "/usr/libexec/apache2/mod_R.so")
httpd.conf.path <- file.path(app.basedir, "myapp-httpd.conf")
writeLines(conf.lines, httpd.conf.path)
At this point you have an httpd.conf which is not too bad, but it doesn't really stand on its own. If you are running off your laptop or a small machine on which you have root access then you can just slip this line in the end of your system httpd.conf:
Include /Users/friedmab/EP/AnalysisPageServer/vignettes/rapache-example/myapp-httpd.conf
And restart your apache server, maybe something like
sudo apache restart
Finally you can point your browser to the landing page
http://localhost/myapp/client/analysis-page-server.html
.
This looks just like the Rook deployment, but it will work if you connect from another machine and it will be generally more stable.
If you don't have the right to modify the configuration of the shared Apache server then you'll have to make your own apache. You may be able to do this by copying the system apachectl script and modifying the path to the httpd.conf file. Then make a copy of the system httpd.conf file and point your private apachectl to use that. Be sure to Include your application's specific httpd.conf file. Set your PidFile, LockFile, ErrorLog and CustomLog to write to your local directory and not conflict with the system apache. Update your Listen directive to your a high port. Good luck!