Skip to content

Commit 8c53a0d

Browse files
committed
feature: implemented the balancer_by_lua_block and balancer_by_lua_file directives to allow NGINX load balancers written in Lua.
Also added pure C API to support the ngx.balancer Lua API implemented in the lua-resty-core library. Thanks Shuxin Yang, Dejiang Zhu, Brandon Beveridge, and others for the help.
1 parent e5bf7d6 commit 8c53a0d

13 files changed

+1191
-21
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ src/timer.[ch]
154154
src/config.[ch]
155155
src/worker.[ch]
156156
src/lex.[ch]
157+
src/balancer.[ch]
157158
*.plist
158159
lua
159160
ttimer

README.markdown

Lines changed: 106 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,6 +1028,8 @@ Directives
10281028
* [log_by_lua](#log_by_lua)
10291029
* [log_by_lua_block](#log_by_lua_block)
10301030
* [log_by_lua_file](#log_by_lua_file)
1031+
* [balancer_by_lua_block](#balancer_by_lua_block)
1032+
* [balancer_by_lua_file](#balancer_by_lua_file)
10311033
* [lua_need_request_body](#lua_need_request_body)
10321034
* [lua_shared_dict](#lua_shared_dict)
10331035
* [lua_socket_connect_timeout](#lua_socket_connect_timeout)
@@ -2217,6 +2219,83 @@ This directive was first introduced in the `v0.5.0rc31` release.
22172219

22182220
[Back to TOC](#directives)
22192221

2222+
balancer_by_lua_block
2223+
---------------------
2224+
2225+
**syntax:** *balancer_by_lua_block { lua-script }*
2226+
2227+
**context:** *upstream*
2228+
2229+
**phase:** *content*
2230+
2231+
This directive runs Lua code as an upstream balancer for any upstream entities defined
2232+
by the `upstream {}` configuration block.
2233+
2234+
For instance,
2235+
2236+
```nginx
2237+
2238+
upstream foo {
2239+
server 127.0.0.1;
2240+
balancer_by_lua_block {
2241+
-- use Lua to do something interesting here
2242+
-- as a dynamic balancer
2243+
}
2244+
}
2245+
2246+
server {
2247+
location / {
2248+
proxy_pass http://foo;
2249+
}
2250+
}
2251+
```
2252+
2253+
The resulting Lua load balancer can work with any existing nginx upstream modules
2254+
like [ngx_proxy](http://nginx.org/en/docs/http/ngx_http_proxy_module.html) and
2255+
[ngx_fastcgi](http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html).
2256+
2257+
Also, the Lua load balancer can work with the standard upstream connection pool mechanism,
2258+
i.e., the standard [keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive.
2259+
Just ensure that the [keepalive](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) directive
2260+
is used *after* this `balancer_by_lua_block` directive in a single `upstream {}` configuration block.
2261+
2262+
The Lua load balancer can totally ignore the list of servers defined in the `upstream {}` block
2263+
and select peer from a completely dynamic server list (even changing per request) via the
2264+
[ngx.balancer](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md) module
2265+
from the [lua-resty-core](https://github.com/openresty/lua-resty-core) library.
2266+
2267+
The Lua code handler registered by this directive might get called more than once in a single
2268+
downstream request when the nginx upstream mechanism retries the request on conditions
2269+
specified by directives like the [proxy_next_upstream](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream)
2270+
directive.
2271+
2272+
This Lua code execution context does not support yielding, so Lua APIs that may yield
2273+
(like cosockets and "light threads") are disabled in this context. One can usually work
2274+
around this limitation by doing such operations in an earlier phase handler (like
2275+
[access_by_lua*](#access_by_lua)) and passing along the result into this context
2276+
via the [ngx.ctx](#ngxctx) table.
2277+
2278+
This directive was first introduced in the `v0.10.0` release.
2279+
2280+
[Back to TOC](#directives)
2281+
2282+
balancer_by_lua_file
2283+
--------------------
2284+
2285+
**syntax:** *balancer_by_lua_file <path-to-lua-script-file>*
2286+
2287+
**context:** *upstream*
2288+
2289+
**phase:** *content*
2290+
2291+
Equivalent to [balancer_by_lua_block](#balancer_by_lua_block), except that the file specified by `<path-to-lua-script-file>` contains the Lua code, or, as from the `v0.5.0rc32` release, the [Lua/LuaJIT bytecode](#lualuajit-bytecode-support) to be executed.
2292+
2293+
When a relative path like `foo/bar.lua` is given, they will be turned into the absolute path relative to the `server prefix` path determined by the `-p PATH` command-line option while starting the Nginx server.
2294+
2295+
This directive was first introduced in the `v0.10.0` release.
2296+
2297+
[Back to TOC](#directives)
2298+
22202299
lua_need_request_body
22212300
---------------------
22222301

@@ -2763,6 +2842,7 @@ Nginx API for Lua
27632842
* [ngx.worker.count](#ngxworkercount)
27642843
* [ngx.worker.id](#ngxworkerid)
27652844
* [ngx.semaphore](#ngxsemaphore)
2845+
* [ngx.balancer](#ngxbalancer)
27662846
* [ndk.set_var.DIRECTIVE](#ndkset_vardirective)
27672847
* [coroutine.create](#coroutinecreate)
27682848
* [coroutine.resume](#coroutineresume)
@@ -3028,7 +3108,7 @@ print
30283108
-----
30293109
**syntax:** *print(...)*
30303110

3031-
**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.**
3111+
**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, ngx.balancer_by_lua**
30323112

30333113
Writes argument values into the nginx `error.log` file with the `ngx.NOTICE` log level.
30343114

@@ -3047,7 +3127,7 @@ There is a hard coded `2048` byte limitation on error message lengths in the Ngi
30473127

30483128
ngx.ctx
30493129
-------
3050-
**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.**
3130+
**context:** *init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua**
30513131

30523132
This table can be used to store per-request Lua context data and has a life time identical to the current request (as with the Nginx variables).
30533133

@@ -3650,7 +3730,7 @@ ngx.resp.get_headers
36503730
--------------------
36513731
**syntax:** *headers = ngx.resp.get_headers(max_headers?, raw?)*
36523732

3653-
**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua**
3733+
**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua**
36543734

36553735
Returns a Lua table holding all the current response headers for the current request.
36563736

@@ -3768,7 +3848,7 @@ ngx.req.get_method
37683848
------------------
37693849
**syntax:** *method_name = ngx.req.get_method()*
37703850

3771-
**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua**
3851+
**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, balancer_by_lua**
37723852

37733853
Retrieves the current request's request method name. Strings like `"GET"` and `"POST"` are returned instead of numerical [method constants](#http-method-constants).
37743854

@@ -3936,7 +4016,7 @@ ngx.req.get_uri_args
39364016
--------------------
39374017
**syntax:** *args = ngx.req.get_uri_args(max_args?)*
39384018

3939-
**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua**
4019+
**context:** *set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua**
39404020

39414021
Returns a Lua table holding all the current request URL query arguments.
39424022

@@ -4725,7 +4805,7 @@ ngx.log
47254805
-------
47264806
**syntax:** *ngx.log(log_level, ...)*
47274807

4728-
**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.**
4808+
**context:** *init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua**
47294809

47304810
Log arguments concatenated to error.log with the given logging level.
47314811

@@ -4761,7 +4841,7 @@ ngx.exit
47614841
--------
47624842
**syntax:** *ngx.exit(status)*
47634843

4764-
**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.**
4844+
**context:** *rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua**
47654845

47664846
When `status >= 200` (i.e., `ngx.HTTP_OK` and above), it will interrupt the execution of the current request and return status code to nginx.
47674847

@@ -7211,6 +7291,25 @@ This feature requires at least ngx_lua `v0.10.0`.
72117291

72127292
[Back to TOC](#nginx-api-for-lua)
72137293

7294+
ngx.balancer
7295+
------------
7296+
**syntax:** *local balancer = require "ngx.balancer"*
7297+
7298+
This is a Lua module that provides a Lua API to allow defining completely dynamic load balancers
7299+
in pure Lua.
7300+
7301+
This Lua module does not ship with this ngx_lua module itself rather it is shipped with
7302+
the
7303+
[lua-resty-core](https://github.com/openresty/lua-resty-core) library.
7304+
7305+
Please refer to the [documentation](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md)
7306+
for this `ngx.balancer` Lua module in [lua-resty-core](https://github.com/openresty/lua-resty-core)
7307+
for more details.
7308+
7309+
This feature requires at least ngx_lua `v0.10.0`.
7310+
7311+
[Back to TOC](#nginx-api-for-lua)
7312+
72147313
ndk.set_var.DIRECTIVE
72157314
---------------------
72167315
**syntax:** *res = ndk.set_var.DIRECTIVE_NAME*

config

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
352352
$ngx_addon_dir/src/ngx_http_lua_config.c \
353353
$ngx_addon_dir/src/ngx_http_lua_worker.c \
354354
$ngx_addon_dir/src/ngx_http_lua_lex.c \
355+
$ngx_addon_dir/src/ngx_http_lua_balancer.c \
355356
"
356357

357358
NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
@@ -407,6 +408,7 @@ NGX_ADDON_DEPS="$NGX_ADDON_DEPS \
407408
$ngx_addon_dir/src/ngx_http_lua_config.h \
408409
$ngx_addon_dir/src/ngx_http_lua_worker.h \
409410
$ngx_addon_dir/src/ngx_http_lua_lex.h \
411+
$ngx_addon_dir/src/ngx_http_lua_balancer.h \
410412
"
411413

412414
CFLAGS="$CFLAGS -DNDK_SET_VAR"

doc/HttpLuaModule.wiki

Lines changed: 93 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1853,6 +1853,76 @@ When a relative path like <code>foo/bar.lua</code> is given, they will be turned
18531853
18541854
This directive was first introduced in the <code>v0.5.0rc31</code> release.
18551855
1856+
== balancer_by_lua_block ==
1857+
1858+
'''syntax:''' ''balancer_by_lua_block { lua-script }''
1859+
1860+
'''context:''' ''upstream''
1861+
1862+
'''phase:''' ''content''
1863+
1864+
This directive runs Lua code as an upstream balancer for any upstream entities defined
1865+
by the <code>upstream {}</code> configuration block.
1866+
1867+
For instance,
1868+
1869+
<geshi lang="nginx">
1870+
upstream foo {
1871+
server 127.0.0.1;
1872+
balancer_by_lua_block {
1873+
-- use Lua to do something interesting here
1874+
-- as a dynamic balancer
1875+
}
1876+
}
1877+
1878+
server {
1879+
location / {
1880+
proxy_pass http://foo;
1881+
}
1882+
}
1883+
</geshi>
1884+
1885+
The resulting Lua load balancer can work with any existing nginx upstream modules
1886+
like [http://nginx.org/en/docs/http/ngx_http_proxy_module.html ngx_proxy] and
1887+
[http://nginx.org/en/docs/http/ngx_http_fastcgi_module.html ngx_fastcgi].
1888+
1889+
Also, the Lua load balancer can work with the standard upstream connection pool mechanism,
1890+
i.e., the standard [http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive keepalive] directive.
1891+
Just ensure that the [http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive keepalive] directive
1892+
is used *after* this <code>balancer_by_lua_block</code> directive in a single <code>upstream {}</code> configuration block.
1893+
1894+
The Lua load balancer can totally ignore the list of servers defined in the <code>upstream {}</code> block
1895+
and select peer from a completely dynamic server list (even changing per request) via the
1896+
[https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md ngx.balancer] module
1897+
from the [https://github.com/openresty/lua-resty-core lua-resty-core] library.
1898+
1899+
The Lua code handler registered by this directive might get called more than once in a single
1900+
downstream request when the nginx upstream mechanism retries the request on conditions
1901+
specified by directives like the [http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream proxy_next_upstream]
1902+
directive.
1903+
1904+
This Lua code execution context does not support yielding, so Lua APIs that may yield
1905+
(like cosockets and "light threads") are disabled in this context. One can usually work
1906+
around this limitation by doing such operations in an earlier phase handler (like
1907+
[[#access_by_lua|access_by_lua*]]) and passing along the result into this context
1908+
via the [[#ngx.ctx|ngx.ctx]] table.
1909+
1910+
This directive was first introduced in the <code>v0.10.0</code> release.
1911+
1912+
== balancer_by_lua_file ==
1913+
1914+
'''syntax:''' ''balancer_by_lua_file <path-to-lua-script-file>''
1915+
1916+
'''context:''' ''upstream''
1917+
1918+
'''phase:''' ''content''
1919+
1920+
Equivalent to [[#balancer_by_lua_block|balancer_by_lua_block]], except that the file specified by <code><path-to-lua-script-file></code> contains the Lua code, or, as from the <code>v0.5.0rc32</code> release, the [[#Lua/LuaJIT bytecode support|Lua/LuaJIT bytecode]] to be executed.
1921+
1922+
When a relative path like <code>foo/bar.lua</code> is given, they will be turned into the absolute path relative to the <code>server prefix</code> path determined by the <code>-p PATH</code> command-line option while starting the Nginx server.
1923+
1924+
This directive was first introduced in the <code>v0.10.0</code> release.
1925+
18561926
== lua_need_request_body ==
18571927
18581928
'''syntax:''' ''lua_need_request_body <on|off>''
@@ -2427,7 +2497,7 @@ These constants are usually used by the [[#ngx.log|ngx.log]] method.
24272497
== print ==
24282498
'''syntax:''' ''print(...)''
24292499
2430-
'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*''
2500+
'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, ngx.balancer_by_lua*''
24312501
24322502
Writes argument values into the nginx <code>error.log</code> file with the <code>ngx.NOTICE</code> log level.
24332503
@@ -2442,7 +2512,7 @@ Lua <code>nil</code> arguments are accepted and result in literal <code>"nil"</c
24422512
There is a hard coded <code>2048</code> byte limitation on error message lengths in the Nginx core. This limit includes trailing newlines and leading time stamps. If the message size exceeds this limit, Nginx will truncate the message text accordingly. This limit can be manually modified by editing the <code>NGX_MAX_ERROR_STR</code> macro definition in the <code>src/core/ngx_log.h</code> file in the Nginx source tree.
24432513
24442514
== ngx.ctx ==
2445-
'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*''
2515+
'''context:''' ''init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, ngx.timer.*, balancer_by_lua*''
24462516
24472517
This table can be used to store per-request Lua context data and has a life time identical to the current request (as with the Nginx variables).
24482518
@@ -2998,7 +3068,7 @@ For reading ''request'' headers, use the [[#ngx.req.get_headers|ngx.req.get_head
29983068
== ngx.resp.get_headers ==
29993069
'''syntax:''' ''headers = ngx.resp.get_headers(max_headers?, raw?)''
30003070
3001-
'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*''
3071+
'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua*''
30023072
30033073
Returns a Lua table holding all the current response headers for the current request.
30043074
@@ -3097,7 +3167,7 @@ This method was first introduced in the <code>v0.7.17</code> release.
30973167
== ngx.req.get_method ==
30983168
'''syntax:''' ''method_name = ngx.req.get_method()''
30993169
3100-
'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*''
3170+
'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, balancer_by_lua*''
31013171
31023172
Retrieves the current request's request method name. Strings like <code>"GET"</code> and <code>"POST"</code> are returned instead of numerical [[#HTTP method constants|method constants]].
31033173
@@ -3240,7 +3310,7 @@ See also [[#ngx.req.set_uri|ngx.req.set_uri]].
32403310
== ngx.req.get_uri_args ==
32413311
'''syntax:''' ''args = ngx.req.get_uri_args(max_args?)''
32423312
3243-
'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*''
3313+
'''context:''' ''set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua, log_by_lua*, balancer_by_lua*''
32443314
32453315
Returns a Lua table holding all the current request URL query arguments.
32463316
@@ -3919,7 +3989,7 @@ Just as [[#ngx.print|ngx.print]] but also emit a trailing newline.
39193989
== ngx.log ==
39203990
'''syntax:''' ''ngx.log(log_level, ...)''
39213991
3922-
'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*''
3992+
'''context:''' ''init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*''
39233993
39243994
Log arguments concatenated to error.log with the given logging level.
39253995
@@ -3949,7 +4019,7 @@ Since <code>v0.8.3</code> this function returns <code>1</code> on success, or re
39494019
== ngx.exit ==
39504020
'''syntax:''' ''ngx.exit(status)''
39514021
3952-
'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*''
4022+
'''context:''' ''rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*''
39534023
39544024
When <code>status >= 200</code> (i.e., <code>ngx.HTTP_OK</code> and above), it will interrupt the execution of the current request and return status code to nginx.
39554025
@@ -6099,6 +6169,22 @@ for more details.
60996169
61006170
This feature requires at least ngx_lua <code>v0.10.0</code>.
61016171
6172+
== ngx.balancer ==
6173+
'''syntax:''' ''local balancer = require "ngx.balancer"''
6174+
6175+
This is a Lua module that provides a Lua API to allow defining completely dynamic load balancers
6176+
in pure Lua.
6177+
6178+
This Lua module does not ship with this ngx_lua module itself rather it is shipped with
6179+
the
6180+
[https://github.com/openresty/lua-resty-core lua-resty-core] library.
6181+
6182+
Please refer to the [https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md documentation]
6183+
for this <code>ngx.balancer</code> Lua module in [https://github.com/openresty/lua-resty-core lua-resty-core]
6184+
for more details.
6185+
6186+
This feature requires at least ngx_lua <code>v0.10.0</code>.
6187+
61026188
== ndk.set_var.DIRECTIVE ==
61036189
'''syntax:''' ''res = ndk.set_var.DIRECTIVE_NAME''
61046190

0 commit comments

Comments
 (0)