最新消息:

Lua 版写了个简化的 MogileFS 的 Nginx 模块配合多数据中心的地域感知功能

lua admin 3088浏览 0评论

MogileFS 可以做多数据库中心存储, 这是象我这种方案中非常方便的. 我使用 MogileFS 在电信和联通分别做了一个源站. 我然后请求到联通的直接从联通数据中心的 MogileFS 中取文件, 电信从电信取文件.  ( 怎么样保证存储文件时是二个节点, 请参照 “为 MogileFS 配置使用多个网络段/多数据中心” )

默认其实使用 Multiple Networks 是可以保证不同的数据库中心各自有自己的一份文件, 但使用 MogileFS 吐出来的时候, 发现还是有可能命中其它的节点来取文件. 不单有这个问题. 前端使用 Nginx 做为前端加 MogileFS 模块的时候. 因为多数据库中心, 都是使用的公网来连接,所以吐出 500M 的流量, 就要从其它的机器取 500M 的公网流量, 为了减少这个,我需要给  Nginx 返回的取后端 MogileFS 数据的路径修改成内网.

为了实现以上需求, 花了点时间研究 Lua 使用这个来实现比较简单高效. 代码如下

local sock = ngx.socket.tcp()
local server_pool = { ["192.168.1.xxx"] = "7001",   ["192.168.1.xxx"] = "7001" }

local ok, err = nil, nil;
for server, port in pairs(server_pool) do
    ok, err = sock:connect(server, port)
    if ok then
        break
    end
end

if not ok then
    ngx.log(ngx.ERR, "failed to connect to server: ".. err)
    return
end

sock:settimeout(5000)

local get_path = "get_paths key=" .. ngx.var.key .. "&domain=" .. ngx.var.domain .."&noverify=1rn"
local bytes, err = sock:send(get_path)
local reader = sock:receiveuntil("rn")
local data, err, partial = reader()
if not data then
    ngx.log(ngx.ERR, "failed to read the data stream: ".. err)
    return
end
--sock:setkeepalive()
sock:close()
--ngx.log(ngx.ERR, ngx.var.http_host)


function Split(szFullString, szSeparator)
    local nFindStartIndex = 1
    local nSplitIndex = 1
    local nSplitArray = {}
    while true do
       local nFindLastIndex = string.find(szFullString, szSeparator, nFindStartIndex)
       if not nFindLastIndex then
        nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, string.len(szFullString))
        break
       end
       nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, nFindLastIndex - 1)
       nFindStartIndex = nFindLastIndex + string.len(szSeparator)
       nSplitIndex = nSplitIndex + 1
    end
    return nSplitArray
end

function parseUrl(url)
    local t1 = nil
    t1 = Split(url, " ")
    t1 = Split(t1[2],'&')

    local res = {}
    for k,v in pairs(t1) do
        t1 = Split(v,'=')

        if not t1[2] or not t1[1] then
            return
        end

        local newstr, n, err = ngx.re.sub(t1[2], "http://可用本地节点 IP 前三段", "http://192.168.1")
        if n == 1 then
            res["localpath"]  = newstr
        elseif t1[1] ~= "paths" then
            res["remotepath"] = t1[2]
        end
    end
    return res
end

local res = parseUrl(data)
if not res then
    --ngx.log(ngx.ERR, "not find:"..data)
    ngx.exit(ngx.HTTP_NOT_FOUND)
    return
end

if res["localpath"] then
    ngx.var.mogilefs_path = res["localpath"]
else
    ngx.var.mogilefs_path = res["remotepath"]
    ngx.log(ngx.ERR, "file key not find local" .. ngx.var.key)
end

因为没写过 lua , 其中的 Split 函数抄别人的. 连接本地的 tracker 直接使用那个能连接上就连接的顺序连接….判断是否本地直接使用 ngx.re.sub 来做查找, 顺便替换成本地地址, 这样就实现了我要的功能.

location ~ ([^/]+).www$ {
    expires 365d;
    set $domain $host;
    set $key $1;
    set $mogilefs_path '';
    rewrite_by_lua_file "/etc/nginx/conf.d/ngx_lua/mogilefs.lua";
    proxy_hide_header Content-Type;
    proxy_buffering off;
    proxy_pass $mogilefs_path;
}

转载请注明:爱开源 » Lua 版写了个简化的 MogileFS 的 Nginx 模块配合多数据中心的地域感知功能

您必须 登录 才能发表评论!