zoukankan      html  css  js  c++  java
  • 用Nginx+Lua+Redis给百度鹰眼API服务搭建缓存服务中间件(记录过程)

    一、环境安装部分

    Centos7,Nginx1.14,Redis5.0,luajit-2.1,ngx_devel_kit-0.3.1rc1,lua-nginx-module-0.10.14.

    下载安装包:

    wget http://nginx.org/download/nginx-1.14.0.tar.gz
    wget https://github.com/simplresty/ngx_devel_kit/archive/v0.3.1rc1.tar.gz
    wget https://github.com/openresty/lua-nginx-module/archive/v0.10.14.tar.gz
    wget http://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz
    wget http://download.redis.io/releases/redis-5.0.4.tar.gz

    安装配置过程:

    解压ngx_devel_kit和lua-nginx-module

    tar xzvf v0.3.1rc1.tar.gz
    tar xzvf v0.10.14.tar.gz

    解压LuaJIT,进入目录编译安装

    make PREFIX=/usr/local/luajit
    make install PREFIX=/usr/local/luajit
    export LUAJIT_LIB=/usr/local/luajit/lib
    export LUAJIT_INC=/usr/local/luajit/include/luajit-2.1

    解压Nginx,给编译参数追加上面三个模块的目录再编译

    nginx -V #已安装Nginx执行该命令查看现有编译参数
    configure arguments: 
    --prefix=/usr/local/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=www --group=www --with-http_ssl_module --with-pcre --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module
    
    #执行./configure命令,在现有编译参数最后追加luajit,ngx_devel_kit和lua-nginx-module
    ./configure --prefix=/usr/local/nginx --sbin-path=/usr/sbin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --user=www --group=www --with-http_ssl_module --with-pcre --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-http_dav_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_stub_status_module --with-http_auth_request_module--with-ld-opt=-Wl,-rpath,/usr/local/luajit/lib --add-module=/data/lua/ngx_devel_kit-0.3.1rc1 --add-module=/data/lua/lua-nginx-module-0.10.14

    service nginx stop
    make #编译
    cp objs/nginx /usr/sbin/
    service nginx start
    nginx -V #检查模块是否添加上

    解压Redis,进入目录编译

    make PREFIX=/usr/local/redis
    make install PREFIX=/usr/local/redis
    cd /usr/local/redis/bin
    ./redis-server & #启动
    ./redis-cli #测试set a a; keys *; flushall


    二、Lua代码编写部分

    下载插件拷贝lua文件至目录 /usr/local/lib/lua/resty
    resty.http:https://github.com/ledgetech/lua-resty-http
    resty.redis:https://github.com/openresty/lua-resty-redis
    resty.redis_iresty:https://github.com/moonbingbing/9915c66346e8fddcefb5

    配置Nginx文件

    #http下添加lua路径
    lua_package_path "/usr/local/lib/lua/?.lua;;";

    #server下添加DNS,字符集和location
    resolver 8.8.8.8;
    charset utf-8;
    #地理解码
    location /geocoder/{
      default_type "application/json;charset=utf-8";
      content_by_lua_file "/usr/local/lib/lua/resty/geocoder.lua"
      #也可以用content_by_lua_block{直接将代码写到nginx内部}
    }
    #鹰眼服务
    location /api/ {
      default_type "application/json;charset=utf-8";
      content_by_lua_file "/usr/local/lib/lua/resty/api.lua"
    }

    编写lua代码文件

    地理解码文件/usr/local/lib/lua/resty/geocoder.lua
    数据隐私保护:客户端发送请求url可以不需要携带ak和service_id参数
    二次请求缓存:第二请求传递坐标数据时,直接从redis拿坐标对应位置

    local url = ngx.var.request_uri.."&ak=你的ak参数&service_id=你的鹰眼服务id"
    local redis = require "resty.redis_iresty"
    local red = redis:new()
    local res, err = red:get(url)
    if not res or res == ngx.null then
        local http = require "resty.http"
        local httpc = http.new()
        local res, err = httpc:request_uri("http://api.map.baidu.com"..url)
        if res.status == ngx.HTTP_OK then
            red:set(url, res.body)
            ngx.print(res.body)
            return
        else
            ngx.exit(res.status)
        end
    end
    
    ngx.print(res)

    鹰眼服务API文件/usr/local/lib/lua/resty/api.lua
    支持post请求,可编辑post参数内容,对post参数追加ak和service_id
    为防止错乱,只对包含参数end_time且值小于今天的请求结果进行缓存
    客户端可用http://yourdomain.com/api/* 代替 http://yingyan.baidu.com/api/*

    local http = require "resty.http"
    local httpc = http.new()
    
    if ngx.var.request_method == "POST" then
        ngx.req.read_body();
        local postargs = ngx.req.get_post_args()
        local postdata = "ak=你的ak参数&service_id=你的鹰眼服务id"
        for k,v in pairs(postargs) do
            postdata = postdata.."&"..k.."="..v
        end
        local res = httpc:request_uri("http://yingyan.baidu.com"..ngx.var.uri, { method = "POST", body = postdata, headers = { ["Content-Type"] = "application/x-www-form-urlencoded", ["Content-Length"] = nil } })
        if res.status == ngx.HTTP_OK then
            ngx.print(res.body)
            return
        else
            ngx.exit(res.status)
        end
    end
    
    local end_time = nil
    local args = ngx.req.get_uri_args()
    local url = ngx.var.request_uri.."&ak=你的ak参数&service_id=你的鹰眼服务id"
    for k,v in pairs(args) do
        if(k == "end_time") then
            end_time = v
            break
        end
    end
    if(end_time ~= nil) then
        local now_time = os.date("*t")
        local today_time = os.time({day=now_time.day, month=now_time.month,year=now_time.year, hour=0, minute=0, second=0})
        if(tonumber(end_time) < today_time) then
            local redis = require "resty.redis_iresty"
            local red = redis:new()
            local res = red:get(url)
            if not res or res == ngx.null then
                local res = httpc:request_uri("http://yingyan.baidu.com"..url)
                if res.status == ngx.HTTP_OK then
                    red:set(url, res.body)
                    ngx.print(res.body)
                    return
                else
                    ngx.exit(res.status)
                end
            end
    
            ngx.print(res)
            return
        end
    end
    
    local res = httpc:request_uri("http://yingyan.baidu.com"..url)
    if res.status == ngx.HTTP_OK then
        ngx.print(res.body)
    else
        ngx.exit(res.status)
    end

    以上开发调试工具:https://openresty.org/download/openresty-1.13.6.2-win64.zip,https://moonbingbing.gitbooks.io/openresty-best-practices/content/lua/build_env.html

    PS:原创文章,转载请标注来源。@轻云科技,by海飞。

  • 相关阅读:
    Codeforces 512D
    Codeforces Gym 101480C
    Codeforces 575A
    Codeforces Round #691 (Div. 2) 题解
    .net Core 中文等非英文文字html输出编码输出问题
    .net5 grpc服务在windows上的架设方法
    北大集训 2020 游记
    北大集训2020游记
    Tricks -「网络流」经典模型汇总
    Solution -「BJWC 2018」「洛谷 P4486」Kakuro
  • 原文地址:https://www.cnblogs.com/chf/p/10749427.html
Copyright © 2011-2022 走看看