Socket編程
Linux Socket編程領(lǐng)域?yàn)榱颂幚泶罅窟B接請(qǐng)求場(chǎng)景,需要使用非阻塞I/O和復(fù)用,select、poll、epoll是Linux API提供的I/O復(fù)用方式,自從Linux2.6中加入了epoll之后,高性能服務(wù)器領(lǐng)域得到廣泛的應(yīng)用,Nignx就是使用epoll來(lái)實(shí)現(xiàn)I/O復(fù)用支持高并發(fā)。
對(duì)于“高性能”服務(wù)端而言,我們所關(guān)注的并不是語(yǔ)言的性能,而是緩存和語(yǔ)言支持異步非阻塞。
緩存
針對(duì)緩存要明白通信速度的快慢順序
本機(jī)》網(wǎng)絡(luò)
進(jìn)程內(nèi) 》 進(jìn)程間
緩存系統(tǒng)的目標(biāo)是希望在進(jìn)程內(nèi)的命中率是最高的,那么此時(shí)緩存系統(tǒng)整體的效率也是最高的。
異步非阻塞
希望訪問數(shù)據(jù)庫(kù)、訪問網(wǎng)絡(luò),訪問一些比較慢的IO設(shè)備時(shí),不要在等待上耗費(fèi)大量時(shí)間。而是使用事件驅(qū)動(dòng)的方式,當(dāng)系統(tǒng)完成某項(xiàng)任務(wù)后再來(lái)通知我們。這樣就可以將服務(wù)器CPU的空閑資源,用來(lái)服務(wù)客戶端連接。
OpenResty
OpenResty是基于Ngnix和Lua的高性能web平臺(tái),內(nèi)部集成精良的LUa庫(kù)、第三方模塊、依賴項(xiàng)。用于方便搭建能夠處理高并發(fā)、擴(kuò)展性極高的動(dòng)態(tài)web應(yīng)用、web服務(wù)、動(dòng)態(tài)網(wǎng)關(guān)??梢允褂肔ua腳本調(diào)用Ngnix支持的C以及Lua模塊,快速構(gòu)建10K~1000K單機(jī)并發(fā)連接的高性能web應(yīng)用系統(tǒng)。OpenResty的目標(biāo)是讓web服務(wù)直接運(yùn)行在Nginx服務(wù)內(nèi)部,利用Ngnix的非阻塞IO模型,對(duì)HTTP客戶端請(qǐng)求和后端DB進(jìn)行一致的高性能響應(yīng)。
OpenResty的出現(xiàn)可以說是顛覆了高性能服務(wù)端的開發(fā)模式。OpenResty實(shí)際上是Nginx+LuaJIT的完美組合。
OpenResty工作方式
由于Nginx采用的是master-worker模型,也就是一個(gè)master主進(jìn)程管理多個(gè)worker進(jìn)程,基本的事件處理都是放在worker中,master僅負(fù)責(zé)一些全劇初始化,以及對(duì)worker的管理。在OpenResty中,每個(gè)worker使用一個(gè)LuaVM,每個(gè)請(qǐng)求被分配到worker時(shí),將在這個(gè)LuaVM中創(chuàng)建一個(gè)coroutine協(xié)程。協(xié)程之間數(shù)據(jù)隔離,每個(gè)協(xié)程具有獨(dú)立的全局變量_G。
Lua中的協(xié)程和多線程下的線程類似,都有自己的堆棧、局部變量、指令指針。。。,但是和其他協(xié)程程序共享全局變量等信息。線程和協(xié)程主要不同在于:多處理器的情況下,概念上來(lái)說多線程是同時(shí)運(yùn)行多個(gè)線程,而協(xié)程是通過代碼來(lái)完成協(xié)程的切換,任何時(shí)刻只有一個(gè)協(xié)程程序在運(yùn)行。并且這個(gè)在運(yùn)行的協(xié)程只有明確被要求掛起時(shí)才會(huì)被掛起。
根據(jù)實(shí)際測(cè)試,OpenResty性能接近于Nginx 性能之王c module,甚至超過。
OpenResty 架構(gòu)
負(fù)載均衡
LVS+HAProxy將流量轉(zhuǎn)發(fā)給核心Nginx1和Nginx2,即實(shí)現(xiàn)了流量的負(fù)載均衡。
單機(jī)閉環(huán)
所有想要的數(shù)據(jù)都能從本服務(wù)器直接獲取,大多數(shù)時(shí)候無(wú)需通過網(wǎng)絡(luò)或去其他服務(wù)器獲取。
分布式閉環(huán)
單機(jī)閉環(huán)會(huì)遇到2個(gè)主要問題
1.數(shù)據(jù)不一致
例如沒有主從架構(gòu)導(dǎo)致不同服務(wù)器數(shù)據(jù)不一致
2.遇到存儲(chǔ)瓶頸
磁盤或內(nèi)存遇到天花板
解決數(shù)據(jù)不一致比較好的辦法是采用主從或分布式集中存儲(chǔ),而遇到存儲(chǔ)瓶頸就需要進(jìn)行按業(yè)務(wù)鍵進(jìn)行分片,將數(shù)據(jù)分散到多臺(tái)服務(wù)器。
接入網(wǎng)關(guān)
接入網(wǎng)關(guān)又叫接入層,即接收流量的入口,在入口處做如下事情:
接入網(wǎng)關(guān)
OpenResty環(huán)境搭建
http://openresty.org
http://openresty.org/cn/download.html
安裝前準(zhǔn)備,必須安裝perl、libpcre、libssl庫(kù)。
# 從系統(tǒng)路徑中查看必備庫(kù)是否已經(jīng)安裝
$ sudo ldconfig -v
# 安裝必備庫(kù)
$ sudo apt install libpcre3-dev libssl-dev perl make build-essential curl libreadline-dev libncurses5-dev
下載并解壓OpenResty后進(jìn)入其目錄
$ wget https://openresty.org/download/ngx_openresty-1.13.6.1.tar.gz
$ tar -zxvf ngx_openresty-1.13.6.1.tar.gz
$ mv openresty-1.13.6.1 openresty
$ cd openresty
$ 。/configure
默認(rèn)會(huì)被安裝到/usr/local/openresty目錄下
# 編譯并安裝
$ sudo make && make install
$ cd /usr/local/openresty
啟動(dòng)Nginx
$ sudo /usr/local/openresty/nginx/sbin/nginx
$ ps -ef | grep nginx
$ service nginx status
Nginx啟動(dòng)若出現(xiàn)
nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
nginx: [emerg] still could not bind()
說明80端口并占用,查看80端口被占用的端口并重啟。原因在于nginx先監(jiān)聽了ipv4的80端口之后又監(jiān)聽了ipv6的80端口,于是就重復(fù)占用了。
$ sudo netstat -ntlp | grep 80
$ sudo killall -9 nginx
重新編輯Nginx配置文件
$ sudo vim /etc/nginx/conf/nginx.conf
listen 80;
listen [::]:80 ipv6only=on default_server;
使用curl工具或在瀏覽器訪問默認(rèn)80端口
$ curl 127.0.0.1
瀏覽器輸入http://127.0.0.1/
將Nginx工具配置到當(dāng)前用戶的系統(tǒng)環(huán)境變量中
$ sudo vim ~/.bashrc
export PATH=$PATH:/usr/local/openresty/nginx/sbin
$ source ~。/bashrc
$ cd ~
$ nginx -s reload
nginx: [alert] kill(12267, 1) failed (1: Operation not permitted)
開發(fā)文檔
https://www.nginx.com/resources/wiki/modules/lua/
ubuntu 安裝 vcode 或 sublime text 編輯器
content_by_lua
$ vim /usr/local/openresty/nginx/conf/nginx.conf
location /test {
default_type text/html;
content_by_lua ‘ngx.say(“hello openresty”)’;
}
# 重啟Nginx
$ /usr/local/openresty/nginx/sbin/nginx -s reload
# 瀏覽器訪問 127.0.0.1/test
content_by_lua_file
$ vim nginx.conf
location /test {
content_by_lua_file ‘html/test.lua’;
}
$ vim 。。/html/test.lua
ngx.say(“hello lua”)
$ sudo /usr/local/nginx/sbin/nginx -s reload
$ curl 127.0.0.1/test
hello lua
為避免每次修改都需要重啟Nginx,可在Nginx的server選項(xiàng)中配置lua_code_cache選項(xiàng)。
$ vim nginx.conf
server{
lua_code_cache off;
location /test{
content_by_lua_file ‘html/test.lua’;
}
}
$ sudo /usr/local/openresty/nginx/sbin/nginx -s reload
nginx: [alert] lua_code_cache is off; this will hurt performance in /usr/local/openresty/nginx/conf/nginx.conf:48
注意lua_code_cache off;是會(huì)引擎Nginx的性能的,在生產(chǎn)環(huán)境中是需要將其開啟的。
小節(jié)
在OpenResty中開發(fā)是分為兩步的,第一步是修改Nginx配置,第二步是使用Lua開發(fā)自己的腳本。
OpenResty入門
OpenResty最佳實(shí)踐
Nginx Lua
創(chuàng)建工作目錄
OpenResty安裝之后就有配置文件及相關(guān)目錄,為了工作目錄和安裝目錄互不干擾,另外創(chuàng)建OpenResty工作目錄,并另寫配置。
$ mkdir -p ~/openresty/test/logs ~/openresty/test/conf
$ vim ~/openresty/test/conf/nginx.conf
# 設(shè)置Nginx worker工作進(jìn)程數(shù)量,即CPU核數(shù)。
worker_processes 1;
# 設(shè)置錯(cuò)誤日志文件路徑
error_log logs/error.log;
# 配置Nginx服務(wù)器與用戶的網(wǎng)絡(luò)連接
events{
# 設(shè)置每個(gè)工作進(jìn)程的最大連接數(shù)
worker_connections 10224;
}
http{
# 虛擬機(jī)主機(jī)塊定義
server{
# 監(jiān)聽端口
listen 8001;
# 配置請(qǐng)求的路由
location /{
default_type text/html;
content_by_lua_block{
ngx.say(“hello world”);
}
}
}
}
$ nginx -p ~/openresty/test
$ curl 127.0.0.1:8001
hello world
$ vim nginx.conf
location /test{
content_by_lua_file “l(fā)ua/test.lua”;
}
$ cd 。。 && mkdir lua && cd lua
$ vim test.lua
local args = ngx.req.get_uri_args()
local salt = args.salt
if not salt then
ngx.exit(ngx.HTTP_BAD_REQUEST)
end
local md5str = ngx.md5(ngx.time()。.salt)
ngx.say(md5str)
$ sudo /usr/local/openresty/nginx/sbin/nginx -s reload
$ curl -i 127.0.0.1/test?salt=lua
HTTP/1.1 200 OK
Server: openresty/1.13.6.2
Date: Sun, 27 Jan 2019 1017 GMT
Content-Type: application/octet-stream
Transfer-Encoding: chunked
Connection: keep-alive
b55b77f75e46b96b11778ca7edfe8d55
若代碼中出現(xiàn)錯(cuò)誤則需要直接查看Nginx的錯(cuò)誤日志進(jìn)行查看
$ vim nginx/logs/error.log
2019/01/27 1715 [error] 15764#0: *6 failed to load external Lua file “/usr/local/openresty/nginx/test.lua”: cannot open /usr/local/openresty/nginx/test.lua: No such file or.。。
Windows系統(tǒng)下查看Nginx進(jìn)程
λ tasklist /fi “imagename eq nginx.exe”
映像名稱 PID 會(huì)話名 會(huì)話# 內(nèi)存使用
========================= ======== ================ =========== ============
nginx.exe 9072 Console 1 7,840 K
nginx.exe 7692 Console 1 12,304 K
nginx.exe 8120 Console 1 7,840 K
nginx.exe 4552 Console 1 12,188 K
nginx.exe 9588 Console 1 7,828 K
nginx.exe 6256 Console 1 12,216 K
nginx.exe 7308 Console 1 7,828 K
nginx.exe 10192 Console 1 12,212 K
λ taskkill /im nginx.exe /f
成功: 已終止進(jìn)程 “nginx.exe”,其 PID 為 9072。
ngx lua API
參考資料
NGINX API for Lua
編輯:jq
-
Linux
+關(guān)注
關(guān)注
87文章
11336瀏覽量
210098 -
服務(wù)器
+關(guān)注
關(guān)注
12文章
9285瀏覽量
85845 -
API
+關(guān)注
關(guān)注
2文章
1509瀏覽量
62263 -
SSD
+關(guān)注
關(guān)注
21文章
2882瀏覽量
117667
原文標(biāo)題:OpenResty搭建高性能服務(wù)端
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論