Nginx-Clojure is a Nginx module for embedding Clojure or Java programs, typically those Ring based handlers.
There are some core features :
-
Compatible with Ring and obviously supports those Ring based frameworks, such as Compojure etc.
-
One of benifits of Nginx is worker processes are automatically restarted by a master process if they crash
-
Utilizes lazy headers and direct memory operation between Nginx and JVM to fast handle dynamic contents from Clojure or Java code.
-
Utilizes Nginx zero copy file sending mechanism to fast handle static contents controlled by Clojure or Java code.
-
Supports Linux x64, Win32 and Mac OS X
-
Installation =============
The lastest version is 0.1.0.
- First you can download the latest one from here. The zip file includes Nginx-Clojure binaries about Linux x64, Win32 and Mac OS X.
- Unzip the zip file downloaded then rename the file
nginx-${os-arc}
tonginx
, eg. for linux isnginx-linux-x64
Nginx-Clojure may be compiled successfully on Linux x64, Win32 and Mac OS X x64.
-
First download from nginx site or check out nginx source by hg from http://hg.nginx.org/nginx. For Win32 users MUST check out nginx source by hg because the zipped source doesn't contain Win32 related code.
-
Check out Nginx-Clojure source from github OR download the zipped source code from https://github.com/xfeep/nginx-clojure/releases
-
If you want to use Http SSL module, you should install openssl and openssl dev first.
-
Setting Java header include path in nginx-clojure/src/c/config
#eg. on ubuntu JNI_HEADER_1="/usr/lib/jvm/java-7-oracle/include" JNI_HEADER_2="${JNI_HEADER_1}/linux"
-
Add Nginx-Clojure module to Nginx configure command, here is a simplest example without more details about InstallOptions
#If nginx source is checked out from hg, please replace ./configure with auto/configure $./configure \ --add-module=nginx-clojure/src/c $ make $ make install
-
Create the jar about Nginx-Clojure
$ cd nginx-clojure $ lein jar
Then you'll find nginx-clojure-${version}.jar (eg. nginx-clojure-0.1.0.jar) in the target folder.
-
Configurations =================
Setting JVM path and class path within http {
block in nginx.conf
#for win32, jvm_path maybe "C:/Program Files/Java/jdk1.7.0_25/jre/bin/server/jvm.dll";
#for macosx, jvm_path maybe "/Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Libraries/libserver.dylib";
#for linux, jvm_path maybe "/usr/lib/jvm/java-7-oracle/jre/lib/amd64/server/libjvm.so";
jvm_path "/usr/lib/jvm/java-7-oracle/jre/lib/amd64/server/libjvm.so";
#jvm_options can be repeated once per option.
#for win32, class path seperator is ";", jvm_options maybe "-Djava.class.path=jars/nginx-clojure-0.1.0.jar;jars/clojure-1.5.1.jar";
jvm_options "-Djava.class.path=jars/nginx-clojure-0.1.0.jar:jars/clojure-1.5.1.jar";
#for memory setting
#jvm_options "-Xms256m"
#jvm_options "-Xmx256m"
#for engble java remote debug uncomment next two lines
#jvm_options "-Xdebug";
#jvm_options "-Xrunjdwp:server=y,transport=dt_socket,address=8400,suspend=n";
Now you can start nginx and access http://localhost:8080/clojure, if some error happens please check error.log file.
Within http {
block in nginx.conf jvm_workers
is a directive about threads number for request handler thread pool on JVM, default is 0.
ONLY IF you cann't resolve your performance problems by increasing worker_processes or reducing single request-response time,
you can consider the way.
eg.
jvm_workers 8;
Now Nginx-Clojure will create a thread pool with fixed eight threads per JVM instance/Nginx worker to handle requests.
Within location
block, directive clojure
is an enable flag and directive clojure_code
is used to setting a Ring handler.
###2.3.1 Inline Ring Handler
location /clojure {
clojure;
clojure_code '
(fn[req]
{
:status 200,
:headers {"content-type" "text/plain"},
:body "Hello Clojure & Nginx!"
})
';
}
###2.3.2 Reference of External Ring Handlers
(ns my.hello)
(defn hello-world [request]
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello World"})
You should set your clojure JAR files to class path, see [2.1 JVM path & class path](#2.1 JVM path & class path) .
location /myClojure {
clojure;
clojure_code '
(do
(use \'[my.hello])
hello-world))
';
}
For more details and more useful examples for Compojure which is a small routing library for Ring that allows web applications to be composed of small, independent parts. Please refer to https://github.com/weavejester/compojure
###2.3.3 Pure Java Handler
package my;
import nginx.clojure.Constants;
import clojure.lang.AFn;
import clojure.lang.IPersistentMap;
import clojure.lang.PersistentArrayMap;
public class HelloHandler extends AFn {
@Override
public Object invoke(Object r) {
IPersistentMap req = (IPersistentMap)r;
//get some info from req. eg. req.valAt(Constants.QUERY_STRING)
//....
//prepare resps, more details about Ring handler on this site https://github.com/ring-clojure/ring/blob/master/SPEC
Object[] resps = new Object[] {Constants.STATUS, 200,
Constants.HEADERS, new PersistentArrayMap(new Object[]{Constants.CONTENT_TYPE.getName(),"text/plain"}),
Constants.BODY, "Hello Java & Nginx!"};
return new PersistentArrayMap(resps);
}
}
In nginx.conf, eg.
location /java {
clojure;
clojure_code '
(do (import \'[my HelloHandler]) (HelloHandler.) )
';
}
You should set your JAR files to class path, see [2.1 JVM path & class path](#2.1 JVM path & class path) .