OpenResty与location

nginx的location可以说是非常强大的,每一个location都可以看作是一个service,而location之间相互跳转、调用,也是家常便饭。

内部调用

对于一些接口,我们可以设计一个统一接口,而将其背后的实现作为internal,从而让这些内部接口相对独立。

例子:

worker_processes  1;
error_log logs/error.log info;

events {
    worker_connections 512;
}

http {

    log_format myformat '$remote_addr $status $time_local';
    access_log logs/access.log myformat;

    server {
        listen 8080;
        charset utf-8;

        location /add {
            internal;

            content_by_lua_block {
                local args = ngx.req.get_uri_args()
                ngx.say(tonumber(args.a) + tonumber(args.b))
            }
        }
        location = / {
            content_by_lua_block {
                local res = ngx.location.capture (
                    "/add", {args={a=3,b=4}}
                )
                ngx.say("status:", res.status, "response:", res.body)
            }
        }
    }
}

location的add作为一个内部服务,由主接口调用这个内部服务,因为/add是内部的,所以如果你试图访问的话,会得到404错误。

并行运行

如果我们知道两个location之间的操作没有先后顺序,那么我们就可以把这两个操作并行运行,以降低相应时间。我们还可以通过一个简单的例子,来测试。

worker_processes  1;
error_log logs/error.log info;

events {
    worker_connections 512;
}

http {

    log_format myformat '$remote_addr $status $time_local';
    access_log logs/access.log myformat;

    server {
        listen 8080;
        charset utf-8;

        location /add {
            internal;

            content_by_lua_block {
                ngx.sleep(0.1)
                local args = ngx.req.get_uri_args()
                ngx.say(tonumber(args.a) + tonumber(args.b))
            }
        }

        location /sum {
            internal;

            content_by_lua_block {
                ngx.sleep(0.1)
                local args = ngx.req.get_uri_args()
                ngx.say(tonumber(args.a) + tonumber(args.b))
            }
        }

        location = / {
            content_by_lua_block {
                local res = ngx.location.capture (
                    "/add", {args={a=3,b=4}}
                )
                ngx.say("status:", res.status, "response:", res.body)
            }
        }

        location = /test_parallels {
            content_by_lua_block {
                local start = ngx.now()
                local res1, res2 = ngx.location.capture_multi(
                    {
                        {"/add", {args={a=1, b=2}}},
                        {"/sum", {args={a=3, b=4}}}
                    }
                )
                ngx.say("status:", res1.status, " response:", res1.body)
                ngx.say("status:", res2.status, " response:", res2.body)
                ngx.say("Time used:", ngx.now() - start)
            }
        }

        location = /test_queue {
            content_by_lua_block {
                local start = ngx.now()
                local res1 = ngx.location.capture_multi(
                    {
                        {"/add", {args={a=1, b=2}}}
                    }
                )
                local res2 = ngx.location.capture_multi(
                    {
                        {"/sum", {args={a=3, b=4}}}
                    }
                )
                ngx.say("status:", res1.status, " response:", res1.body)
                ngx.say("status:", res2.status, " response:", res2.body)
                ngx.say("Time used:", ngx.now() - start)
            }
        }
    }
}

还是上面的那个例子,我们增加了一个加法调用,然后使用两种不同的方式,对这两个加法调用进行调用。测试结果:

@ubuntu:~/Desktop/work$ curl http://localhost:8080/test_parallels
status:200 response:3
status:200 response:7
Time used:0.10099983215332
@ubuntu:~/Desktop/work$ curl http://localhost:8080/test_queue
status:200 response:3
status:200 response:7
Time used:0.20299983024597

可以看到,并行的运行时间大概是串行的一半,虽然实践上不会这么准确,单道理将明白了。