openresty / redis2-nginx-module

Nginx upstream module for the Redis 2.0 protocol
http://wiki.nginx.org/HttpRedis2Module
901 stars 142 forks source link

Redis2_pass with <host>:<port> from $args fail #11

Open maxf3r opened 12 years ago

maxf3r commented 12 years ago

I'm trying to address several redis instances, dispatching it on a host:port basis (one single backend location)

here my nginx.conf location ... location /redis_backend { internal; set_unescape_uri $verb $arg_verb; set_unescape_uri $key $arg_key; set_unescape_uri $r_host $arg_host; set_unescape_uri $r_port $arg_port; redis2_query $verb $key; redis2_pass $r_host:$r_port; } ...

I call /redis_backend location from a lua like this:

.... r_instance["redis_host"] = '127.0.0.1' r_instance["redis_port"] = '33001' .... local res = ngx.location.capture ( "/redis_backend", { args = { verb = r_verb, key = redis_key, host = r_instance["redis_host"], port = r_instance["redis_port"], } } ) ...

in nginx error log (i use the openresty suite ngx_openresty/1.0.10.44), I got this error 2012/04/07 19:25:03 [error] 11715#0: *1 redis2: upstream "127.0.0.1:33001" not found, client: 127.0.0.1, server: ....

I'm sure redis instance is up&running. I'm able to connect to her via redis-cli or, simply setting redis2_pass 127.0.0.1:33001;

ciao massimo

agentzh commented 12 years ago

I'm terribly sorry for the delay! I don't know why I missed the email for this ticket :(

ngx_redis2 only supports nginx variables pointing to upstream names that are already defined. For example:

 upstream foo { server ...; }
 upstream bar { server ...; }

and then we can have

location = /api {
    set $target 'foo';
    redis2_pass $target;
}

That will work. But you cannot specify raw host names and port number in the nginx variable for redis2_pass.

It seems that you're already using Lua to access ngx_redis2, so it is now recommended to use the lua-resty-redis library which is much more flexible and much easier to use than issuing subrequests to locations configured by ngx_redis2:

https://github.com/agentzh/lua-resty-redis

Also, this library is usually more efficient ;)

Thanks! -agentzh

signals2 commented 10 years ago

--location = /api { -- set $target 'foo'; -- redis2_pass $target; --}

It seems this feature is not working any more with v0.11, the error.log always says: [alert] 28236#0: *25 no upstream configuration

agentzh commented 10 years ago

@signals2 There has been a test case for this usage in ngx_redis2's test suite that keeps passing for long:

https://github.com/openresty/redis2-nginx-module/blob/master/t/sanity.t#L294

One common mistake is that you forget to define the named upstream {} blocks for all possible nginx variable values beforehand.

signals2 commented 10 years ago

Finally I find the answer, it's not working when using out of one or multiple if conditions, for example: if($arg_k) { redis2_query get $arg_k; } redis2_pass $arg_pool;

instead the following config is working: if ($arg_k) { redis2_query get $arg_k; redis2_pass $arg_pool; }

maybe i'm using it in a wrong way?

thanks

agentzh commented 10 years ago

@signals2 Please avoid the use of the "if" directive. See http://wiki.nginx.org/IfIsEvil

Better use ngx_lua and lua-resty-redis for such things.

signals2 commented 10 years ago

@agentzh thanks alot in my simple case, it's more convinient with this module than lua-resty-redis lua module, the evil 'if' is really a big surprise:(