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海飞。

  • 相关阅读:
    ACM ICPC 2008–2009 NEERC MSC A, B, C, G, L
    POJ 1088 滑雪 DP
    UVA 11584 最短回文串划分 DP
    POJ 2531 Network Saboteur DFS+剪枝
    UVa 10739 String to Palindrome 字符串dp
    UVa 11151 Longest Palindrome 字符串dp
    UVa 10154 Weights and Measures dp 降维
    UVa 10271 Chopsticks dp
    UVa 10617 Again Palindrome 字符串dp
    UVa 10651 Pebble Solitaire 状态压缩 dp
  • 原文地址:https://www.cnblogs.com/chf/p/10749427.html
Copyright © 2011-2022 走看看