Openresty torch GPU module loading issue - nginx

I am using openresty with lua. When I was loading torch without cutorch,cunn(GPU) it was working fine. But it is unable to load cutorch module.
Here is my nginx.conf
error_log stderr notice;
daemon off;
events{}
http {
lua_code_cache on;
#lua_package_cpath '/usr/local/cuda/include/?.so;;';
init_by_lua_file 'evaluate.lua';
server {
listen 6788;
lua_code_cache on;
lua_need_request_body on;
client_body_buffer_size 10M;
client_max_body_size 10M;
location /ff {
# only permit POST requests
if ($request_method !~ ^(POST)$ ) {
return 403;
}
content_by_lua '
local body = ngx.req.get_body_data()
if body == nil then
ngx.say("empty body")
else
local resp =FeedForward(body)
ngx.say(cjson.encode({result=resp}))
end
';
}
}
}
Here is my evaluate.lua code
-- load the required lua models
torch = require("torch")
nn = require("nn")
gm = require("image")
cutorch = require "cutorch"
cunn = require "cunn"
cjson = require("cjson")
-- model
modelPath='./model.t7'
ninputs = 3
model = nn.Sequential()
model:add(nn.Linear(ninputs,2))
-- let’s save a dummy model
-- to demonstrate the functionality
torch.save(modelPath, model)
-- load a pretrained model
net = torch.load(modelPath)
net:cuda()
net:evaluate()
-- our end point function
-- this function is called by the ngx server
-- accepts a json body
function FeedForward(json)
print("starting")
-- decode and extract field x
local data = cjson.decode(json)
local input = torch.Tensor(data.x)
local response = {}
-- example checks
if input == nil then
print("No input given")
elseif input:size(1) ~=ninputs then
print("Wrong input size")
else
-- evaluat the input and create a response
local output = net:forward(input:cuda()):float()
-- from tensor to table
for i=1,output:size(1) do
response[i] = output[i]
end
end
-- return response
return response
end
I am trying to run the model using following commands
/usr/local/openresty/nginx/sbin/nginx -p "$(pwd)" -c "nginx.conf"
It's starting up fine but when I am sending curl request like
curl -H "Content-Type: application/json" -X POST -d '{"x":[1,2,3]}' http://localhost:6788/ff
I am getting following error.
2016/09/29 12:59:59 [notice] 10355#0: *1 [lua] evaluate.lua:28: FeedForward(): starting, client: 127.0.0.1, server: , request: "POST /ff HTTP/1.1", host: "localhost:6788"
THCudaCheck FAIL file=/tmp/luarocks_cutorch-scm-1-700/cutorch/lib/THC/generic/THCStorage.cu line=40 error=3 : initialization error
2016/09/29 12:59:59 [error] 10355#0: *1 lua entry thread aborted: runtime error: unknown reason
stack traceback:
coroutine 0:
[C]: in function 'resize'
/home/ubuntu/torch/install/share/lua/5.1/cutorch/Tensor.lua:14: in function 'cuda'
/rootpath/evaluate.lua:41: in function 'FeedForward'
content_by_lua(nginx.conf:31):7: in function <content_by_lua(nginx.conf:31):1>, client: 127.0.0.1, server: , request: "POST /ff HTTP/1.1", host: "localhost:6788"
Without cutorch the model is running fine like If I remove
net:cuda()
and replace line
local output = net:forward(input:cuda()):float()
by
local output = net:forward(input):float()
It's working fine. Also I tried to run evaluate.lua using th and it's working fine there with cutorch and cunn packages.

Related

How can I `encode_base64` string in lua in nginx?

I am using lua inside nginx, below is the code to encode a string:
set_by_lua $base64_credential '
set $es_username os.getenv("ES_USERNAME");
set $es_pwd os.getenv("ES_PWD");
return ngx.encode_base64(ngx.var.es_username+":"+ngx.var.es_pwd)
'
after launching the server I got below error:
2021/11/18 01:58:01 [error] 7#7: *151 failed to load inlined Lua code: set_by_lua:2: '=' expected near '$', client: 10.0.6.61, server: localhost, request: "GET /health HTTP/1.1", host: "10.0.1.246:8080"
I use the syntax from this doc https://github.com/openresty/lua-nginx-module#set_by_lua and it doesn't use = sign when set a variable. What did I do wrong?
Again, you made a couple of errors. Lua operator for string concatenation is ... Lua doesn't expect semicolons between the operators. You have a weird mix of lua and nginx configuration syntax. If you don't need those $es_username and $es_pwd variables elsewhere, use
set_by_lua $base64_credential '
local es_username = os.getenv("ES_USERNAME")
local es_pwd = os.getenv("ES_PWD")
return ngx.encode_base64(es_username .. ":" .. es_pwd)
';
If you need those variables elsewhere, then your way is
set_by_lua $es_username 'return os.getenv("ES_USERNAME")';
set_by_lua $es_pwd 'return os.getenv("ES_PWD")';
set_by_lua $base64_credential 'return ngx.encode_base64(ngx.var.es_username .. ":" .. ngx.var.es_pwd)';

Metrics for nginx stream module

I'm trying to get metrics from nginx about the total connections when using the nginx stream module. I know there is stub_status option but it looks like its only for http and not stream.
I found the prometheus lua plugin which has stream, but I was not able to figure out the right conf for it. I only get the built-in error metric but not the metric defined. Here's the conf and the response. Whats also weird is that the response is in the header and not body.
stream {
lua_shared_dict prometheus_metrics 10M;
lua_package_path "/tmp/nginx-lua-prometheus/?.lua;/usr/local/openresty/luajit/lib/lua/5.1/?.lua;;";
init_by_lua '
prometheus = require("prometheus").init("prometheus_metrics")
metric_requests = prometheus:counter("nginx_http_requests_total", "Number of HTTP requests", {"test"})
metric_connections = prometheus:gauge("nginx_http_connections", "Number of HTTP connections", {"test"})';
log_by_lua_block {
metric_requests:inc(1, {"test"})
}
server {
listen 9145;
content_by_lua '
local sock = assert(ngx.req.socket(true))
local data = sock:receive()
local location = "GET /metrics"
if string.sub(data, 1, string.len(location)) == location then
ngx.say("HTTP/1.1 200 OK")
ngx.say("Content-Type: text/plain")
ngx.say("yo")
ngx.say(table.concat(prometheus:metric_data(), ""))
else
ngx.say("HTTP/1.1 404 Not Found")
end
';
}
}
curl localhost:9145/metrics -v
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 9145 (#0)
> GET /metrics HTTP/1.1
> Host: localhost:9145
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: text/plain
< # HELP nginx_metric_errors_total Number of nginx-lua-prometheus errors
< # TYPE nginx_metric_errors_total counter
< nginx_metric_errors_total 0
* no chunk, no close, no size. Assume close to signal end
<
* Curl_http_done: called premature == 0
* Closing connection 0
https://github.com/knyar/nginx-lua-prometheus/issues/77
Answered here
log_by_lua_block {
metric_connections:set(ngx.var.connections_active, {"active"})
metric_connections:set(ngx.var.connections_reading, {"reading"})
metric_connections:set(ngx.var.connections_writing, {"writing"})
metric_connections:set(ngx.var.connections_waiting, {"waiting"})
metric_requests:inc(1, {"test"})
}

Pass POST data to unix domain socket through nginx

I have a unix domain socket file and it is working with with nc command. Now I want to access it via nginx but it does not work. Am I missing something?
test with nc => it works
$ echo '{ "method" : "getinfo", "params" : [], "id" : "1" }' | nc -U /home/zono/.lightning/lightning-rpc
{ "jsonrpc": "2.0", "id" : "1", "result" :
{
"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
test via nginx => it does not work
// /etc/nginx/sites-enabled/default
upstream nginx-internal-sock {
server unix:/home/zono/.lightning/lightning-rpc;
}
server {
listen 80;
location / {
proxy_pass http://nginx-internal-sock;
}
}
$ curl -H "content-type: application/json" -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1
2019-03-20T04:25:52.551Z lightningd(30143):jcon fd 32: Invalid token in json input: 'POST / HTTP/1.0??Host: nginx-internal-sock??Connection: close??C'
Update 1
There's been a development. However I can't get whole data.
// install nginx-extras
apt-get install nginx-extras
// /etc/nginx/sites-enabled/default
server {
listen 80;
location / {
content_by_lua '
ngx.req.read_body()
local body_data = ngx.req.get_body_data()
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:/home/zono/.lightning/lightning-rpc")
local bytes = sock:send(body_data)
local line, err = sock:receive("*a")
ngx.say(line)
ok, err = sock:close()
';
}
}
// Response is nil
$ curl -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1
nil
// /var/log/nginx/error.log
2019/03/20 07:43:39 [error] 4926#4926: *35 lua tcp socket read timed out, client: 127.0.0.1, server: , request: "POST / HTTP/1.1", host: "127.0.0.1"
// When I set "sock:receive("*l")" the response is the part of the data.
$ curl -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1
{ "jsonrpc": "2.0", "id" : "1", "result" :
I'm checking the reference now. http://w3.impa.br/~diego/software/luasocket/tcp.html
'*a': reads from the socket until the connection is closed. No end-of-line translation is performed;
'*l': reads a line of text from the socket. The line is terminated by a LF character (ASCII 10), optionally preceded by a CR character (ASCII 13). The CR and LF characters are not included in the returned line. In fact, all CR characters are ignored by the pattern. This is the default pattern;
number: causes the method to read a specified number of bytes from the socket.
I found out the answer.
// install nginx-extras
apt-get install nginx-extras
// /etc/nginx/sites-enabled/default
server {
listen 80;
location / {
content_by_lua '
ngx.req.read_body()
local body_data = ngx.req.get_body_data()
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:/home/zono/.lightning/lightning-rpc")
local bytes = sock:send(body_data)
local readline = sock:receiveuntil("\\n\\n")
local line, err, part = readline()
if line then
ngx.say(line)
end
ok, err = sock:close()
';
}
}
// curl
$ curl -X POST --data '{ "method" : "getinfo", "params" : [], "id" : "1" }' http://127.0.0.1

Strange io.popen behaviour in lua

I have lua block in nginx config, which checks for redis-server connection and if 4 java-processes are up, and then returns 200 or 500 status accordingly to this checks.
location = /healthcheck {
content_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.status = 500
return
end
local ps = io.popen("/bin/ps aux |grep -c '[j]ava.*63'")
local output = tostring(ps:read('*a'))
ps:close()
if string.match(output, '4') then
ngx.status = 200
else
ngx.status = 500
end
}
}
But periodically output variable takes nil value, while it shouldn't. Just can't get why it happens.
Thanks in advance, comrades.
UPD:
Using tonumber fails on
bad argument #2 to 'tonumber' (number expected, got string)
Updated location config:
location = /healthcheck {
content_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.status = 500
return
end
local ps = io.popen("/bin/ps aux |grep -c '[j]ava.*63'")
local output = tonumber(ps:read())
ps:close()
if (output == 4) then
ngx.status = 200
else
ngx.status = 500
end
}
}
UPD2:
Logging to nginx error (with tostring) prints next:
grep: write error: Broken pipe
2016/04/19 17:54:48 [error] 301#0: *5 [lua] content_by_lua(healthcheck.conf:33):20: OUTPUT:nil
UPD3:
Using command grep -c '[j]ava.*63' <(/bin/ps aux) to avoid the use of pipe:
local ps = io.popen("grep -c '[j]ava.*63' <(/bin/ps aux)")
getting next error:
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `grep -c '[j]ava.*63' <(/bin/ps aux)'
According to this answer and some testing next config do the job:
location = /healthcheck {
content_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeout(1000)
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
ngx.status = 500
return
end
local ps = io.popen("/bin/ps aux >/tmp/ps.out", "w")
ps:close()
local ps = io.popen("grep -c '[j]ava.*63' /tmp/ps.out")
local output = tostring(ps:read())
ps:close()
if string.match(output, '4') then
ngx.status = 200
else
ngx.status = 500
end
}
}

lua with Nginx : bad argument to 'getNewSessionID' (string expected, got nil)

I have compiled nginx with Lua. and i am facing a problem .
When i hit localhost i get an error in nginx error logs
2015/05/29 07:41:32 [error] 112#0: *1 lua entry thread aborted: runtime error: /opt/hello.lua:11: bad argument #1 to 'getNewSessionID' (string expected, got nil)
stack traceback:
coroutine 0:
[C]: in function 'getNewSessionID'
Nginx configurations are
location / {
default_type 'text/html';
content_by_lua_file /opt/hello.lua;
}
And my hello.lua look like
package.path = package.path ..';/opt/?.lua'
JSON = (loadfile "/opt/JSON.lua")()
local proxyFunctions = require("proxyCode")
coherenceNGIXLocation = "/coherence"
local coherenceCookie = proxyFunctions.getExistingSessionID()
-- To Create a coherance Session if not present
if (not coherenceCookie or coherenceCookie == '') then
-- ngx.log(ngx.INFO,"No Coherence Session Exists, Creating New")
local uidCookieValueEncoded = proxyFunctions.base64Encode(str,proxyFunctions.getNewSessionID())
local sessCreateResponse = proxyFunctions.coherencePut('{"sessionToken":"'..uidCookieValueEncoded..'"}')
local parsedJSON= JSON:decode(sessCreateResponse.body)
ngx.log(ngx.INFO, "Coherence Session Create")
ngx.log(ngx.INFO, "\n\n\n=============Coherence Res==============\n\n\n"..sessCreateResponse.body.."\n\n\n=============Coherence Res==============\n\n\n")
end
local client_cookie = ngx.req.get_headers()["cookie"]
-- To Create a coherance Session if not present
ngx.log(ngx.DEBUG, "\n\n\n=============REQ==============\n\n\n"..proxyFunctions.deepPrint(ngx.req.get_headers()).."\n\n\n=============REQ==============\n\n\n")
-- Set the cookie for the legacy request
ngx.req.set_header('cookie', client_cookie)
ngx.log(ngx.INFO, "\n\n\n=============REQ URI==============\n\n\n"..ngx.var.request_uri.."\n\n\n=============REQ URI==============\n\n\n")
local legacy_res = ngx.location.capture("/app"..ngx.var.request_uri, { share_all_vars = true })
ngx.log(ngx.DEBUG, "\n\n\n=============APP Res==============\n\n\n"..proxyFunctions.deepPrint(legacy_res.header).."\n\n\n=============APP Res==============\n\n\n")
if (legacy_res.status == 302) then
ngx.redirect(legacy_res.header.Location )
else
ngx.log(ngx.INFO, "Passing the Page/Layout to Maken")
local dev_res_encoded = legacy_res.body
dev_res_encoded = ngx.escape_uri(dev_res_encoded)
-- ngx.req.set_header('Cookie', ngx.req.get_headers()["cookie"])
-- ngx.req.set_header("Content-Type", "text/html") -- application/x-www-form-urlencoded -- 'page='..dev_res_encoded
ngx.req.set_header('cookie', client_cookie) -- maken/render
-- legacy_res.header('Content-Length', legacy_res.header['Content-Length']);
local maken_res = ngx.location.capture("/maken/", {method = ngx.HTTP_POST, body = legacy_res.body, share_all_vars = true} )
ngx.header['Set-Cookie'] = legacy_res.header["Set-Cookie"]
ngx.log(ngx.INFO, "Sending Back Maken Response to Client/Browser with Cookies from lagacy")
ngx.say(maken_res.body)
end
My proxyCode.lua looks like
function _M.getNewSessionID()
-- strip the sessionID length 11 cookie name before putting into the session
-- return string.sub(ngx.var.uid_set,11)
return _M.removeCookieSessionPrefixname(ngx.var.uid_set,11)
end
function _M.removeCookieSessionPrefixname(cookieName)
return string.sub(cookieName,11)
end
function _M.getIncomingAuthToken()
local cookie = ngx.req.get_headers()["Cookie"]
if (cookie ~=nil) then
local str = string.match(cookie,"AuthToken=(.*)$")
if (str ~= nil) then
return string.sub(str,11)
end
end
return nil
end
Can someone help me why i am getting this error ? i am new to Lua programming. and trying to run legacy application on my laptop.

Resources