正文前先來一波福利推薦:
福利一:
百萬年薪架構師視頻,該視頻可以學到很多東西,是本人花錢買的VIP課程,學習消化了一年,為了支持一下女朋友公眾號也方便大家學習,共享給大家。
福利二:
畢業答辯以及工作上各種答辯,平時積累了不少精品PPT,現在共享給大家,大大小小加起來有幾千套,總有適合你的一款,很多是網上是下載不到。
獲取方式:
微信關注 精品3分鍾 ,id為 jingpin3mins,關注后回復 百萬年薪架構師 ,精品收藏PPT 獲取雲盤鏈接,謝謝大家支持!
------------------------正文開始---------------------------
一.前言
我們都知道Nginx有很多的特性和好處,但是在Nginx上開發成了一個難題,Nginx模塊需要用C開發,而且必須符合一系列復雜的規則,最重要的用C開發模塊必須要熟悉Nginx的源代碼,使得開發者對其望而生畏。為了開發人員方便,所以接下來我們要介紹一種整合了Nginx和lua的框架,那就是OpenResty,它幫我們實現了可以用lua的規范開發,實現各種業務,並且幫我們弄清楚各個模塊的編譯順序。關於OpenResty,我想大家應該不再陌生,隨着系統架構的不斷升級、優化,OpenResty在被廣泛的應用。
二.OpenResty運行原理
Nginx 采用的是 master-worker 模型,一個 master 進程管理多個 worker 進程,基本的事件處理都是放在 woker 中,master 負責一些全局初始化,以及對 worker 的管理。在OpenResty中,每個 woker 使用一個 LuaVM,當請求被分配到 woker 時,將在這個 LuaVM 里創建一個 coroutine(協程)。協程之間數據隔離,每個協程具有獨立的全局變量_G。
ps. 協程和多線程下的線程類似:有自己的堆棧,自己的局部變量,有自己的指令指針,但是和其他協程程序共享全局變量等信息。線程和協程的主要不同在於:多處理器的情況下,概念上來說多線程是同時運行多個線程,而協程是通過代碼來完成協程的切換,任何時刻只有一個協程程序在運行。並且這個在運行的協程只有明確被要求掛起時才會被掛起。
原理圖如下:
三.OpenResty的優勢
首先我們選擇使用OpenResty,其是由Nginx核心加很多第三方模塊組成,其最大的亮點是默認集成了Lua開發環境,使得Nginx可以作為一個Web Server使用。
借助於Nginx的事件驅動模型和非阻塞IO,可以實現高性能的Web應用程序。
而且OpenResty提供了大量組件如Mysql、Redis、Memcached等等,使在Nginx上開發Web應用更方便更簡單。目前在京東如實時價格、秒殺、動態服務、單品頁、列表頁等都在使用Nginx+Lua架構,其他公司如淘寶、去哪兒網等。
四.Nginx和lua的簡介
1. Nginx:
(1) Nginx的優點
-
輕量級同樣起web 服務比apache占用更少內存及資源
-
抗並發nginx 處理請求異步非阻塞而apache 則阻塞型高並發下nginx 能保持低資源低消耗高性能
-
高度模塊化設計編寫模塊相對簡單
-
社區活躍各種高性能模塊出品迅速啊
(2) Nginx為什么性能高,占用內存少
眾所周知,nginx性能高,而nginx的高性能與其架構是分不開的。在這里,我們簡單粗略的介紹一下nginx的架構。
-
首先,nginx采用的是多多進程模式,好處是什么呢?首先,對於每個worker進程來說,獨立的進程,不需要加鎖,所以省掉了鎖帶來的開銷,同時在編程以及問題查找時,也會方便很多。其次,采用獨立的進程,可以讓互相之間不會影響,一個進程退出后,其它進程還在工作,服務不會中斷,master進程則很快啟動新的worker進程。當然,worker進程的異常退出,肯定是程序有bug了,異常退出,會導致當前worker上的所有請求失敗,不過不會影響到所有請求,所以降低風險。
-
Nginx是采用異步非阻塞的方式去處理請求的,什么是異步非阻塞呢?其實就是當一個線程調用出現等待的io之類的情況時,而不是阻塞在這里,而是去處理別的事情,等io准備好了,然后再去執行,具體的我就不在這里和大家描述了。
2. lua:
(1) Lua 是一個小巧的腳本語言。作者是巴西人。該語言的設計目的是為了嵌入應用程序中,從而為應用程序提供靈活的擴展和定制功能
(2) Lua的特點:
-
Lua腳本可以很容易的被C/C++代碼調用,也可以反過來調用C/C++的函數,這使得Lua在應用程序中可以被廣泛應用。不僅僅作為擴展腳本,也可以作為普通的配置文件,代替XML,Ini等文件格式,並且更容易理解和維護。
-
Lua由標准C編寫而成,代碼簡潔優美,幾乎在所有操作系統和平台上都可以編譯,運行。一個完整的Lua解釋器不過200k,在目前所有腳本引擎中,Lua的速度是最快的。這一切都決定了Lua是作為嵌入式腳本的最佳選擇。
五.OpenResty的安裝
上面我門對OpenResty進行了簡單的介紹,運行原理的說明,還有Nginx、Lua優點的介紹,是為了更好的讓大家理解。讓大家知道用這個的好處,接下來我簡單的介紹一下OpenResty的安裝和搭建一個簡單的限流的例子,這是為了讓大家明白,除了上面說的好處,它到底能夠做什么。
OpenResty的安裝:
(1) 需要事先安裝一下所需的插件
1
|
yum
install
readline-devel pcre-devel openssl-devel
|
(2) 下載ngx_openresty-1.7.7.2.tar.gz並解壓
1
|
wget http:
//openresty
.org
/download/ngx_openresty-1
.7.7.2.
tar
.gz
|
(3) 安裝LuaJIT
1
2
3
|
cd
bundle
/LuaJIT-2
.1-20150120/
make
clean &&
make
&&
make
install
ln
-sf luajit-2.1.0-alpha
/usr/local/bin/luajit
|
(4) 下載ngx_cache_purge模塊,該模塊用於清理nginx緩存
1
|
wget https:
//github
.com
/FRiCKLE/ngx_cache_purge/archive/2
.3.
tar
.gz
|
(5) 下載nginx_upstream_check_module模塊,該模塊用於ustream健康檢查
1
|
wget https:
//github
.com
/yaoweibin/nginx_upstream_check_module/archive/v0
.3.0.
tar
.gz
|
(6) 安裝ngx_openresty
1
2
3
4
5
6
7
8
9
|
cd
/usr/servers/ngx_openresty-1
.7.7.2
.
/configure
--prefix=
/usr/servers
--with-http_realip_module
--with-pcre
--with-luajit
--add-module=.
/bundle/ngx_cache_purge-2
.3/
--add-module=.
/bundle/nginx_upstream_check_module-0
.3.0/ -j2
make
&&
make
install
|
(7) 到/usr/servers目錄下,會發現多出來了如下目錄,說明安裝成功
(8) 啟動nginx:/usr/servers/nginx/sbin/nginx(其實我們可以配置好系統的環境變量,配置好后就可以直接數據nginx命令了)
六.防刷(黑白名單)簡單例子的搭建
1. 首先我們先可以在/usr/servers/nginx/conf/ 目錄下創建我們自己的一個簡單的lua文件,就叫做example.lua好了。
輸入如下命令,我們就可以創建一個example.conf文件,或者我們可以cp nginx.conf example.conf 或者mkdir example.conf
2. 接下來我們需要編輯nginx.conf這個啟動配置的文件了
ok,我們進入到編輯界面,接下來我們需要將我們的example.conf文件給引入進來,在nginx.conf的http體里添加一下命令:include example.conf
nginx.conf 的具體內容如下:
其中大家可以看到用紅線框框的是自己項目文件的引入和lua模塊的引入。
3. 接下來我們可以在example.conf文件中寫我們的邏輯實現了
4. 我們可以看到,在example.conf中的server里面配置多個location,而location中嵌入了content_by_lua_file /usr/example/lua/redis_black_limit.lua,從這可以看出在content階段嵌入了lua腳本,進行了內容的響應,在這里,我們進去看看相應的代碼是如何來處理的:
這是一個防刷的demo,從中我們可以看出,我是更具ip,從redis里面取值,然后通過請求ip的匹配,來做到防刷的功能,除此之外,這里有一個語句,我們的注意到,那就是require,這就相當於我們的類加載器,class.forname,從而做到加載進來lua的模塊。
5. 除此之外,還簡單的做了一個設置黑名單和取消黑名單的功能,用來充當我們以后的管理中心,具體邏輯寫在set_black.lua和cancel.lua中,然后在lua.conf中配置好url,具體如下圖所示:
在lua.conf中server體里加入一下代碼:
接下來我們需要寫set_black.lua和cancel.lua文件,文件內容如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
v
set_black.lua:
local
redis =require
"resty.redis"
local
cache =redis.new()
cache:set_timeout(6000)
local
ok,err=cache.connect(cache,
'192.168.150.61'
,6379)
if
not ok
then
ngx.say(
"failed to connect:"
,err)
return
end
local
ip = ngx.var.remote_addr
cache:
set
(
"user:"
..ip..
":block"
,1)
ngx.say(
"user:"
..ip..
":block"
..
"設置黑名單成功"
)
|
1
2
3
4
5
6
7
8
9
10
11
12
|
v
cancel_black.lua:
local
redis =require
"resty.redis"
local
cache =redis.new()
cache:set_timeout(6000)
local
ok,err=cache.connect(cache,
'192.168.150.61'
,6379)
if
not ok
then
ngx.say(
"failed to connect:"
,err)
return
end
local
ip = ngx.var.remote_addr
cache:expire(
"user:"
..ip..
":block"
,0)
ngx.say(
"user:"
..ip..
":block"
..
"移除黑名單"
)
|
7. 效果
做好了以上配置,我們可以開始先設置好黑名單,然后訪問請求,返回的結果是被黑名單了,然后再取消黑名單,再訪問請求,顯示訪問成功,具體結果如下圖。
七.總結
上文簡單的介紹一些OpenResty,以及搭建了一個簡單的應用,目的是想讓大家對這個框架有一個大體的了解。隨着架構的升級,我們會慢慢的把一些不太復雜的業務可以移到nginx層,從而提高我們的吞吐量,解決一些性能上的瓶頸。例如在nginx這一層做簡單的限流、黑白名單,緩存之類的業務復雜性不是太強的工作,從而增加我們的吞吐率,也可以再nginx這一層過濾掉一些垃圾流量,從而讓tomcat層只需要更加專注於業務。(以上是我簡單粗略的一些理解,如果有什么問題,歡迎大家一起討論)