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; }