主要邏輯
上傳
前端請求 nginx 服務, nginx 調用 upload 腳本,腳本通過查找配置,找到對應的邏輯存儲路徑和物理存儲機器的 agent 的 ip 和端口,通過 tcp 發包到對應 agent ,部署在對應機器的 agent 接受數據,并寫到本地文件。
下載
http下載請求 nginx , nginx 調用 download 腳本,腳本解析鏈接參數,根據參數找到對應的 agent 地址,請求返回文件二進制內容,腳本接受到 agent 返回的數據,返回給請求端。
配置nginx+lua
接下來主要講一下 nginx 安裝配置(這里包括lua的二進制流處理 lpack, md5計算, mysql 操作, json 操作)
1、安裝 nginx
下載
解壓tar -xvf nginx-1.10.3.tar.gz
2、安裝 luajit(輕量級 lua)
修改 makefile 里面的安裝路徑export prefix= /usr/local/luajit
然后安裝make &make install
3、安裝nginx_lua_module
下載
解壓
4、 安裝ngx_devel_kit (ndk提供函數和宏處理一些基本任務,減輕第三方模塊開發的代碼量)
下載
5、 安裝編譯,導入
export?luajit_lib=/usr/local/luajit/lib? export?luajit_inc=/usr/local/luajit/include/luajit-2.0? ./configure?--prefix=/usr/local/nginx?--with-http_stub_status_module?--with-http_ssl_module?--add-module=/home/oicq/jeffzhuang/ngx_devel_kit-0.3.0?--add-module=/home/oicq/jeffzhuang/lua-nginx-module-0.10. make?-j2? make?install
啟動/usr/local/nginx/sbin/nginx 重啟命令` usr/local/nginx/sbin/nginx -s reload v
如果報錯找不到luajit庫ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
測試nginx直接打開瀏覽器就可以了http:10.x.x.x:8080就可以看到歡迎界面了
6 、配置conf/nginx.conf運行 lua 腳本
增加lua庫的查找路徑lua_package_path,lua_package_cpath
7、增加mysql.lua下載 ?拷貝到lua_package_path 目錄下就可以了
8、增加 csjon
修改 makefile 里面的 prefix=/usr/local/luajit就是luajit 的安裝路徑,make后將生成的 cjson.so拷貝到
lua_package_cpath目錄下
9、安裝lpack 可以用現成的 lpack.lua 拷貝到 lua_package_path 或者用 https://github.com/luadist/lpack 編譯生成 lpack.so拷貝到 lua_package_cpath 64位需要增加編譯命令 -fpic
10、upload.lua下載
11、md5下載
主要代碼
1、前端上傳頁面代碼
nbsp;html> ? ??<title>file?upload?example</title> ? ? ??
?
2、upload上傳代碼,該模塊在解析文件上傳請求的過程中,主要采用了簡單的類似有限狀態機的算法來實現的,在不同的狀態由相應的 handler 進行處理。
--文件下載服務寫到?saverootpath?.."/"?..?filename?下面? function?download() ?local?chunk_size?=?4096 ?local?form,err=upload:new(chunk_size) ?if?not?form?then ??ngx.log(ngx.err,?"failed?to?new?upload:?",?err) ??ngx.exit(ngx.http_internal_server_error) ?end? ?form:set_timeout(100000) ?while?true?do ?local?typ,res,err=form:read() ?if?not?typ?then ??errormsg="failed?to?read?:"..err ??return?1 ?end ?if?typ?=="header"?then ??local?key=res[1] ??local?value=res[2] ??if?key?=="content-disposition"?then ??local?kvlist=string.split(value,';') ???for?_,?kv?in?ipairs(kvlist)?do ???local?seg?=?string.trim(kv) ???if?seg:find("filename")?then ???local?kvfile?=?string.split(seg,?"=") ???filename?=?string.sub(kvfile[2],?2,?-2) ???if?filename?then ????--獲取文件后綴名字 ????fileextension=getextension(filename) ????local?linuxtime=tostring(os.time()) ????filepath=saverootpath?.."/"?..linuxtime..filename ????filetosave,errmsg?=?io.open(filepath,?"w+") ????--存儲的文件路徑??? ????--ngx.say("failed?to?open?file?",?filepath) ????if?not?filetosave?then ????--ngx.say("failed?to?open?file?",?filepath?..?errmsg) ????errormsg="打開文件失敗"..filepath?..?errmsg ????return?1 ????end ???else ????errormsg="請求參數找不到文件名字" ????return?1 ???end ???--跳出循環 ???break? ???end ???end ??end ?elseif?typ?=="body"?then ??if?filetosave?then ??filetosave:write(res) ??filemd5:update(res) ??end ?elseif?typ?=="part_end"?then ??if?filetosave?then ??local?md5_sum=filemd5:final() ??--ngx.say("md5:?",?str.to_hex(md5_sum)) ??filemd532=str.to_hex(md5_sum) ??filetosave:close() ??filetosave?=?nil ??end?? ?elseif?typ?=="eof"?then ??break ?else ??ngx.log(ngx.info,?"do?other?things") ?end ?end ?return?0 end
3、tcp接收二進制數據
--?讀取byte function?readint8(tcp) ?local?next,?val?=?string.unpack(tcp:receive(1),?"b") ?return?tonumber(val); end --?讀取int16 function?readint16(tcp) ?local?next,?val?=?string.unpack(tcp:receive(2),?"h"); ?return?tonumber(val); end --?讀取int32 function?readint32(tcp) ?local?next,?val?=?string.unpack(tcp:receive(4),?">i"); ?return?tonumber(val); end --?讀取字符串 function?readstring(tcp,len) ?return?tostring(tcp:receive(len)); end
4、tcp寫二進制數據,這里和 agent 的通信協議是:開始標志位+包長度+json 字符串+結束標志位,所以對應 pack 用的參數就是 biab ,> 就是轉化為大端
jsondata["filename"]=filemd532?..?"."?..?fileextension jsondata["cmd"]="write" jsondata["filesize"]=tostring(filelen) jsondata["path"]=system.."/"..storagedate local?jsonstr=cjson.encode(jsondata) local?uilen=string.len(jsonstr) senddata=bpack(">b1iab",startindex,uilen,jsonstr,endindex) socket:send(senddata)
5、下載錯誤的時候,使用了 redirect 直接跳轉到錯誤頁面,方便輸出錯誤信息,其實這里還可以做用戶 token 校驗
local?errorurl="/downloaderror.html" errormsg="url?參數解析有問題?"..index return?ngx.redirect(errorurl.."?msg="..errormsg,```?ngx.http_moved_temporarily)