Communications Sequence with Upstream

agentzh agentzh at gmail.com
Sun Apr 25 13:35:24 MSD 2010


On Sun, Apr 25, 2010 at 4:58 PM, Magnus Lynch <maglyx at gmail.com> wrote:
> Say I have a location /url that I want to construct responses to based
> on a sequence of communications with an upstream, host:port. To be
> specific, the upstream would be a database, and the sequence of
> communications would comprise commands and responses.

We've been doing this kind of things via ngx_echo's echo_location
directive in our ngx_memc and ngx_drizzle's tests suite. Here's some
an example to do sequential memcached command execution against the
ngx_memc upstream module in a single location /main:

    location /main {
        echo_location '/memc?cmd=flush_all';
        echo_location '/memc?key=foo&cmd=set&val=';
        echo_location '/memc?key=foo&cmd=get';
    }
    location /memc {
        set $memc_cmd $arg_cmd;
        set $memc_key $arg_key;
        set $memc_value $arg_val;
        memc_pass 127.0.0.1:11211;
    }

You can find more examples here:
http://github.com/agentzh/memc-nginx-module/blob/master/test/t/

And here's an example for sequential SQL queries against a mysql backend:

    location /test {
        echo_location /mysql "drop table if exists foo";
        echo;
        echo_location /mysql "create table foo (id serial, name
char(10), age integer);";
        echo;
        echo_location /mysql "insert into foo (name, age) values ('', null);";
        echo;
        echo_location /mysql "insert into foo (name, age) values (null, 0);";
        echo;
        echo_location /mysql "select * from foo order by id";
        echo;
    }
    location /mysql {
        drizzle_pass backend;
        drizzle_module_header off;
        drizzle_query $query_string;
        rds_json on;
    }

Responses look like this

    {"errcode":0}
    {"errcode":0}
    {"errcode":0,"insert_id":1,"affected_rows":1}
    {"errcode":0,"insert_id":2,"affected_rows":1}
    [{"id":1,"name":"","age":null},{"id":2,"name":null,"age":0}]

More examples can be seen here:
http://github.com/agentzh/rds-json-nginx-module/blob/master/test/t/sanity.t

> A simple example
> of what I'd like to do would be:
>  1. client communicates message to /url meaning "if key foo exists,
> add 1 to bar"
>  2. module handling /url sends first database command to check if foo
> exists, if not reply "failed" to client, or it does and
>  3. module sends database command to increment bar, replies "succeeded".
>

It reminds me of the "safe incr" sample in my slides for my talk on
nginx.conf scripting:

    http://agentzh.org/misc/slides/nginx-conf-scripting/nginx-conf-scripting.html

(Use the arrow keys on your keyboard to switch pages there.)

> The details are arbitrary, but I would think there are myriad examples
> where you'd want a module to construct a reply based on back and forth
> communications.
>

Check out ngx_echo module to see if it fits your needs:

    http://wiki.nginx.org/NginxHttpEchoModule

> I'm hoping there's some nice way of handling this case, but from I've
> gathered looking at the code it seems oriented to "1 message to
> module, filter as desired, send to upstream, get response, filter
> again, then response back to client."
>

IMHO, Evan Miller's Guide is very limited in expressing nginx's full
power ;) It's just a good old introductory guide anyway :) Still many
thanks to Evan Miller because the guide has helped so many people
including me :)

I must add that the echo_location and echo_subrequest thingies in
ngx_echo are still limited in power :) We're currently releasing the
full power of nginx's subrequests in our ngx_lua module. Soon we'll be
able to do things like this on the Lua land:

     res = ngx.location.capture('/sub1?id=32');
     if (res ...) {
           res2 = ngx.location.capture('/sub2?id=56');
     } else {
           res2 = ngx.subrequest.capture(ngx.HTTP_POST, '/sub2?id=56',
{ body: 'hello' });
     }

And all the capture operations are transparent non-blocking I/O ones
that are based on nginx's subrequests. Thanks to coco lua's C-level
coroutine support!

There will also be equivalences to the echo_location and
echo_location_async directives on the Lua land, i.e.,
ngx.location.echo and ngx.location.echo_async :)

Stay tuned!
-agentzh



More information about the nginx mailing list