# Nginx, echo module & lua

**URL:** <https://www.ruby-forum.com/t/nginx-echo-module-lua/219415>\
**Category:** NGINX\
**Created:** [May 2, 2012, 10:12am UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415 "2012-05-02T10:12:22Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [May 2, 2012, 10:12am UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/1 "2012-05-02T10:12:22Z")

</div>

Hi all,

I’m trying to use both echo module & lua, but I’m having some issues:

1. I reach quickly “subrequests cycle”. Looking @ the code, subrequests  
is unsigned:8,  
but I would need thousands of subrequests sometimes. putting  
subrequests to unsigned just  
results to crashes.

2. when in config: set\_by\_lua\_file $varname luafile.lua , and  
luafile.lua references to ngx.ctx,  
I get the following error:  
(lua-error)…no request ctx found  
according to the doc, ngx.ctx is available in set\_lua\*, but does not  
work. Would anybody suggest  
me a workaround ?

I’m using luajit, openresty last version.

Thanks a lot in advance,  
Pierre

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 2, 2012, 1:47pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/2 "2012-05-02T13:47:04Z")

</div>

Hello!

On Wed, May 2, 2012 at 4:11 PM, Pierre [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I’m trying to use both echo module & lua, but I’m having some issues:
> 
> 1. I reach quickly “subrequests cycle”. Looking @ the code, subrequests is  
> unsigned:8,  
> but I would need thousands of subrequests sometimes. putting subrequests to  
> unsigned just  
> results to crashes.

There’s no way to support thousands of subrequests in a single main  
request without patching the nginx core.

But you’re encouraged to try out ngx\_lua’s cosocket API to avoid  
subrequests altogether. And the cosocket stuff does not have such  
limitations.

There’s already several Lua drivers based on that, including  
memcached, redis, mysql, http, and mongodb. For instance, the  
lua-resty-redis library:

> **[GitHub - openresty/lua-resty-redis: Lua redis client driver for the ngx\_lua based on...](https://github.com/openresty/lua-resty-redis)**
>
> Lua redis client driver for the ngx\_lua based on the cosocket API

> 1. when in config: set\_by\_lua\_file $varname luafile.lua , and luafile.lua  
> references to ngx.ctx,  
> I get the following error:  
> (lua-error)…no request ctx found  
> according to the doc, ngx.ctx is available in set\_lua\*, but does not work.  
> Would anybody suggest  
> me a workaround ?

This is indeed a bug. Thanks for reporting this!

I’ve just committed a patch for it:

> **[bugfix: ngx.ctx was not accessible at all in set\_by\_lua\*. thanks Pierre. ·...](https://github.com/openresty/lua-nginx-module/commit/bee1cab)**
>
> Embed the Power of Lua into NGINX HTTP servers. Contribute to openresty/lua-nginx-module development by creating an account on GitHub.

Could you try out the git master HEAD on your side?

Thanks!  
-agentzh

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 2, 2012, 3:40pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/3 "2012-05-02T15:40:12Z")

</div>

On 02/mai - 19:46, agentzh wrote:

> > 
> 
> There’s no way to support thousands of subrequests in a single main  
> request without patching the nginx core.  
> ok
> 
> But you’re encouraged to try out ngx\_lua’s cosocket API to avoid  
> subrequests altogether. And the cosocket stuff does not have such  
> limitations.  
> hmm, any more documentation about that ?  
> More about: how to implement it in my lua scripts ?

is that it ? :

local tcp = ngx.socket.tcp

function new(self)  
return setmetatable({ sock = tcp() }, mt)  
end

?

> There’s already several Lua drivers based on that, including  
> memcached, redis, mysql, http, and mongodb. For instance, the  
> lua-resty-redis library:  
> mongodb: you mean mongofs or mongodb ?
> 
> > 
> 
> This is indeed a bug. Thanks for reporting this!
> 
> I’ve just committed a patch for it:
> 
> [bugfix: ngx.ctx was not accessible at all in set\_by\_lua\*. thanks Pierre. · openresty/lua-nginx-module@bee1cab · GitHub](https://github.com/chaoslawful/lua-nginx-module/commit/bee1cab)  
> woh, thx !
> 
> Could you try out the git master HEAD on your side?  
> I will

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 2, 2012, 5:11pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/4 "2012-05-02T17:11:10Z")

</div>

On Wed, May 2, 2012 at 9:39 PM, Pierre [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > But you’re encouraged to try out ngx\_lua’s cosocket API to avoid  
> > subrequests altogether. And the cosocket stuff does not have such  
> > limitations.  
> > hmm, any more documentation about that ?

See the official documentation for ngx\_lua cosocket:

```
http://wiki.nginx.org/HttpLuaModule#ngx.socket.tcp

```

> More about: how to implement it in my lua scripts ?
> 
> is that it ? :
> 
> local tcp = ngx.socket.tcp
> 
> function new(self)  
> return setmetatable({ sock = tcp() }, mt)  
> end  
> ?

See the lua-resty-redis, lua-resty-memcached, and lua-resty-mysql  
libraries as examples:

```
https://github.com/agentzh/lua-resty-redis
https://github.com/agentzh/lua-resty-memcached
https://github.com/agentzh/lua-resty-mysql

```

bigplum has been working on lua-resty-mongol:

```
https://github.com/bigplum/lua-resty-mongol

```

I’m not sure about its state, but you can read the document or contact  
the author directly.

Best regards,  
-agentzh

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 3, 2012, 9:54am UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/5 "2012-05-03T09:54:03Z")

</div>

A little thread hijacking. Are there plans to provide an HTTP response  
parser? I suppose that for performance reasons that would have to  
be in C along the lines of the Redis parser.

> **[GitHub - openresty/lua-redis-parser: Lua module for parsing raw redis responses](https://github.com/openresty/lua-redis-parser)**
>
> Lua module for parsing raw redis responses. Contribute to openresty/lua-redis-parser development by creating an account on GitHub.

That’s what’s missing, IMHO, in order to completely replace  
luasocket.

Great work as usual.

–appa

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 3, 2012, 12:43pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/6 "2012-05-03T12:43:32Z")

</div>

Investigating a bit more, here is the conclusion:

location = /store {  
internal;  
#test 1  
#echo\_subrequest\_async PUT /trucalacon -q ‘filename=$arg\_filename’  
-b $echo\_request\_body;  
#test 2  
#content\_by\_lua ’

# local filename = ngx.req.get\_uri\_args()[“md5”]

# local res = ngx.location.capture(“/trucalacon”,

# { args = {filename = filename } ,

# ctx = ngx.ctx })

#';  
}  
location = /trucalacon {  
proxy\_set\_header X-Real-IP $remote\_addr;  
proxy\_pass [http://otherserver](http://otherserver);  
}

using echo\_subrequest\_async, I directly reach :  
2012/05/03 12:08:25 [error] 13204#0: \*1 subrequests cycle while  
processing “/trucalacon”,

using echo\_subrequest, I get the same behaviour as ngx.location.capture

using content\_by\_lua + location.capture, everything is smooth.

/store is called by another lua script, which does  
location.capture.multi(‘/store’), 20 by 20

Last interrogation:  
What is the best way to discard body (I mean free the memory by body  
passed to subrequests ) ?

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 3, 2012, 1:35am UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/7 "2012-05-03T01:35:31Z")

</div>

On 02/mai - 19:46, agentzh wrote:

> > 
> 
> lua-resty-redis library:
> 
> [GitHub - openresty/lua-resty-redis: Lua redis client driver for the ngx\_lua based on the cosocket API · GitHub](https://github.com/agentzh/lua-resty-redis)

how can I combine cosocket & foreign upstream ?  
also, I didn’t find any example involving cosocket between locations, or  
maybe  
I’m getting it wrong.

> I’ve just committed a patch for it:
> 
> [bugfix: ngx.ctx was not accessible at all in set\_by\_lua\*. thanks Pierre. · openresty/lua-nginx-module@bee1cab · GitHub](https://github.com/chaoslawful/lua-nginx-module/commit/bee1cab)

works like a charm, thanks !

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 3, 2012, 2:53pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/8 "2012-05-03T14:53:24Z")

</div>

On Thu, May 3, 2012 at 3:53 PM, Antonio P.P. Almeida [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> A little thread hijacking. Are there plans to provide an HTTP response  
> parser? I suppose that for performance reasons that would have to  
> be in C along the lines of the Redis parser.
> 
> [GitHub - openresty/lua-redis-parser: Lua module for parsing raw redis responses · GitHub](https://github.com/agentzh/lua-redis-parser)
> 
> That’s what’s missing, IMHO, in order to completely replace  
> luasocket.

Liseen Wan has been working on the lua-resty-http library:

```
https://github.com/liseen/lua-resty-http

```

We’ll extend that to support more and more HTTP features in the near  
future.

But I think it will remain pure Lua because introducing C may not  
really help here given the performance of LuaJIT 2.0 (and it has  
already been proven in lua-resty-mysql where rewriting the MySQL  
packet parser in C actually slowed things down because going across  
language boundary is more expensive).

But anyway we can provide pure C API for ngx\_lua cosocket, just like  
ngx\_http\_upstream, so a pure C implementation for those lua-resty-\*  
library will have a chance to achieve better performance than the pure  
Lua implementations, but I’m not 100% sure 😉

Regards,  
-agentzh

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 3, 2012, 2:34pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/9 "2012-05-03T14:34:44Z")

</div>

On Thu, May 3, 2012 at 7:34 AM, Pierre [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> 

The cosocket API is used to talk to remote servers in TCP or unix  
domain sockets directly. It does not support the subrequest model at  
all so it is not used for reusing existing upstream modules.

The “cosocket” term is short for “coroutine-based socket”, it is a  
parallel implementation as ngx\_http\_usptream, see the following graph:

```
http://agentzh.org/misc/slides/libdrizzle-lua-nginx/#57

```

> > I’ve just committed a patch for it:
> > 
> > [bugfix: ngx.ctx was not accessible at all in set\_by\_lua\*. thanks Pierre. · openresty/lua-nginx-module@bee1cab · GitHub](https://github.com/chaoslawful/lua-nginx-module/commit/bee1cab)
> 
> works like a charm, thanks !

Sorry, my previous patch introduced a bad memory leak and I’ve just  
committed the following patch to fix this:

```
https://github.com/chaoslawful/lua-nginx-module/commit/8d2878

```

Best regards,  
-agentzh

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 3, 2012, 5:39pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/10 "2012-05-03T17:39:17Z")

</div>

On 03/mai - 21:03, agentzh wrote:

> On Thu, May 3, 2012 at 6:43 PM, Pierre [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > using echo\_subrequest\_async, I directly reach :  
> > 2012/05/03 12:08:25 [error] 13204#0: \*1 subrequests cycle while processing  
> > “/trucalacon”,
> 
> Which version of nginx are you using?  
> tested on openresty 10.0.10 abd 1.0.11  
> the lifetime of the main request.  
> ok, thx
> 
> It’s worth mentioning that the ngx\_lua cosocket API does not suffer  
> from this issue because Lua GC handles the resource lifetime there.  
> 🙂

---

<div class="post-metadata">

**Author:** ![pierre](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/p/d07c76/32.png) [@pierre](https://www.ruby-forum.com/u/pierre)\
**Post date:** [May 3, 2012, 3:04pm UTC](https://www.ruby-forum.com/t/nginx-echo-module-lua/219415/11 "2012-05-03T15:04:35Z")

</div>

On Thu, May 3, 2012 at 6:43 PM, Pierre [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> using echo\_subrequest\_async, I directly reach :  
> 2012/05/03 12:08:25 [error] 13204#0: \*1 subrequests cycle while processing  
> “/trucalacon”,

Which version of nginx are you using?

> Last interrogation:  
> What is the best way to discard body (I mean free the memory by body passed to  
> subrequests ) ?

There’s no way to release all the memory of a subrequest instantly  
because nginx subrequests share the same memory pool as their parent  
request. So for long-running requests that issue a lot of serial  
subrequests, there will be a good chance of temporary memory leaks in  
the lifetime of the main request.

It’s worth mentioning that the ngx\_lua cosocket API does not suffer  
from this issue because Lua GC handles the resource lifetime there.

Best regards,  
-agentzh
