Skip to content

Nginx module for embedding Clojure or Java programs, typically those Ring based handlers.

License

Notifications You must be signed in to change notification settings

dist/nginx-clojure

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nginx-Clojure

Alt textNginx-Clojure is a Nginx module for embedding Clojure or Java programs, typically those Ring based handlers.

There are some core features :

  1. Compatible with Ring and obviously supports those Ring based frameworks, such as Compojure etc.
  2. One of benifits of Nginx is worker processes are automatically restarted by a master process if they crash
  3. Utilizes lazy headers and direct memory operation between Nginx and JVM to fast handle dynamic contents from Clojure or Java code.
  4. Utilizes Nginx zero copy file sending mechanism to fast handle static contents controlled by Clojure or Java code.
  5. Supports Linux x64, Win32 and Mac OS X

By the way it is very fast, the benchmarks can be found HERE .

  1. Installation =============

The lastest release is 0.1.2. Please check the Update History for more details.

1.1 Installation by Binary

  1. First you can download Release 0.1.2 from here. The zip file includes Nginx-Clojure binaries about Linux x64, Win32 and Mac OS X.
  2. Unzip the zip file downloaded then rename the file nginx-${os-arc} to nginx, eg. for linux is nginx-linux-x64

1.2 Installation by Source

Nginx-Clojure may be compiled successfully on Linux x64, Win32 and Mac OS X x64.

  1. 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.

  2. Check out Nginx-Clojure source from github OR download the zipped source code from https://github.com/xfeep/nginx-clojure/releases

  3. If you want to use Http SSL module, you should install openssl and openssl dev first.

  4. 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"
  5. 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
  6. Create the jar file about Nginx-Clojure

    Please check the lein version lein version, it should be at least 2.0.0.

    $ cd nginx-clojure
    $ lein javac
    $ lein jar

    Then you'll find nginx-clojure-${version}.jar (eg. nginx-clojure-0.1.0.jar) in the target folder.

  7. Configurations =================

2.1 JVM Path , Class Path & Other JVM Options

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.

2.2 Threads Number for Request Handler Thread Pool on JVM

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 can't resolve your performance problems by increasing worker_processes or reducing single request-response time, you can try this way. If your tasks are often blocked by slow I/O operations, the thread pool method can make the nginx worker not blocked until all threads are exhuasted.

eg.

jvm_workers 40;

Now Nginx-Clojure will create a thread pool with fixed 40 threads per JVM instance/Nginx worker to handle requests. If you get more memory, you can set a bigger number.

2.3 Ring Handler for Location

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) .

  1. Useful Links =================
  1. License ================= Copyright © 2013-2014 Zhang, Yuexiang (xfeep) and released under the BSD 3-Clause license.

This program uses:

  • Re-rooted ASM bytecode engineering library which is distributed under the BSD 3-Clause license
  • Modified Continuations Library Written by Matthias Mann is distributed under the BSD 3-Clause license

About

Nginx module for embedding Clojure or Java programs, typically those Ring based handlers.

Resources

License

Stars

Watchers

Forks

Packages

No packages published