This week, I managed to figure out what was causing the issue with my previous version of the plugin. As I discussed in my previous blog post, I changed the code execution model for the plugin. Now the code for the script is loaded as a lua co-routine and executed. Currently the plugin will block the thread if you make a blocking call from lua. This can be fixed by yielding to the event loop.

Two approaches are possible to make the plugin 100% non blocking. One is to write custom lua modules for making network calls that will integrate with the plugins event loop. Another possible approach as I discussed earlier was to wrap the sockets api. Currently, the plugin is functional although I have to check for memory leaks and other issues.

I started out the project planning to accomplish a lot more, however I had a few roadblocks that really slowed down the progress. I had struggled a lot but I have learned a lot about things like event loops, networking, the HTTP specification, lua, coroutines, and a bunch of other interesting stuff. I want to that Eduardo and Jorge for all the guidance they have given throughout the program. The plugin can be improved in a lot of ways and I plan to work on it after the GSoC, the socket library wrapper is on my list first. This will allow porting openresty libraries to monkey thus providing an alternative to duda for writing web applications with minimum hassle with lua.

In order to implement a nonblocking way to excecute the lua code for the plugin I have been reading ngnix’s http://wiki.nginx.org/HttpLuaModule. The module is implemented with one LUA VM per worker and each lua call/request is run with it’s own coroutine. This seems to be a better approach than the one I am currently using as this removes the latency involved in creating a Lua state per request as coroutines are much more lightweight compared to lua_state, I am currently rewriting some of the code to work in this way as it might offer much more flexibility and performance.

from the https://github.com/openresty/lua-nginx-module/wiki/Introduction

Lua-nginx-module integrated Lua into NginX, and providing high-concurrent & non-blocking request processing ability without forcing developers explicitly dividing business logics into state machine. Developers can write their programs in plain-old sequential ways, and lua-nginx-module will automatically interrupt the program logic at blockable I/O operations, save the context and delegate these I/O ops to NginX’s event mechanism. When I/O ops are done, lua-nginx-module will restore the context and restore the normal running of the program logic. User program itself will feel everything as usual as never being interrupted.

Lua-nginx-module uses one-coroutine-per-request request handling model, i.e. for each incoming request, lua-nginx-module creates a coroutine to run user code to process the request, and the coroutine will be destroyed when the request handling process is done. Every coroutine has its own independent global environment, which inherits shared read-only common data. So any global values injected by the user code won’t affect other request’s processing, and will be freed when request handling is done. You can imagine that user code is running in a ‘sandbox’, which shares the same lifecycle with the request itself. By this way, lua-nginx-module can prevent memory-leak caused by abusing uses of global values in user code, hence improve robustness.

The non blocking behaviour of the module is achieved by using coroutines with blocking calls that yields to the event loop. This is done using something called cosockets which makes writing sequential code that works in non blocking way. In order to implement similar functionality in monkey, this co sockets api has to rewritten to integrate with monkeys event loop. Although this would require in effect writing a socket library for lua that specifically works with monkey, this will make adding more libraries easier in the future as well as make it possible to use many of the existing libraries for openresty to monkey lua without much effort other than that required for dealing with lua 5.1 vs lua 5.2 issues.

This week I completed a for the api documentation. I have a version of the plugin that is functional in the testing branch of the repo. Making the plugin non blocking by using co sockets requires some effort and I have started writing code for this. I will try to finish this before the pencils down date.

I haven’t been able to figure out what is causing the looping issue that had been troubling me from last week. I have created a branch with the old version of plugin working in blocking mode. The plugin’s current execution model is not efficient as it might block the server thread and a thread based model is also scalable. Also I am creating a new lua_state instance per request which could be avoided.

I have identified similar areas for performance improvement and most important of all will be to use a coroutine based approach for executing the lua code similar to nginx’s lua module.I have started documenting everything that are working right now.In the coming weeks, I will complete the documentation and move on to fixing issues that I have identified.

code: github

I seem to have hit a roadblock as I am facing some issues with integrating the plugin with monkey. Last week I had a working implementation for the plugin, however on further testing, I noticed that the plugin will fail while using some features which make use of the monkey api as the lua execution happens in a new thread. I have been trying to figure out ways to circumvent the issues without any luck as I had limited time due to school work.

A temporary solution was to execute the lua code in the plugin context itself, blocking the thread. I also found a few more issues with the current implementation which I am having a little trouble in fixing.

My project is lagging behind the initial plan I had in mind, I will try my level best from now on to make up for the lost time and complete the project in time.

I have completed a bare version of the plugin and started working on code for monitoring lua’s resource usage. Last week was mostly spend on wiring everything together from last weeks work. I have also started reading code for integrating the plugin with duda. I haven’t figured out how to proceed on it and haven’t been able to get in touch with Jorge this week. I will discuss with him on how to proceed next week.

Most of the work this week was mostly re-factoring my old code to fit in with the the plugin system and reading

code: https://github.com/diadara/monkey_lua

As mentioned in the last post, the week before the last one I was trying to understand event driven programming and monkeys use of epoll to serve large number of connections and had started writing the response part of the plugin and struggled to complete it.This week was also spent on the same task except that I think I have a hold of what am I doing. I have been studying the fast cgi and cgi plugins for figuring out how to deal with writing response back to the client.

The CGI plugin maintains a list of connections and forks to execute the script with a execv and uses two pipes to communicate with the parent and uses epoll for getting notification when it has something to read from the pipe and write back to the client. Similarly fast cgi has it’s own socket for communicating with monkey and uses epoll for notification. In case of the lua plugin, I had a few options to implement it. Till now, I have been executing lua code from the monkeys thread which obviously will prevent the thread from doing anything else. So the solution is to either fork and execute or spawn a new thread.

Currently, there is no particular advantage of using epoll to get notification from the lua thread as I can only start writing to the client socket once the entire lua script finish executing.I am stuck on putting together this small detail and the plugin should be ready in a bare metal state.

Next Week, I will sort out the remaining details for IO also taking into acount chunked encoding and figure out a way to collect some metrics on the execution.

github

This week, I was trying to get a better Idea about event driven programming especially using epoll in specific so that I can integrate the plugin with monkey. I found a bunch of great resources for understanding epoll as well as other strategies and system calls available in various operating systems to achieve concurrency.

http://kovyrin.net/2006/04/13/epoll-asynchronous-network-programming/

http://www.wangafu.net/~nickm/libevent-book/01_intro.html

I started working on sending the response back to the client by hooking to the epoll callbacks instead of the blocking way I was using till now to get things done till now.

Also, I was looking at a way to execute the lua code in a non blocking way. The popular approach is to use a watchdog timer or something along the lines mentioned in this thread

http://lua-users.org/wiki/NonBlockingLuaExecution

http://lua.2524044.n2.nabble.com/Nonblocking-script-execution-td7641186.html

I still haven’t figured out a working way to make everything work together and so haven’t pushed in my changes as I am running into some errors.

I had to move to a new apartment this week and was under some time constraints and this weeks work required a lot more reading before I started coding so, that leaves me with no working code till now, I will try to fix up my code and push it by tonight.

Last week, I started to re-factor the code I had already written for the plugin. During the course of the project, I have been reading source code from ngnix and apache respective lua modules to understand good coding patterns for lua and to understand good ways for getting things done. I am using LUA’s lightuserdata that allows to access C datastructures from LUA code and also wrote a bunch of functions to help building on top of it easier. Also I have tried to make the code more modular.

I was also working on adding cookie support to the lua environment, which took more time than I had expected. You can get a table of all the set cookies from mk.cookies.get_cookies() function call and set a cookie by this syntax mk.cookie.set_cookie{name=[name], value=[value], secure=true, expires= os.time()+ 60*60*12}

Next Week:

  • Make the response in a non blocking way
  • Start work on the duda plugin

code:

github

This week I have been working on finishing up the request parsing functionality for the plugin. The plugin can now handle application/x-www-form-urlencoded as well as multipart/form-data encoded form data and thus should be able to handle file uploads as well although I haven’t wired up the file-uploading part of the api yet.

I also implemented a configuration option for turning debugging on or off which will decide whether a trace back of error will be send back as response. To easily test all these, I went ahead and made a blocking version for sending back the response. Everything seems to be working fine.

Next:

  • There is no cookie handling in the api yet although headers are accessible, this has to be implemented.
  • re-factor the code and remove errors that may have been introduced
  • make the plugin work in a non-blocking way.
  • decide upon how the duda package for the plugin should function

code:

github

This week I had been working on the completing the environment preparation for lua script execution. All basic tables request, response and config have been implemented as of now. I had been working on implementing some features that would make using the lua scripting support easier like better query string and post data parsing and also to provide a stack trace for easier error detection.I have updated the example script from last time to show, how the new features work.

A few things tripped me up like monkeys lack of query string parsing and the fact that the query strings were not escaped caused some problems which have been taken care of.

Next thing on my list is to write back the actual response from the plugin and before that I have to check the code with valgrind.

code: github