与其他 location 配合

    例如对数据库、内部公共函数的统一接口,可以把它们放到统一的 location 中。通常情况下,为了保护这些内部接口,都会把这些接口设置为 。这么做的最主要好处就是可以让这个 内部接口相对独立,不受外界干扰

    示例代码:

    紧接着,稍微扩充一下,并行请求的效果,示例如下:

    1. location = /sum {
    2. internal;
    3. content_by_lua_block {
    4. ngx.sleep(0.1)
    5. local args = ngx.req.get_uri_args()
    6. ngx.print(tonumber(args.a) + tonumber(args.b))
    7. }
    8. }
    9. location = /subduction {
    10. internal;
    11. content_by_lua_block {
    12. ngx.sleep(0.1)
    13. local args = ngx.req.get_uri_args()
    14. ngx.print(tonumber(args.a) - tonumber(args.b))
    15. }
    16. }
    17. location = /app/test_parallels {
    18. content_by_lua_block {
    19. local start_time = ngx.now()
    20. local res1, res2 = ngx.location.capture_multi( {
    21. {"/sum", {args={a=3, b=8}}},
    22. {"/subduction", {args={a=3, b=8}}}
    23. })
    24. ngx.say("status:", res2.status, " response:", res2.body)
    25. ngx.say("time used:", ngx.now() - start_time)
    26. }
    27. location = /app/test_queue {
    28. content_by_lua_block {
    29. local start_time = ngx.now()
    30. local res1 = ngx.location.capture_multi( {
    31. {"/sum", {args={a=3, b=8}}}
    32. })
    33. local res2 = ngx.location.capture_multi( {
    34. {"/subduction", {args={a=3, b=8}}}
    35. })
    36. ngx.say("status:", res1.status, " response:", res1.body)
    37. ngx.say("status:", res2.status, " response:", res2.body)
    38. ngx.say("time used:", ngx.now() - start_time)
    39. }
    40. }

    测试结果:

    该方法,可以被广泛应用于广告系统(1:N 模型,一个请求,后端从 N 家供应商中获取条件最优广告)、高并发前端页面展示(并行无依赖界面、降级开关等)。

    现在的网络请求,已经变得越来越拥挤。各种不同 API 、下载请求混杂在一起,这就要求不同厂商针对下载的动态调整有不同的定制策略。而这些策略在一天的不同时间段,执行规则可能还不一样。这时候我们就可以效仿工厂的流水线模式,逐层过滤、处理。

    示例代码:

    1. location ~ ^/static/([-_a-zA-Z0-9/]+).jpg {
    2. set $image_name $1;
    3. content_by_lua_block {
    4. ngx.exec("/download_internal/images/"
    5. .. ngx.var.image_name .. ".jpg");
    6. };
    7. }
    8. location /download_internal {
    9. # 这里还可以有其他统一的 download 下载设置,例如限速等
    10. alias ../download;
    11. }

    这里的两个 location 更像是流水线上工人之间的协作关系。第一环节的工人完成自己的处理部分后,直接交给第二环节处理人(实际上可以有更多环节),它们之间的 数据流是定向 的。

    图例

    不知道大家什么时候开始注意的,百度的首页已经不再是 HTTP 协议,它已经全面修改到了 HTTPS 协议上。但是对于大家的输入习惯,估计还是在地址栏里面输入 baidu.com ,回车后发现它会自动跳转到 https://www.baidu.com ,这时候就需要的外部重定向了。

    执行测试,结果如下:

    1. ~ curl 127.0.0.1 -i
    2. HTTP/1.1 302 Moved Temporarily
    3. Server: openresty/1.9.3.2rc3
    4. Date: Sun, 22 Nov 2015 11:04:03 GMT
    5. Content-Type: text/html
    6. Content-Length: 169
    7. Connection: keep-alive
    8. Location: /foo
    9. <html>
    10. <head><title>302 Found</title></head>
    11. <body bgcolor="white">
    12. <center><h1>302 Found</h1></center>
    13. <hr><center>openresty/1.9.3.2rc3</center>
    14. </body>
    15. </html>
    16. ~ curl 127.0.0.1/foo -i
    17. HTTP/1.1 200 OK
    18. Server: openresty/1.9.3.2rc3
    19. Date: Sun, 22 Nov 2015 10:43:51 GMT
    20. Content-Type: text/html
    21. Transfer-Encoding: chunked
    22. Connection: keep-alive

    与之前两个应用实例不同的,外部重定向是可以跨域名的。例如从 A 网站跳转到 B 网站是绝对允许的。在 CDN 场景的大量下载应用中,一般分为调度、存储两个重要环节。调度就是通过根据请求方 IP 、下载文件等信息寻找最近、最快节点,应答跳转给请求方完成下载。