Nginx+lua+redis 實現(xiàn)微服務(wù)動態(tài)路由(openresty+redis)及redis帶密碼配置

一.下載軟件包

1..echo-nginx-module 下載,是一個 Nginx 模塊,提供直接在 Nginx 配置使用包括 "echo", "sleep", "time" 等指令。

wget?https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz


?2.lua-nginx-module 下載??稍?Nginx 中嵌入 Lua 語言,讓 Nginx 可以支持 Lua 強大的語法。

wget?https://github.com/openresty/lua-nginx-module/archive/v0.10.12rc2.tar.gz


3.redis2-nginx-module 下載。是一個支持 Redis 2.0 協(xié)議的 Nginx upstream 模塊,它可以讓 Nginx 以非阻塞方式直接防問遠方的 Redis 服務(wù),同時支持 TCP 協(xié)議和 Unix Domain Socket 模式,并且可以啟用強大的 Redis 連接池功能。

wget?https://github.com/openresty/redis2-nginx-module/archive/v0.15rc1.tar.gz


4.set-misc-nginx-module 下載。是標準的HttpRewriteModule指令的擴展,提供更多的功能,如URI轉(zhuǎn)義與非轉(zhuǎn)義、JSON引述,Hexadecimal、MD5、SHA1、Base32、Base64編碼與解碼、隨機數(shù)等等

wget?https://github.com/openresty/set-misc-nginx-module/archive/v0.32rc1.tar.gz

?5.nginx 下載

wget?http://nginx.org/download/nginx-1.14.0.tar.gz

二、編譯安裝

1.確認下目錄位置? ?

[root@test01?~]#?ls

echo-nginx-module-0.61???????nginx-1.14.0????????????redis2-nginx-module-0.15rc1

lua-nginx-module-0.10.12rc2????set-misc-nginx-module-0.32rc1

2.進入nginx-1.12.2 ,編譯安裝

安裝依賴

yum?install?pcre-devel?openssl-devel?gcc?curl?lua?lua-devel

yum 安裝luajit-devel.x86_64

????./configure?--prefix=/usr/local/nginx?--user=www?--group=www?--with-http_gzip_static_module?--with-http_stub_status_module?--with-http_ssl_module?--with-file-aio?--with-http_realip_module?--add-module=../echo-nginx-module-0.61?--add-module=../redis2-nginx-module-0.15rc1?--add-module=../lua-nginx-module-0.10.12rc2?--add-module=../set-misc-nginx-module-0.32rc1

????make

注意:

若只是升級操作,則不需要make install ,若第一次安裝,則需要make install

? ? a.升級操作


????cd?/usr/local/nginx/sbin/

????mv?nginx?nginx.bak

????cd?~/objs/

????cp?-rp??nginx?/usr/local/nginx/sbin/

????kill?-USR2?$(cat?/var/run/nginx.pid)

????b.安裝操作

?????make?install

調(diào)整nginx配置文件,編寫啟動腳本

3.redis插件安裝

1)lua-resty-redis是openresty(1.9.15.1)的一個組件,簡單來說,它提供一個lua語言版的redis API,使用socket(lua sock)和redis通信。(不需要)

mdkir?/usr/local/nginx/lua??

cd?/usr/local/nginx/lua

wget?https://github.com/openresty/lua-resty-redis/archive/v0.26.tar.gz

tar?-xf??v0.26.tar.gz

2)安裝lua-redis-parser

wget??https://github.com/openresty/lua-redis-parser/archive/v0.13.tar.gz

tar?-xvf?v0.13.tar.gz

gmake?CC=gcc

gmake?install?CC=gcc

cd?/usr/local/lib/lua/5.1/redis/

cd?../..

cp?-rp?lua/?/usr/lib64/

4.?redis 安裝 (略過)

三.lua 腳本測試


首先,要解析并拆分URL字符串,各種百度和Google,需要寫一段Lua代碼,實現(xiàn)字符串按"/"拆分

function?split(str,?pat)

local?t?=?{}

local?fpat?=?"(.-)"?..?pat

local?last_end?=?1

local?s,?e,?cap?=str:find(fpat,1)

while?s?do

if?s?~=?1?or?cap?~=?""?then

table.insert(t,cap)

end

last_end?=?e+1

s,?e,?cap?=?str:find(fpat,?last_end)

end

if?last_end?<=?#str?then

cap?=?str:sub(last_end)

table.insert(t,?cap)

end

return?t

end

function?split_path(str)

return?split(str,'[\\/]+')

end

其實就是定義了一個split_path函數(shù)。

然后我們將上面的Split.lua文件,配置到Nginx的配置文件中

/usr/local/nginx/conf/nginx.conf

?init_worker_by_lua_file "/usr/local/nginx/lua/split.lua"

編輯 vhost.conf 配置文件

server?{

????????listen?80;

????????server_name?test.xxxx.com;

????????index?index.html?index.htm?index.php;

????????location?=?/redis?{

????????????internal;

????????????set_unescape_uri?$key?$arg_key;

????????????redis2_query?get?$key;

????????????#redis2_query?auth?"mypaas";

????????????redis2_pass?172.16.197.72:6379;

????????}

????????location?/?{

????????????set?$target?'';

????????????access_by_lua?'

????????local?parameters?=?split_path(ngx.var.uri)

????????local?action?=?parameters[1]

????????if(#parameters?==?0)?then

???????????????????ngx.exit(ngx.HTTP_FORBIDDEN)

????????end

????????local?key?=?action

????????local?res?=?ngx.location.capture(

????????????????????"/redis",?{?args?=?{?key?=?key?}?}

????????)

????????if?res.status?~=?200?then

????????????????????ngx.log(ngx.ERR,?"redis?server?returned?bad?status:?",

????????????????????????res.status)

????????????????????ngx.exit(res.status)

????????end

????????if?not?res.body?then

????????????????????ngx.log(ngx.ERR,?"redis?returned?empty?body")

????????????????????ngx.exit(500)

????????end

????????local?parser?=?require?"redis.parser"

????????local?server,?typ?=?parser.parse_reply(res.body)

????????if?typ?~=?parser.BULK_REPLY?or?not?server?then

????????????????????ngx.log(ngx.ERR,?"bad?redis?response:?",?res.body)

????????????????????ngx.exit(500)

????????end

????????if?server?==?""?then

????????????????????server?=?"test.paas.qjclouds.com"

????????end

????????ngx.var.target?=?server

???????';

???????resolver?8.8.8.8;

???????proxy_pass?http://$target;

??????proxy_set_header?Host?test.xxx.com;

?????}

access_log?/tmp/access.log;

????}

需求變更:

1. 訪問域名的? 重定向到某個頁面

2.訪問/xxx? ?重定向到 某個固定頁面

3.訪問/xxx/xxx/xxxx的重定向到 某個server并 把請求轉(zhuǎn)發(fā)過去

4.訪問到后端主機的請求,需要負載(負載地址 在redis value里面,并且以','分割)

更改?/usr/local/nginx/lua/split.lua文件為如下:

function?split(str,?pat)

local?t?=?{}

local?fpat?=?"(.-)"?..?pat

local?last_end?=?1

local?s,e,cap?=?str:find(fpat,1)

while?s?do

???if?s?~=?1?or?cap?~=?""?then

??????table.insert(t,cap)

???end

???last_end?=?e+1

???s,e,cap?=?str:find(fpat,?last_end)

end

if?last_end?<=?#str?then

???cap?=?str:sub(last_end)

???table.insert(t,?cap)

end

return?t

end

function?split_path(str)

return?split(str,'[\\/]+')

end

function?split_arr(inputstr,?sep)

????????if?sep?==?nil?then

????????????????sep?=?"%s"

????????end

????????local?t={}?;?i=1

????????for?str?in?string.gmatch(inputstr,?"([^"..sep.."]+)")?do

????????????????t[i]?=?str

????????????????i?=?i?+?1

????????end

????????return?t

end

更改Nginx文件為:

????server?{

????????listen?80;

????????server_name?uatx.paas.xxx.com;

????????index?index.html?index.htm?index.php;

????????location?=?/redis?{

????????????internal;

????????????set_unescape_uri?$key?$arg_key;

????????????redis2_query?get?$key;

????????????redis2_pass?172.19.151.176:6379;

????????}

????????location?/?{

????????????set?$target?'';

????????????access_by_lua?'

????????local?parameters?=?split_path(ngx.var.uri)

????????local?action?=?parameters[1]

????????local?action1?=?parameters[2]

????????local?action2?=?ngx.var.host

????????if?ngx.var.uri?==?"/"?then

???????????????res?=?ngx.location.capture(

????????????????"/redis",?{?args?=?{?key?=?"0_"..action2?}?}

????????????????)

??????????????local?parser?=?require?"redis.parser"

??????????????local?dapeng,?typ?=?parser.parse_reply(res.body)

???????????return?ngx.redirect(dapeng)

????????end

????????if(#parameters?==?0)?then

?????????????????ngx_log(ngx.ERR,?"----------------------->")

?????????????????ngx.exit(ngx.ERROR)

???????????????????ngx.exit(ngx.HTTP_FORBIDDEN)

????????end

????????if?action1?==?nil?then

?res?=?ngx.location.capture(

????????????????????"/redis",?{?args?=?{?key?=?"0_/paas/res"?}?}

????????????????)

else

?????????res?=?ngx.location.capture(

????????????????????"/redis",?{?args?=?{?key?=?"0_/"..action.."/"..action1?}?}

????????)

????????end

????????if?res.status?~=?200?then

????????????????????ngx.exit(res.status)

????????end

????????if?not?res.body?then

???????????????res?=?ngx.location.capture(

????????????????"/redis",?{?args?=?{?key?=?"0_paas/res"?}?}

????????????????)

????????end

????????local?parser?=?require?"redis.parser"

????????local?server,?typ?=?parser.parse_reply(res.body)

????????if?typ?~=?parser.BULK_REPLY?or?not?server?then

????????????????????return?ngx.redirect("/paas/res")

????????end

????????if?server?==?""?then

????????????????????server?=?"uat.paas.qjclouds.com"

????????end

????????if?server?==?""?then

????????????????????server?=?"uat.paas.qjclouds.com"

????????end

????????local?more?=?server

????????local?have?=?split_arr(more,?",")

????????ngx.var.target?=?have[math.random(1,#have)]

???????';

???????resolver?8.8.8.8;

???????proxy_pass?http://$target;

??????proxy_set_header?Host?$host;

??????proxy_set_header??X-Real-IP????????$remote_addr;

?????proxy_set_header??X-Forwarded-For??$proxy_add_x_forwarded_for;

?????}

access_log?/tmp/access.log;

error_log?/tmp/access.log;

????}

https配置

a.配置重定向

server?{

??listen?0.0.0.0:80;

??#listen?[::]:80?ipv6only=on?default_server;

??server_name?mp.xytest.qjclouds.com;

??server_tokens?off;?##?Don't?show?the?nginx?version?number,?a?security?best?practice

#location?~?^/.well-known?{

#root?/tmp;

#}

??return?301?https://$http_host$request_uri;

}

2.配置https??

server?{

????????listen?443;

server_tokens?off;

????????server_name?mp.xytest.qjclouds.com;

????????index?index.html?index.htm?index.php;

add_header?Access-Control-Allow-Origin?"*";

????????ssl??????????????????on;????

????????ssl_certificate??????vhosts/ssl/mp.xytest.qjclouds.com.pem;

????????ssl_certificate_key??vhosts/ssl/mp.xytest.qjclouds.com.key;????

????????#ssl_ciphers??HIGH:!aNULL:!MD5;????

????????ssl_prefer_server_ciphers???on;????

????????ssl_ciphers?"ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";

????????ssl_protocols?TLSv1?TLSv1.1?TLSv1.2?SSLv2?SSLv3;???

????????ssl_session_cache?shared:SSL:10m;???

????????ssl_session_timeout?5m;

????????location?=?/redis?{

????????????internal;

????????????set_unescape_uri?$key?$arg_key;

????????????redis2_query?get?$key;

????????????redis2_pass?10.68.0.16:6379;

????????}

????????location?/?{

????????????set?$target?'';????????????


????????????access_by_lua?'

????????local?parameters?=?split_path(ngx.var.uri)

????????local?action?=?parameters[1]

????????local?action1?=?parameters[2]

????????local?action2?=?ngx.var.host

????????if?ngx.var.uri?==?"/"?then

???????????????res?=?ngx.location.capture(

????????????????"/redis",?{?args?=?{?key?=?"0_"..action2?}?}

????????????????)

??????????????local?parser?=?require?"redis.parser"

??????????????local?dapeng,?typ?=?parser.parse_reply(res.body)

???????????return?ngx.redirect(dapeng)

????????end

????????if(#parameters?==?0)?then

?????????????????ngx_log(ngx.ERR,?"----------------------->")

?????????????????ngx.exit(ngx.ERROR)

???????????????????ngx.exit(ngx.HTTP_FORBIDDEN)

????????end

????????if?action1?==?nil?then?

?res?=?ngx.location.capture(

????????????????????"/redis",?{?args?=?{?key?=?"0_/paas/res"?}?}

????????????????)


else?

?????????res?=?ngx.location.capture(

????????????????????"/redis",?{?args?=?{?key?=?"0_/"..action.."/"..action1?}?}

????????)

????????end

????????if?res.status?~=?200?then

????????????????????ngx.exit(res.status)

????????end

????????if?not?res.body?then

???????????????res?=?ngx.location.capture(

????????????????"/redis",?{?args?=?{?key?=?"0_paas/res"?}?}

????????????????)

????????end

????????local?parser?=?require?"redis.parser"

????????local?server,?typ?=?parser.parse_reply(res.body)

????????if?typ?~=?parser.BULK_REPLY?or?not?server?then

????????????????????return?ngx.redirect("/paas/res")

????????end

????????if?server?==?""?then

????????????????????server?=?"uatb.ress.qjclouds.com"

????????end

????????ngx.var.target?=?server

???????';

???????resolver?8.8.8.8;???????????????

???????proxy_pass?http://$target;

??????proxy_set_header?Host?$host;

??????proxy_set_header??X-Real-IP????????$remote_addr;??

?????proxy_set_header??X-Forwarded-For??$proxy_add_x_forwarded_for;?

?????}

access_log?/usr/local/nginx/logs/access.log?access;

error_log?/usr/local/nginx/logs/error.log;

????}

redis 帶密碼的配置:

實現(xiàn)思路,

因為每次auth之后,會有返回ok,但是不需要返回OK ,還是返回之前的值的樣子,故重新編輯返回值,只返回之前的key的形式,具體實現(xiàn)方式如下:

????server?{

????????listen?80;

????????server_name?*.xingyun.xxx.com;

????????index?index.html?index.htm?index.php;

????????location?=?/redis?{

????????????internal;

????redis2_raw_queries?$args?$echo_request_body;

????????????redis2_pass?127.0.0.1:6382;

????????}

????????location?/?{

????????????set?$target?'';????????????


????????????access_by_lua?'

????????local?parameters?=?split_path(ngx.var.uri)

????????local?action?=?parameters[1]

????????local?action1?=?parameters[2]

????????local?action2?=?ngx.var.host

????????function?LsReadis(key)

??????????local?parser?=?require?"redis.parser"

??????????local?reqs?=?{

?????????????{"auth",?"mima"},

?????????????{"get",?key}

????????????????}??

??local?raw_reqs?=?{}

?for?i,?req?in?ipairs(reqs)?do

table.insert(raw_reqs,?parser.build_query(req))

??end

???local?res?=?ngx.location.capture("/redis?"?..?#reqs,

?????{?body?=?table.concat(raw_reqs,?"")?})

??if?res.status?~=?200?or?not?res.body?then

?????ngx.log(ngx.ERR,?"failed?to?query?redis")

?????ngx.exit(500)

???end

???replies?=?parser.parse_replies(res.body,?#reqs)

?????return?replies[2][1]

????????end

????????if?ngx.var.uri?==?"/"?then

????if?LsReadis("0_"..action2)?==?nil?then

????ngx.exit(501)

????else

????????????return?ngx.redirect(LsReadis("0_"..action2))

????end

????????end

????????----判斷paas后是否為空

????????if?action1?==?nil?then

????????key?=?"0_paas/res"

????????else

????????key?=?"0_/"..action.."/"..action1

????????end

???????----空值重定向

server?=?LsReadis(key)

????????if?not?server?or?server?==?nil?then

local?key?=?"0_paas/res"

server?=?LsReadis(key)

????????end

???????----redis?連接或取值失敗

???????if?server?==?""?then

??????????server?=?"uatb.xingyun.qjclouds.com"

????????end

???????ngx.var.target?=?server

???????';

???????resolver?8.8.8.8;

???????proxy_pass?http://$target;

???????proxy_set_header?Host?$host;

???????proxy_set_header??X-Real-IP????????$remote_addr;

???????proxy_set_header??X-Forwarded-For??$proxy_add_x_forwarded_for;

}

access_log?/usr/local/nginx/logs/test.log?access;

error_log?/usr/local/nginx/logs/test.log;

????}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,505評論 6 533
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,556評論 3 418
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,463評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,009評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,778評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,218評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,281評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,436評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,969評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,795評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,993評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,537評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,229評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,659評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,917評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,687評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,990評論 2 374

推薦閱讀更多精彩內(nèi)容