windows下openresty中接纳lua做接口转载,达成数据替换跟缓存

By admin in 美高梅手机版4858 on 2019年4月10日

急需:依照客户供给,能够在ngx下
通过lua做接口三遍封装再度转载给用户或第一方

windows下openresty中使用lua做接口转载、1遍封装等,openrestylua

急需:根据客户供给,能够在ngx下
通过lua做接口3次封装再度转载给用户或第3方

情景:对再次回到值有须求的、接口屏蔽字段、或做一些工作上的验证等

一、windows直接下载openresty 解压即可,就到位了windows下利用lua的成本环境

2、配置:

a、在nginx.conf里http下配置如下代码:

include       mime.types;
default_type  application/octet-stream;
lua_package_path "/lualib/?.lua;;";  #lua 模块  
lua_package_cpath "/lualib/?.so;;";  #c模块   
include lua.conf;   #导入自定义lua配置文件
resolver 8.8.8.8;

美高梅手机版4858,b、在nginx.conf同目录创立lua.conf文件特别存放lua的路由配置

#lua.conf  
server {  
 charset utf-8; #设置编码
    listen       80;  
    server_name  _;  
 location /user {  
  default_type 'text/html';  
  content_by_lua_file lua/api/userController.lua; #相对于nginx安装目录  
 } 
}    

c、在ngx根目录下的lua文件夹里创制“api”文件夹,并且在里面添加userController.lua
处理文件类,例如代码如下:

local request_method = ngx.var.request_method
local args = nil

--1、获取参数的值 获取前端提交参数
if "GET" == request_method then
    args = ngx.req.get_uri_args()
elseif "POST" == request_method then
    ngx.req.read_body()
    args = ngx.req.get_post_args()
end

--2、组合url请求Get/Post请求 并获取参数  
local http = require "resty.http"  
local httpc = http.new()  
local url = "http://xxxxx/user/login/"..args["userid"].."/"..args["pass"]
local resStr --响应结果  
local res, err = httpc:request_uri(url, {  
    method = "GET",  
    --args = str,  
     body = "a=1&b=2",
    headers = {  
       ["Content-Type"] = "application/json",  
    }  
})  

--3、开始重新组合参数 例子 可根据返回的JSON自己处理
local cjson = require "cjson"
local sampleJson = [[{"age":"23","testArray":{"array":[8,9,11,14,25]},"Himi":"himigame.com"}]];
--解析json字符串
local data = cjson.decode(sampleJson);
--打印json字符串中的age字段
ngx.say(data["age"]);
--打印数组中的第一个值(lua默认是从0开始计数)
ngx.say(data["testArray"]["array"][1]);  


--4、打印输出新返回值
ngx.say(res.body) 

三、运营ngx服务器,访问地址,路由为user  

 

要求:依据客户须要,可以在ngx下
通过lua做接口2回封装再次转载给用户或第…

需求:根据客户须要,能够在ngx下
通过lua做接口一遍封装再次转载给用户或第1方

导读:demo都以在自己本地一个域名下完了的。但是文中分了。m.yanshinian.com,api.yanshinian.com,shopapi.yanshinian.com。别搞晕了。
文中提到到openResty、vue、laravel、lua、nginx缓存、本地dns配置的使用。都以粗略的应用。

场所:对再次回到值有须求的、接口屏蔽字段、或做一些作业上的辨证等

气象:对重返值有供给的、接口屏蔽字段、或做壹些政工上的证实等

数据替换

何以选取openResty呢?

我们曾经有大气页面使用了静态数据。开发动态接口,要合营从前的多寡(比如说:从前目录在a目录上边,笔者经过更换链接,用location相称,照旧去拿a目录下边的静态数据处理),并且上线迫切。

openResty的便宜就毫无说了。上边包车型地铁篇章是自身依据实际工作,编了两个demo(原理一样)。

1、windows直接下载openresty 解压即可,就做到了windows下选择lua的开发环境

一、windows直接下载openresty 解压即可,就成功了windows下选拔lua的支出条件

讲述下工作场景

作为2个营业后台跟超级市场后台是分手的两套系统。有一天产品经营说,我们要收获商城的多少变动商品静态页显示。那么在营业后台必要制造一张商品表用来保存从超级市场接口的拿到的货物数量。于是小明消除了,后台湾学生成json文件作为数据源。前台通过VUE去渲染。

有一天产品首席营业官,过来说,原来的纯静态不知足了。比如本人要出示仓库储存,要做成动态的。于是,小明用openResty做动态的来得。

2、配置:

2、配置:

落实思路

  1. 获取json文件

windows下openresty中接纳lua做接口转载,达成数据替换跟缓存。二.得到独具商品的id

叁.用id数组请求接口,获得数码

四.做多少替换并出口

相关demo编写

a、在nginx.conf里http下配置如下代码:

a、在nginx.conf里http下配置如下代码:

应用lua要留意的标题

一.lua文本路径

先后中引进了第一方的模块。记得设置文件查找路径。比如,笔者利用了第二方的http请求库——lua-resty-http。假设未有安装路径。那么会报如下错误,它会从私下认可的门路去找。

no file '/usr/local/openresty/site/lualib/resty/http.lua'

no file '/usr/local/openresty/site/lualib/resty/http/init.lua'

no file '/usr/local/openresty/lualib/resty/http.lua'

no file '/usr/local/openresty/lualib/resty/http/init.lua'

no file '/usr/local/openresty/site/lualib/resty/http.so'

no file '/usr/local/openresty/lualib/resty/http.so'

no file '/usr/local/openresty/site/lualib/resty.so'

no file '/usr/local/openresty/lualib/resty.so'

no file '/usr/local/openresty/site/lualib/resty/http.lua'

no file '/usr/local/openresty/site/lualib/resty/http/init.lua'

no file '/usr/local/openresty/lualib/resty/http.lua'

能从漏洞百出中看出来会去安装后openresty目录中找。/usr/local/openresty/site/lualib/
和’/usr/local/openresty/lualib/

之所以要去nginx.conf配置文件中,在http模块里面去设置如下

lua_package_path "/usr/local/openresty/lualib/?.lua;/usr/local/openresty/lualib/lua-resty-http/lib/?.lua    ;;"; #文件查找路径

lua_package_cpath "/usr/local/openresty/lualib/?.so;;"; # 模块路径

看了地点的安排了吗。大家把lua-resty-http第二方库放到了。openresty/lualib上面了。当然你能够停放项目底下。配置好对应路径也是能够的。

2.location 中 content_by_lua_file (放在它上边)以前须求设置
dns的分析,假诺做了内网的界定,那么找个内网的DNS地址(安装配备Dnsmasq
)即可,设置如下

resolver 114.114.114.114  8.8.8.8; #针对外网
include       mime.types;
default_type  application/octet-stream;
lua_package_path "/lualib/?.lua;;";  #lua 模块  
lua_package_cpath "/lualib/?.so;;";  #c模块   
include lua.conf;   #导入自定义lua配置文件
resolver 8.8.8.8;
include       mime.types;
default_type  application/octet-stream;
lua_package_path "/lualib/?.lua;;";  #lua 模块  
lua_package_cpath "/lualib/?.so;;";  #c模块   
include lua.conf;   #导入自定义lua配置文件
resolver 8.8.8.8;

始于开发吧

提到到的学问:laravel框架、vue、luajit、openresty、一张简略的商品表

1.预备数据

商品表如下

CREATE TABLE  `yan_product` (
    `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键id',
    `product_id` BIGINT(20) NOT NULL DEFAULT '0' COMMENT '商品ID',
    `title` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品标题',
    `img` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '商品图片',
    `price` FLOAT NOT NULL DEFAULT '0' COMMENT '商品价格',
    `sales_num` INT(11) NOT NULL DEFAULT '0' COMMENT '销量',
    `stock_num` INT(11) NOT NULL DEFAULT '0' COMMENT '库存数量',
    PRIMARY KEY (`id`),
    INDEX `idx_product_id` (`product_id`)
)
COMMENT='商品表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=5
;

任由在Taobao里面随便找了个商品,借用下简单的数码。(假装那条数据是从事商业城api调用过来的)

INSERT INTO `yan_product` (`product_id`, `title`, `img`, `price`, `sales_num`, `stock_num`) VALUES (542456857815, '甜而不腻回味无穷', 'gju1.alicdn.com/tps/i4/1130806076898038137/TB2nkXyzItnpuFjSZFvXXbcTpXa_!!6000000001308-0-jupush.jpg_360x360Q50.jpg', 28.8, 120, 122);

2.准备php代码

laravel框架创立三个控制器(比如叫做ProductController),写一个生成json的先后,如下:

class ProductController extends Controller
{
    public function buildjson()
    {
        $productList = DB::select('select * from yan_product');
        $json = json_encode([
            'productList' => $productList,
        ]);
        $dir = public_path() . '/product' ;
        if (!file_exists($dir)) {
            mkdir($dir, 0777);
        }
        $path = $dir . '/product.json';
        File::put($path, 'callBack(' . $json . ')');
    }
}

地点代码便是,把json保存到了,public文件夹下边,具体路径为
public/product/product.json (product文件尤其存放商品的json)。前边拼接
callBack 是jsonp跨域请求格局。若是我们接口域名是api.yanshinian.com
前台域名是m.yanshinian.com。那么m.yanshinian.com 请求api 网址(链接为
api.yanshinian.com),会涉及到跨域的标题。

布局路由

Route::Any('product/buildjson', ['as' => 'product.buildjson', 'uses' => 'App\Modules\Product\Controllers\ProductController@buildjson']);

下一场实施 buildjson,在public/product 目录下生成3个product.json 文件

3.预备前台的页面。使用vue代码

引进相应的 js文件

https://unpkg.com/vue@2.1.10/dist/vue.js

https://cdn.jsdelivr.net/npm/vue-resource@1.3.4

重大代码如下:

非常粗大劣的html

<div id="app">

    <ul>
        <li v-for="product in productList">
            <p>productId: {{product.product_id}}</p>
            <p>title: {{product.title}}</p>
            <p>img: {{product.img}}</p>
        </li>
    </ul>
</div>

非常粗大糙的vue

var app = new Vue({
        el: '#app',
        mounted: function() {
            alert('加载中....');
            this.$http.jsonp('http://api.yanshinian.com/product/product.json',{
                jsonp:'callback',
                jsonpCallback: 'callback'
            }).then(function(res) {
                console.log(this.productList)
                  this.productList = JSON.parse(res.bodyText).productList
                  console.log(this.productList)

            }) 
        },
        data: {
            productList: ''
        },
        methods: {
            getProductList: function() {
                alert(23);
            }
        }
 });

jsonp请求到数码,并且渲染出来了。糙图如下:

美高梅手机版4858 1

商品列表.png

但是,它是纯静态的。接下来大家早先用lua替换静态页面。变成动态的多少。

四.假装开发四个杂货店的接口(下一步会用lua脚本调用)。

public function getProductList(Request $request)
{
    $ids = trim($request->input('ids'),',');
    $productList = DB::select('select product_id, stock_num from yan_product where product_id in (' . $ids . ')');
    $data = [];
    foreach ($productList as $v) {
        $data[$v->product_id]= [
            'stock_num'=>$v->stock_num
        ];
    }
    return $data;
}

安顿路由

Route::Any('product/productlist', ['as' => 'product.productlist', 'uses' => 'App\Modules\Product\Controllers\ProductController@getProductList']);

post请求,参数ids = ‘542456857815,542456857817’(ids 是product_id)

{"542456857815":{"stock_num":234},"542456857817":{"stock_num":122}}

五.布局location,用lua去过滤一回

location /product/filter/product.json  { 
    resolver 127.0.0.1; 
    content_by_lua_file /home/nobody/lua/product.lua; #路径自己随意
}

那边有个注意事项就是resolver,须要配置当地的dns解析。安装Dnsmasq并配置(参考链接:《Dnsmasq安装与陈设》http://www.360doc.com/content/14/0913/13/8314158\_409140713.shtml)
,在小编布置的历程中,没布置对外网的分析,导致了git代码无法交到(报错如下ssh:
Could not resolve hostname git.xxxx.org: Name or service not
known,必要如此弄下,echo ‘nameserver 8.八.捌.八’ >
/etc/resolv.dnsmasq.conf)

  1. lua代码 如下

local json = require "cjson"
-- 获取 body内容
-- local bodyJson = ngx.arg[1] -- 这条语句是我觉得body_filter 阶段可以过滤,但事实上,不能发送http请求。所以还是选择在content_by_lua_file 阶段处理

local productListRes = ngx.location.capture("/product/product.json") -- 子查询
local bodyJson = productListRes.body
-- cjson解析
local data = json.decode(string.sub(bodyJson,10,-2))


-- 获取ids
local ids = "";
-- ngx.log(ngx.ERR, json.encode(data));
for k,v in pairs(data.productList) do
    ids = ids..v.product_id..','
end
-- 发送http请求,拿到数据
local http = require "resty.http"

    local httpc = http.new()
function http_request(method, url, param_str)
    local res, err = httpc:request_uri(url, {
        method = method,
        body = param_str,
        headers = {
            ["Content-Type"] = "application/x-www-form-urlencoded",
        },
        ssl_verify = false,
    })

    if not res then
        ngx.log(ngx.ERR, "failed to request: "..err)
        return false;
    end
    return res;
end

local url = "http://shopapi.yanshinian.com/product/productlist"

local res = http_request("POST", url, "ids="..ids)

local productList = json.decode(res.body)
ngx.log(ngx.ERR, json.encode(productList));
-- 解析数据,然后遍历 body,替换库存
for k,v in pairs(data.productList) do
     v.stock_num = productList[""..v.product_id]['stock_num']
end
-- 输出结果

body = "callback(" .. json.encode(data) .. ")"

ngx.say(body)

7.方始验证那么些小作用

大家把js中的链接更换来http://api.yanshinian.com/product/filter/product.json

在追加一个出示的仓库储存字段。

<p>img: {{product.img}}</p>

变动数据库。(由于大家那边是demo,所以大家只要,运维后台的数据库,跟超级市场是同八个。真实环境,当然是数据库跟代码都分手的)。

验证是ok的。

b、在nginx.conf同目录创制lua.conf文件尤其存放lua的路由配置

b、在nginx.conf同目录成立lua.conf文件特别存放lua的路由配置

末段还想说的

lua代码中有壹行注意下local bodyJson = ngx.arg[1]。body_filter阶段是足以对响应数据实行过滤,比如截断、替换。ngx.arg[1]是用来得到响应数据(但也大概取得的不全,那是另2个难题了)。但是这几个等级有毛病,当笔者得到ids参数,实例化http,并发送请求。报错了。报错如下。

2017/08/05 22:08:56 [error] 31159#0: *581 failed to run body_filter_by_lua*: ...local/openresty/lualib/lua-resty-http/lib/resty/http.lua:121: API disabled in the context of body_filter_by_lua*
3797 stack traceback:
3798     [C]: in function 'ngx_socket_tcp'
3799     ...local/openresty/lualib/lua-resty-http/lib/resty/http.lua:121: in function 'new'
3800     /home/nobody/lua/product.lua:20: in function 'http_request'
3801     /home/nobody/lua/product.lua:39: in function </home/nobody/lua/product.lua:1> while sending response to client, client: 192.168.95.1, server: 
......................

也正是说在这么些阶段不可能发送接口请求。此外,执行ngx.say
也是不容许的。所以改用content_by_lua 那几个阶段
再长远的细节,只怕供给查下。

#lua.conf  
server {  
 charset utf-8; #设置编码
    listen       80;  
    server_name  _;  
 location /user {  
  default_type 'text/html';  
  content_by_lua_file lua/api/userController.lua; #相对于nginx安装目录  
 } 
}    
#lua.conf  
server {  
    charset utf-8; #设置编码
    listen       80;  
    server_name  _;  
    location /user {  
        default_type 'text/html';  
        content_by_lua_file lua/api/userController.lua; #相对于nginx安装目录  
    } 
}    

缓存

缓存是行使 了nginx的表征

修改配置文件即可。

缘何用缓存呢?在此以前小说说了,调用商城接口,仓库储存平时是实时的,量大的图景简单让数据库垮掉。小明给产品汇报之后。产品说好能够不那么实时。那样,加上缓存数据库压力就小了。

c、在ngx根目录下的lua文件夹里创造“api”文件夹,并且在个中添加userController.lua
处理文件类,例如代码如下:

c、在ngx根目录下的lua文件夹里创立“api”文件夹,并且在内部添加userController.lua
处理文件类,例如代码如下:

修改 配置文件

nginx.conf 设置 缓存路径

proxy_cache_path /home/nobody/cache levels=1:2 keys_zone=my-cache:8m ina    ctive=1h max_size=10m;proxy_cache_path /home/nobody/cache levels=1:2 keys_zone=my-cache:8m ina    ctive=1h max_size=10m;

api.yanshinian.com.conf,下边扩张如下代码。

 location ^~/product/filter/cache/product.json {
    proxy_pass http://127.0.0.1:8086/product/filter/product.json;
    proxy_cache my-cache;
    proxy_cache_lock on;
    proxy_cache_valid 200 304 1m;#设置一分钟的缓存
    proxy_cache_key $uri$is_args$args;
    add_header Nginx-Cache "$upstream_cache_status";
}

咱们把js请求的链接改成
http://api.yanshinian.com//product/filter/cache/product.json。实行呼吁。抓包看下响应头Nginx-Cache。发现Nginx-Cache:HIT。表明缓存成功。

local request_method = ngx.var.request_method
local args = nil

--1、获取参数的值 获取前端提交参数
if "GET" == request_method then
    args = ngx.req.get_uri_args()
elseif "POST" == request_method then
    ngx.req.read_body()
    args = ngx.req.get_post_args()
end

--2、组合url请求Get/Post请求 并获取参数  
local http = require "resty.http"  
local httpc = http.new()  
local url = "http://xxxxx/user/login/"..args["userid"].."/"..args["pass"]
local resStr --响应结果  
local res, err = httpc:request_uri(url, {  
    method = "GET",  
    --args = str,  
     body = "a=1&b=2",
    headers = {  
       ["Content-Type"] = "application/json",  
    }  
})  

--3、开始重新组合参数 例子 可根据返回的JSON自己处理
local cjson = require "cjson"
local sampleJson = [[{"age":"23","testArray":{"array":[8,9,11,14,25]},"Himi":"himigame.com"}]];
--解析json字符串
local data = cjson.decode(sampleJson);
--打印json字符串中的age字段
ngx.say(data["age"]);
--打印数组中的第一个值(lua默认是从0开始计数)
ngx.say(data["testArray"]["array"][1]);  


--4、打印输出新返回值
ngx.say(res.body) 
local request_method = ngx.var.request_method
local args = nil

--1、获取参数的值 获取前端提交参数
if "GET" == request_method then
    args = ngx.req.get_uri_args()
elseif "POST" == request_method then
    ngx.req.read_body()
    args = ngx.req.get_post_args()
end

--2、组合url请求Get/Post请求 并获取参数  
local http = require "resty.http"  
local httpc = http.new()  
local url = "http://xxxxx/user/login/"..args["userid"].."/"..args["pass"]
local resStr --响应结果  
local res, err = httpc:request_uri(url, {  
    method = "GET",  
    --args = str,  
     body = "a=1&b=2",
    headers = {  
       ["Content-Type"] = "application/json",  
    }  
})  

--3、开始重新组合参数 例子 可根据返回的JSON自己处理
local cjson = require "cjson"
local sampleJson = [[{"age":"23","testArray":{"array":[8,9,11,14,25]},"Himi":"himigame.com"}]];
--解析json字符串
local data = cjson.decode(sampleJson);
--打印json字符串中的age字段
ngx.say(data["age"]);
--打印数组中的第一个值(lua默认是从0开始计数)
ngx.say(data["testArray"]["array"][1]);  


--4、打印输出新返回值
ngx.say(res.body) 

附赠三个函数

在实质上支出中,商城的接口,需求批量调用,做了限定,然而lua
未有array_chunk(不像php)的函数,本人包裹了三个

function table_chunk(stable, count)
        local newTable = {};
        local tlen = #stable;
        local tempTable = {};
        for k,v in pairs(stable) do
                table.insert(tempTable, v);
                local tempLen = #tempTable;
                if(tempLen % count == 0)  then
                        table.insert(newTable, tempTable);
                        tempTable = {};
                end
        end
        table.insert(newTable, tempTable);
        return newTable;
end

ps.openResty是身边小伙提的方案,笔者呢,本身编个代码无非就是回想下所学的。哈哈。

参照链接:


nginx的proxy_cache缓存相关配置》http://hnr520.blog.51cto.com/4484939/1686896

感兴趣的话能够关切本身的大众号——言10年的平时

美高梅手机版4858 2

qrcode_for_gh_20daf6d0ff9e_430 (2).jpg

3、运营ngx服务器,访问地址,路由为user  

3、运营ngx服务器,访问地址,路由为user  

 

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有