中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何通過 Lua 擴展 Nginx

發布時間:2021-07-10 10:31:01 來源:億速云 閱讀:169 作者:chen 欄目:大數據

這篇文章主要講解了“如何通過 Lua 擴展 Nginx”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何通過 Lua 擴展 Nginx”吧!

1. ngx_lua 模塊


  • Nginx 模塊需要用 C 開發,而且必須符合一系列復雜的規則,最重要的用 C 開發模塊必須要熟悉 Nginx 的源代碼,使得開發者對其望而生畏。

  • ngx_lua 模塊通過將 lua 解釋器集成進 Nginx,可以采用 lua 腳本實現業務邏輯。

  • 該模塊具有以下特性:

    • 高并發、非阻塞地處理各種請求。

    • Lua 內建協程,這樣就可以很好地將異步回調轉換成順序調用的形式。

    • 每個協程都有一個獨立的全局環境(變量空間),繼承于全局共享的、只讀的“comman data”。

  • 得益于 Lua 協程的支持,ngx_lua 在處理 10000 個并發請求時只需要很少的內存。根據測試,ngx_lua 處理每個請求只需要 2KB 的內存,如果使用 LuaJIT 則會更少。

  • ngx_lua 非常適合用于實現可擴展的、高并發的服務。

2. 協程(Coroutine)


1. 協程類似一種多線程,與多線程的區別
  • 協程并非 os 線程,所以創建、切換開銷比線程相對較小。

  • 協程與線程一樣有自己的棧、局部變量等,但是協程的棧是在用戶進程空間模擬的,所以創建、開銷很小。

  • 多線程程序是多個線程并發執行,也就是說在一瞬間有多個控制流在執行。而協程強調的是一種多個協程間協作的關系,只有當一個協程主動放棄執行權,另一個協程才能取得執行權,所以在某一瞬間,多個協程間只有一個在運行。

  • 由于多個協程是只有一個在運行,所以對于臨界區的訪問不需要加鎖,而多線程的情況則必須加鎖。

  • 多線程程序由于有多個控制流,所以程序的行為不可控,而多個協程的執行是由開發者定義的所以是可控的。

Nginx 的每個 Worker 進程都是在 epoll 或 kqueue 這樣的事件模型之上,封裝成協程,每個請求都有一個協程進行處理。這正好與 Lua 內建協程的模型是一致的,所以即使 ngx_lua 需要執行 lua,相對 C 有一定的開銷,但依然能保證高并發能力。

3. Nginx 進程模型


  • Nginx 采用多進程模型,單Master-多Worker,Master 進程主要用來管理 Worker 進程。

  • Worker 進程采用單線程、非阻塞地事件模型(Event Loop,事件循環)來實現端口的監聽及客戶端請求的處理和響應,同時 Worker 還要處理來自 Master 的信號。Worker 進程個數一般設置為機器 CPU 核數。

1. Master 進程具體包括如下 4 個主要功能
  • 接受來自外界的信號。

  • 向各 Worker 進程發送信號。

  • 監控 Worker 進程的運行狀態。

  • 當 Worker 進程退出后(異常情況下),會自動重新啟動新的 Worker 進程。

2. 進程模型

如何通過 Lua 擴展 Nginx

4. HTTP 請求處理


階段說明
post-read讀取請求內容階段,nginx 讀取并解析完請求頭之后就立即開始運行
server-rewriteserver 請求地址重寫階段
find-config配置查找階段,用來完成當前請求與 location 配置塊之間的配置工作
rewritelocation 請求地址重寫階段,當 ngx_rewrite 指令用于 location 中,就是在這個階段運行的
post-rewrite請求地址重寫階段,當 nginx 完成 rewrite 階段所要求的內部跳轉動作,如果 rewrite 階段有這個要求的話
preaccess訪問權限檢查準備階段,ngx_limit_req 和 ngx_limit_zone 在這個階段運行,ngx_limit_req 可以控制請求的訪問頻率,ngx_limit_zone 可以控制訪問的并發度。
access權限檢查階段,ngx_access 在這個階段運行,配置指令多是執行訪問控制相關的任務,入檢查用戶的訪問權限,檢查用戶的來源 IP 是否合法
post-access訪問權限檢查提交階段
try-files配置 try_files 處理階段
content內容產生階段,是所有請求處理階段中最為重要的階段,因為這個階段的指令通常是用來生成 HTTP 響應內容的
log日志模塊處理階段

5. ngx_lua 指令


  • ngx_lua 屬于 nginx 的一部分,它的執行指令都包含在 nginx 的 11 個步驟之中了,相應的處理階段可以做插入式處理,即可插拔式架構,不過 ngx_lua 并不是所有階段都會運行的;另外指令可以在 http、server、server if、location、location if 幾個范圍進行配置。

指令所處處理階段使用范圍解釋
init_by_lua<br/>init_by_lua_fileloading-confighttpnginx Master 進程加載配置時執行;<br/>通常用于初始化全局配置/預加載 Lua 模塊
init_worker_by_lua<br/>init_worker_by_lua_filestarting-workerhttp每個 Nginx Worker 進程啟動時調用的計時器,如果 Master 進程不允許<br/>則只會在 init_by_\lua 之后調用;通常用于定時拉取配置/數據,<br/>或者后端服務的健康檢查。
set_by_lua<br/>set_by_lua_filerewriteserver,server if,location,location if設置 nginx 變量,可以實現復雜的賦值邏輯;此處是阻塞的,Lua 代碼要做到非常快
write_by_lua<br/>rewrite_by_lua_filerewrite tailhttp,server,location,location ifrewrite 階段處理,可以實現復雜的轉發/重定向邏輯。
access_by_lua<br/>access_by_lua_fileaccess tailhttp,server,location,location if請求訪問階段處理,用于訪問控制
content_by_lua<br/>content_by_lua_filecontentlocation,location if內容處理器,接受請求處理并輸出響應
header_filter_by_lua<br/>header_filter_by_lua_fileoutput-header-firsthttp,server,location,location if設置 header 和 cookie
body_filter_by_lua<br/>body_filter_by_lua_fileoutput-body-filterhttp,server,location,location if對響應數據進行過濾,比如截斷、替換
log_by_lua<br/>log_by_lua_fileloghttp,server,location,location iflog 階段處理,比如記錄訪問量/統計平均響應時間

6. OpenResty


1. 概念
  • OpenResty 是一個基于 Nginx 與 Lua 的高性能 Web 平臺,其內部集成了大量精良的 Lua 庫、第三方模塊以及大多數的依賴項。用于方便地搭建能夠處理超高并發、擴展性極高的動態 Web 應用、Web 服務和動態網關。

2. 工作原理
  • OpenResty 通過匯聚各種設計精良的 Nginx 模塊(主要由 OpenResty 團隊自主開發),從而將 Nginx 有效地變成一個強大的通用 Web 應用平臺。這樣,Web 開發人員和系統工程師可以使用 Lua 腳本語言調用 Nginx 支持的各種 C 以及 Lua 模塊,快速構造出足以勝任 10k 乃至 1000k 以上單機并發連接的高性能 Web 應用系統。

3. 目標
  • OpenResty 的目標是讓你的 Web 服務直接跑在 Nginx 服務內部,充分利用 Nginx 的非阻塞 I/O 模型,不僅僅對 HTTP 客戶端請求,甚至于對遠程后端諸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都進行一致的高性能響應。

7. ngx_lua 實例


  • content_by_lua:內容處理器,接收請求處理并輸出響應。

  • 該指令工作在 Nginx 處理流程的 content 階段,即內容產生階段,是所有請求處理階段中最為重要的階段,因為這個階段的指令通常是用來生成 HTTP 響應內容的。

  • 測試

    輸出:
    $ curl http://127.0.0.1/
    $ Hello,world


1. 簡單示例
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>Hello, world!</p>")
            ';
        }
    }

}
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
                ngx.say('Hello, world!')
            }
        }
    }

}
啟動
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_01.conf

測試
curl -i http://127.0.0.1/
2. 休眠示例
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location /lua_1 {
            default_type text/html;
            content_by_lua_block {
                ngx.say('Hello, world! @ Time 1!')
                ngx.sleep(3)
                ngx.say('Hello, world! @ Time 2!')
            }
        }
    }

}
啟動
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_02.conf

測試
curl -i http://127.0.0.1/lua_1
curl -i http://127.0.0.1/lua_1
3. 帶參數示例
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location /lua_1 {
            default_type text/html;
            content_by_lua_block {
                ngx.say(ngx.var.arg_a)
            }
        }
    }

}
啟動
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_03.conf

測試
curl -i http://127.0.0.1?a=nginx_lua

8. OpenResty 連接 redis


配置文件
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location ~/redis_lua/(\d+)$ {
            default_type text/html;
            charset utf-8;
            lua_code_cache on;
            content_by_lua_file '/home/zp/openresty/lua/redis.lua';
        }
    }

}
lua 腳本
local json = require("cjson")
local redis = require("resty.redis")
local red = redis:new()
red:set_timeout(1000)
local ip = "127.0.0.1"
local port = 6379
local ok, err = red:connect(ip, port)
if not ok then
    ngx.say('connect to redis error: ', err)
    return ngx.exit(500)
end

local id = ngx.var[1]
local value = "calue-"..id

red:set(id, value)

local resp, err = red:get(id)

if not resp then
    ngx.say('get from redis error: ', err)
    return ngx.exit(500)
end

red:close()

ngx.say(json.encode({content=resp}))
測試
啟動
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_04.conf

測試
curl -i http://127.0.0.1/redis_lua/1
curl -i http://127.0.0.1/redis_lua/2
curl -i http://127.0.0.1/redis_lua/3

感謝各位的閱讀,以上就是“如何通過 Lua 擴展 Nginx”的內容了,經過本文的學習后,相信大家對如何通過 Lua 擴展 Nginx這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

耿马| 璧山县| 肥西县| 额济纳旗| 黄大仙区| 进贤县| 成武县| 浦北县| 固原市| 镇康县| 承德市| 鄯善县| 南丹县| 大石桥市| 隆子县| 尉氏县| 湘西| 郯城县| 内江市| 图们市| 郸城县| 汨罗市| 扎囊县| 搜索| 大厂| 甘南县| 高邑县| 垣曲县| 南陵县| 望奎县| 嘉善县| 汝州市| 浙江省| 修水县| 焉耆| 兴国县| 宁国市| 新郑市| 高碑店市| 忻州市| 汶川县|