-
Notifications
You must be signed in to change notification settings - Fork 348
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Lua and JVM and Python decorators and and and...
- Loading branch information
Showing
8 changed files
with
693 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
JVM in the uWSGI server | ||
======================= | ||
|
||
.. toctree:: | ||
|
||
JWSGI | ||
|
||
.. note:: This documentation may be out of date. | ||
|
||
Starting from 0.9.7-dev version, a plugin that embeds a Java Virtual Machine in uWSGI is available. | ||
|
||
Its main purpose is to allow other plugins (languages) to communicate with Java classes. The first plugin to get JVM support will be Python. | ||
|
||
This is the current list of functions that will be exposed: | ||
|
||
* uwsgi.jvm.call_static_method("class","method", args, ...) | ||
* uwsgi.jvm.call_method(object,"method", args, ...) | ||
* uwsgi.jvm.string("string") | ||
* uwsgi.jvm.integer(N) | ||
* uwsgi.jvm.array(object, ...) | ||
|
||
The ``pyjvm`` plugin is still at early stage of development. The JVM plugin will allow to map string, integers and array to other languages object (in a similar way to the Erlang one). | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
The JWSGI interface | ||
=================== | ||
|
||
.. note:: JWSGI is not a standard. Yet. If you like JWSGI, why not send an RFC to the uWSGI mailing list. We have no interest in a standard, but who knows... | ||
|
||
JWSGI is a port of the WSGI/PSGI/Rack way of thinking for Java. | ||
|
||
If, for some obscure reason, you'd feel like developing apps with JVM languages and you don't feel like deploying a huge servlet stack, JWSGI should be up your alley. | ||
|
||
It is a very simple (and admittedly raw) protocol where you call a public method that takes a ``Hashtable`` as its sole argument. | ||
This Hashtable contains CGI style variables and ``jwsgi.input`` containing a Java FileDescriptor that you can use with ``java.io``. | ||
|
||
Example | ||
------- | ||
|
||
A simple JWSGI app looks like this: | ||
|
||
.. code-block:: java | ||
import java.util.Hashtable; | ||
import java.util.ArrayList; | ||
public class utest { | ||
public static Object[] jwsgi(Hashtable env) { | ||
String status = "200 Ok"; | ||
ArrayList<Object> headers = new ArrayList<Object>(); | ||
String[] header = {"Content-type", "text/html"}; | ||
headers.add(header); | ||
String[] header2 = {"Server", "uWSGI"}; | ||
headers.add(header2); | ||
String body = "<h1>Hello World</h1>" + env.get("REQUEST_URI"); | ||
Object[] response = {status, headers, body}; | ||
return response; | ||
} | ||
} | ||
And to consume HTTP body content, | ||
|
||
.. code-block:: java | ||
public static Object[] jwsgi(Hashtable env) throws java.io.IOException { | ||
if (env.containsKey("CONTENT_LENGTH")) { | ||
String s = (String) env.get("CONTENT_LENGTH"); | ||
if (s.length() > 0) { | ||
Integer cl = Integer.parseInt( s ); | ||
FileInputStream f = new FileInputStream( (FileDescriptor) env.get("jwsgi.input") ); | ||
byte[] b = new byte[cl]; | ||
if (f.read(b) > 0) { | ||
String postdata = new String(b); | ||
System.out.println( postdata ); | ||
} | ||
} | ||
} | ||
String status = "200 Ok"; | ||
ArrayList<Object> headers = new ArrayList<Object>(); | ||
String[] header = { "Content-type", "text/html" } ; | ||
headers.add(header); | ||
String[] header2 = { "Server", "uWSGI" } ; | ||
headers.add(header2); | ||
String body = "<form method=\"POST\"><input type=\"text\" name=\"nome\"/><input type=\"submit\" value=\"send\" /></form>" + env.get("REQUEST_URI"); | ||
Object[] response = { status, headers, body }; | ||
return response; | ||
} | ||
How to use it? | ||
-------------- | ||
|
||
The procedure to run JWSGI is still sort of messy. You have to build both the JVM and the JWSGI plugins. Modifier 8 has been assigned to the JWSGI interface, so remember to edit your webserver | ||
configuration accordingly. | ||
|
||
1. Edit ``plugins/jvm/uwsgiplugin.py`` to set ``JVM_INCPATH`` and ``JVM_LIBPATH`` to their right values. What the right values are is system dependent. Search for ``jni.h`` and ``libjvm.so``. | ||
Do the same for ``plugins/jwsgi/uwsgiplugin.py``. | ||
|
||
2. Build! | ||
|
||
.. code-block:: sh | ||
python uwsgiconfig.py --build core | ||
python uwsgiconfig.py --plugin plugins/jvm core | ||
python uwsgiconfig.py --plugin plugins/jwsgi core | ||
3. Compile your class with ``javac``. | ||
|
||
.. code-block:: sh | ||
javac utest.java | ||
4. Run uWSGI and load the utest class. | ||
|
||
.. code-block:: sh | ||
./uwsgi -s :3031 --plugins jvm,jwsgi --jvm-main-class utest -M -p 4 -m | ||
Important Notes | ||
--------------- | ||
|
||
* The jwsgi method must be called ``jwsgi``. This will be fixed soon. | ||
* The jwsgi plugin leaks memory at every request. We are still evaluating if memory management must be managed in the jvm plugin, or in the jwsgi one. | ||
* Threading will be a core component of the JVM plugin in the future. Expect an update soon. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
Using Lua/WSAPI with uWSGI | ||
========================== | ||
|
||
Compilation notes | ||
----------------- | ||
|
||
Before compiling the plugin take a look at the :file:`plugins/lua/uwsgiplugin.py` configuration file. If you have installed Lua in some exotic directory you may need to adjust the ``CFLAGS`` and ``LIBS`` values. | ||
|
||
For example, on a Debian/Ubuntu system you should use something like this: | ||
|
||
.. code-block:: python | ||
import os, sys | ||
NAME='lua' | ||
CFLAGS = ['-I/usr/include/lua5.1/'] | ||
LDFLAGS = [] | ||
GCC_LIST = ['lua_plugin'] | ||
LIBS = ['-llua5.1'] | ||
The ``lua.ini`` buildconf will build uWSGI with embedded Lua support. The ``luap.ini`` buildconf will build Lua support as a plugin. | ||
|
||
.. code-block:: sh | ||
python uwsgiconfig.py --build lua # embedded | ||
python uwsgiconfig.py --build luap # plugin | ||
# if you have already build the uWSGI core with the default config file... | ||
python uwsgiconfig.py --plugin plugins/lua | ||
# or if you have used another config file (for example core.ini) | ||
python uwsgiconfig.py --plugin plugins/lua core | ||
Your first WSAPI application | ||
---------------------------- | ||
|
||
We will use the official WSAPI example, let's call it :file:`pippo.lua`: | ||
|
||
.. code-block:: lua | ||
function hello(wsapi_env) | ||
local headers = { ["Content-type"] = "text/html" } | ||
local function hello_text() | ||
coroutine.yield("<html><body>") | ||
coroutine.yield("<p>Hello Wsapi!</p>") | ||
coroutine.yield("<p>PATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>") | ||
coroutine.yield("<p>SCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>") | ||
coroutine.yield("</body></html>") | ||
end | ||
return 200, headers, coroutine.wrap(hello_text) | ||
end | ||
return hello | ||
Now run uWSGI with the ``lua`` option (remember to add ``--plugins lua`` as the first command line option if you are using it as a plugin) | ||
|
||
.. code-block:: sh | ||
./uwsgi -s :3031 -M -p 4 --lua pippo.lua -m | ||
The Lua plugin's official uwsgi protocol modifier number is ``6``, so remember to set it in your web server configuration with the ``uWSGIModifier1``/``uwsgi_modifier1`` directive. | ||
|
||
Abusing coroutines | ||
------------------ | ||
|
||
One of the most exciting feature of Lua is coroutine (cooperative multithreading) support. uWSGI can benefit from this using its async core. | ||
|
||
The Lua plugin will initialize a ``lua_State`` for every async core. | ||
|
||
We will use a CPU-bound version of our pippo.lua to test it: | ||
|
||
.. code-block:: lua | ||
function hello(wsapi_env) | ||
local headers = { ["Content-type"] = "text/html" } | ||
local function hello_text() | ||
coroutine.yield("<html><body>") | ||
coroutine.yield("<p>Hello Wsapi!</p>") | ||
coroutine.yield("<p>PATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>") | ||
coroutine.yield("<p>SCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>") | ||
for i=0, 10000, 1 do | ||
coroutine.yield(i .. "<br/>") | ||
end | ||
coroutine.yield("</body></html>") | ||
end | ||
return 200, headers, coroutine.wrap(hello_text) | ||
end | ||
return hello | ||
and run uWSGI with 8 async cores... | ||
|
||
.. code-block:: sh | ||
./uwsgi -s :3031 -M -p 4 --lua pippo.lua -m --async 8 | ||
And just like that, you can manage 8 concurrent requests within a single worker! | ||
|
||
Threading | ||
--------- | ||
|
||
The Lua plugin is "thread-safe" as uWSGI maps a lua_State to each internal pthread. | ||
|
||
For example you can run the Sputnik_ wiki engine very easily. | ||
|
||
Use LuaRocks_ to install Sputnik and ``versium-sqlite3``. A database-backed storage is required as the default filesystem storage does not support being accessed by multiple interpreters concurrently. | ||
|
||
Create a wsapi compliant file: | ||
|
||
.. code-block:: lua | ||
require('sputnik') | ||
return sputnik.wsapi_app.new{ | ||
VERSIUM_STORAGE_MODULE = "versium.sqlite3", | ||
VERSIUM_PARAMS = {'/tmp/sputnik.db'}, | ||
SHOW_STACK_TRACE = true, | ||
TOKEN_SALT = 'xxx', | ||
BASE_URL = '/', | ||
} | ||
And run your threaded uWSGI server | ||
|
||
..code-block:: sh | ||
|
||
./uwsgi --plugins lua --lua sputnik.ws --threads 20 -s :3031 | ||
|
||
.. _Sputnik: http://sputnik.freewisdom.org/ | ||
.. _LuaRocks: http://www.luarocks.org/ | ||
|
||
A note on memory | ||
---------------- | ||
|
||
As we all know, uWSGI is... fascist about memory. Memory is a precious resource. Do not trust software that does not care for your memory! | ||
The Lua garbage collector is automatically called after each request. An option to set the frequency at which the GC runs will be available soon. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
Monitoring uWSGI with Nagios | ||
============================ | ||
|
||
The official uWSGI distribution includes a plugin adding Nagios_ friendly output. | ||
|
||
To monitor, and eventually get warning messages, via Nagios, launch the following command, Where ``node`` is the socket (UNIX or TCP) to monitor. | ||
|
||
.. code-block:: sh | ||
uwsgi --socket <node> --nagios | ||
Setting warning messages | ||
------------------------ | ||
|
||
You can set a warning message directly from your app with the :func:`uwsgi.set_warning_message` function. All the ping responses (used by Nagios too) will report this message. | ||
|
||
.. _Nagios: http://www.nagios.com/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.