配置openresty使用lua併發請求API

背景

如今搞的系統先後端分離,採用 restful 風格設計 API.
隨着業務發展,出現了一個頁面的數據須要請求多個接口,才能完整展現數據.
致使頁面加載耗時很長.所以決定採用openresty 來併發請求客戶端發送來的接口地址,再一次性返回多個接口的數據給前端.這樣前端只須要請求服務端一次.還能夠任意組裝接口.
使用的框架是 laravel. 每個接口地址都要指定請求方式才能夠訪問.php

Lua語法

lua特殊點
1.默認變量,函數都是全局的.慎用.要用 local 修飾符.
2.字符串,數組下標是從1開始html

一.數據類型前端

nil 空
一個變量未被賦值就是 nil
將 nil賦予給一個全局變量就等於刪除它nginx

boolean 布爾
lua 中 nil 和 false 爲假.其餘爲真.0和空字符串也是真laravel

number 數字
用於表示實數. math.floor向下取整. math.ceil 向上取整json

string 字符串
lua 中字符串不能更改.也不能經過下標訪問某個字符.
在 lua 中.兩個徹底同樣的 lua 字符串在虛擬機中只會存儲一份.
每個字符串在建立時都會插入到 lua 虛擬機內部的一個全局的哈希表中.後端

table 表
table 類型實現了一種抽象的關聯數組.api

local  corp = {
    name   =    「kang」,
    age       =    20
}

function 函數
在 lua 中.函數也是一種數據類型.函數能夠存儲在變量中.經過參數傳遞給其餘函數.漢能夠做爲函數的返回值.數組

local  function  foo()
    local  x=10;
    local  y=20;
    return x+y;
end;

local  a=foo;
a();

二.表達式緩存

算術運算符
加+
減-
乘*
除/
指數^
取餘%

關係運算符
小於<
大於>
小於等於<=
大於等於>=
等於==
不等於~=

邏輯運算符
與 and
或 or
非 not

字符鏈接
使用操做符 「..」 (兩個點).
若是其任意一個是數字的話.將會把這個數字轉換爲字符串.

也能夠用 string 庫的函數 string.format 鏈接字符串.

string.format(「%s-%s」,」hello」,」word」);
hello-word

推薦使用 table.concat()來進行字符串拼接.由於 lua 中字符串是隻讀的.鏈接操做會建立一個新的字符串.性能損耗大.

三.表達式

1.單個 if 分支

x=10
if  x>0 then
    print(x);
end;

2.兩個分支 if-else

x=10
if x>0 then
    print(0);
else
    print(1)
end;

3.多個分支 if-elseif-else

score=10
if score==10 then
    print(1)
elseif  score==11  then
    print(2)
else
    print(3)
end;

4.whie 控制結構
while 表達式==真 do

todo

end;

x=1
sum=0
while x<=5 do
    sum = sum+x;
    x = x+1;
end;

5.repeat 控制結構
相似於 do-while 語句

repeat
    todo
until  條件==假

6.for
數字型
for var=begin,finish,step do

todo

end;
step 默認爲1

for i=1,5,1 do
    print(i);
end;

泛型
泛型 for 循環經過一個迭代器函數來遍歷全部制.

local  a= {「a」,」b」,」c」}
for i,v in ipairs(a) do
    print(i,v)
end;

lua 的基礎庫提供了 ipairs. 這是一個用於遍歷數組的迭代器函數.
用於迭代文件中每行的(io.lines)、
迭代 table 元素的(pairs)、
迭代數組元素的(ipairs)、
迭代字符串中單詞的(string.gmatch)

函數

函數的定義

function  name (arc)
    todo
end;

name = function (arc)

end;

沒有 local 修飾的都是全局變量.所以函數聲明局部函數也要用上 local

local function name (arc)
    todo
end;

函數名還能夠是 table 數量類型中某個字段.

function  stu.getName()
    todo
end;

函數的參數
lua 函數的參數大部分都是按值傳遞.

在調用函數的時候,若形參個數和實參個數不一樣時,Lua 會自動調整實參個數。調整規則:若實參個數大於形參個數,從左向右,多餘的實參被忽略;若實參個數小於形參個數,從左向右,沒有被實參初始化的形參會被初始化爲 nil。

變長參數
若形參爲 … 則該函數能夠接收不一樣長度的參數.訪問參數的時候也要使用...

local  function  func( ... )
    local  tmp = {…}
    for k,v  in  pairs(tmp) do
        print(v)
    end;
end;

函數的返回值
lua 容許函數返回多個值.

loca s,e = string.find(「hello word」,」llo");
返回字符串的開始位置和結束位置的下標

返回多個值時.值之間用」,」隔開.

調整規則: 若返回值個數大於接收變量的個數,多餘的返回值會被忽略掉; 若返回值個數小於參數個數,從左向右,沒有被返回值初始化的變量會被初始化爲 nil。

注意:當一個函數有一個以上返回值,且函數調用不是一個列表表達式的最後一個元素,那麼函數調用只會產生一個返回值,也就是第一個返回值。

local function init()       -- init 函數 返回兩個值 1 和 "lua"
    return 1, "lua"
end

local x, y, z = init(), 2   -- init 函數的位置不在最後,此時只返回 1
print(x, y, z)              -->output  1  2  nil

local a, b, c = 2, init()   -- init 函數的位置在最後,此時返回 1 和 "lua"
print(a, b, c)              -->output  2  1  lua

模塊
從 lua5.1開始.增長了對模塊和包的支持.
一個模塊的數據結構是用一個 lua 值(一般是一個 lua 表或者 lua 函數).
能夠使用 require()來加載和緩存模塊.

定義個模塊 my.lua

local foo={}

local function getname()
    return "Lucy"
end

function foo.greeting()
    print("hello " .. getname())
end

return foo

定義個 main.lua.調用 my.lua模塊

local fp = require("my")
fp.greeting()     -->output: hello Lucy

元表

setmetatable(table, metatable)
此方法用於爲一個表設置元表
getmetatable(table)
獲取表的元表對象

local  mytable = {}
local  metatable = {}
setmetatable(mytable, metatable);
or
mytable = setmetatable({},{})

修改表的操做符行爲
經過重載」__add」元方法來計算集合的並集;

local table_1 = {10,20,30};
local table_2 = {40,50,60};

local metatable = {};
metatable.__add = function (self, another)
    local sum = {};
    for k,v in pairs(self) do
        table.insert(sum,v);
    end;

    for k,v in pairs(another) do
        table.insert(sum,v);
    end
    return sum;
end;

setmetatable(table_1, metatable);

table_3 = table_1+table_2;
for k,v in pairs(table_3) do
    print(v)
end

除了加法能夠被重載以外,Lua 提供的全部操做符均可以被重載:

元方法 含義
"__add" + 操做
"__sub" - 操做 其行爲相似於 "add" 操做
"__mul" * 操做 其行爲相似於 "add" 操做
"__div" / 操做 其行爲相似於 "add" 操做
"__mod" % 操做 其行爲相似於 "add" 操做
"__pow" ^ (冪)操做 其行爲相似於 "add" 操做
"__unm" 一元 - 操做
"__concat" .. (字符串鏈接)操做
"__len" # 操做
"__eq" == 操做 函數 getcomphandler 定義了 Lua 怎樣選擇一個處理器來做比較操做 僅在兩個對象類型相同且有對應操做相同的元方法時才起效
"__lt" < 操做
"__le" <= 操做
除了操做符以外,以下元方法也能夠被重載,下面會依次解釋使用方法:

元方法 含義
"__index" 取下標操做用於訪問 table[key]
"__newindex" 賦值給指定下標 table[key] = value
"__tostring" 轉換成字符串
"__call" 當 Lua 調用一個值時調用
"__mode" 用於弱表(week table)
"__metatable" 用於保護metatable不被訪問

組合設計

安裝 openresty

推薦使用官網教程
https://openresty.org/cn/inst...

配置 nginx 使用 lua

location /kang {
    add_header content-type application/json;
    content_by_lua_file lua/kang.lua;
}

lua代碼

--加載 json 庫
local json = require "cjson";
--獲取請求方式
local request_method = ngx.var.request_method;
--判斷請求方式
if request_method == "GET" then
    ngx.say(json.encode({"only post"}));
    return;
end;

--讀取 post 參數.表單須要是 x-www-form-urlencoded
ngx.req.read_body();
local api_p = ngx.req.get_post_args();
--拼接子請求
local list = {};
for api,p in pairs(api_p) do
    local tmp = {api,{args=p,method=ngx.HTTP_GET}};
    table.insert(list, tmp);
end;
--發送子請求
local response = {ngx.location.capture_multi(list)};
--合併響應
local data = {};
for num,resp in pairs(response) do
    resp = json.decode(resp["body"]);
    data[resp["uri"]] = resp;
end;
--響應到客戶端
ngx.say(json.encode(data));


0.請求分爲父請求,子請求.父請求就是客戶端請求 nginx 服務器.子請求就是 catpure_multi,capture 函數發起的請求.
1.發出子請求時.要指定子請求的請求方式.否則默認使用父請求的請求方式
2.nginx 的內置變量 $request_uri 只能獲取到父請求.
若是要獲取到子請求.須要使用第三方庫ngx_echo 提供的內建變量 $echo_request_method
3.在 php 中獲取不到子請求.須要經過 fastcgi_param 傳到 php裏

配置 location

location /api {
            #記錄下子請求的請求方式, uri
            set $my_uri $uri;
            set $my_method $echo_request_method;

            root    /var/www/html;
            index  index.html index.htm;
            try_files $uri $uri/ /index.php?$query_string;
            access_log /usr/local/openresty/nginx/logs/access.log  main;
        }
location ~ \.php {
            root    /var/www/html/laravel/public;
            include        fastcgi_params;

            #fastcgi_pass    unix:/home/wenba/php/var/run/php.sock;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
            fastcgi_index  index.php;

            fastcgi_param   REQUEST_URI  $my_uri;
            fastcgi_param   REQUEST_METHOD $my_method;
            fastcgi_param  SCRIPT_NAME      $fastcgi_script_name;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        }

請求

clipboard.png

相關文章
相關標籤/搜索