文章很長,而且持續更新,建議收藏起來,慢慢讀!瘋狂創客圈總目錄 博客園版 為您奉上珍貴的學習資源 :
免費贈送 :《尼恩Java面試寶典》 持續更新+ 史上最全 + 面試必備 2000頁+ 面試必備 + 大廠必備 +漲薪必備
免費贈送 經典圖書:《Java高並發核心編程(卷1)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高並發核心編程(卷2)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高並發核心編程(卷3)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《尼恩Java面試寶典 最新版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 資源寶庫: Java 必備 百度網盤資源大合集 價值>10000元 加尼恩領取
Nginx 事件驅動模型
事件驅動模型是Nginx服務器保障完整功能和具有良好性能的重要機制之一。
理論篇:操作系統事件驅動模型
實際上,事件驅動並不是計算機編程領域的專業詞匯,它是一種比較古老的響應事件的模型,在計算機編程、公共關系、經濟活動等領域均有很廣泛的應用。顧名思義,事件驅動就是在持續事務管理過程中,由當前時間點上出現的事件引發的調動可用資源執行相關任務,解決不斷出現的問題,防止事務堆積的一種策略。在計算機編程領域,事件驅動模型對應一種程序設計方式,Event-driven programming,即事件驅動程序設計。
事件驅動模型一般是由事件收集器
,事件發送器
,事件處理器
三部分基本單元組成。
其中, 事件收集器
專門負責收集所有的事件,包括來自用戶的(如鼠標單擊事件、鍵盤輸入事件等)、來自硬件的(如時鍾事件等)和來自軟件的(如操作系統、應用程序本身等)。
事件發送器
負責將收集器收集到的事件分發到目標對象中。目標對象就是事件處理器所處的位置。事件處理器主要負責具體事件的響應工作,它往往要到實現階段才完全確定。
在程序設計過程中,對事件驅動機制的實現方式有多種,這里介紹batch programming,即批次程序設計。批次的程序設計是一種比較初級的程序設計方式。使用批次程序設計的軟件,其流程是由程序設計師在實際編碼過程中決定的,也就是說,在程序運行的過程中,事件的發生、事件的發送和事件的處理都是預先設計好的。由此可見,事件驅動程序設計更多的關注了事件產生的隨機性,使得應用程序能夠具備相當的柔性,可以應付種種來自用戶、硬件和系統的離散隨機事件,這在很大程度上增強了用戶和軟件的交互性和用戶操作的靈活性。
事件驅動程序可以由任何編程語言來實現,只是難易程度有別。如果一個系統是以事件驅動程序模型作為編程基礎的,那么,它的架構基本上是這樣的:預先設計一個事件循環所形成的程序,這個事件循環程序構成了“事件收集器”,它不斷地檢查目前要處理的事件信息,然后使用“事件發送器”傳遞給“事件處理器”。“事件處理器”一般運用虛函數機制來實現。
概述:操作系統 事件驅動處理庫
Nginx服務器響應和處理Web請求的過程,就是基於事件驅動模型的,它也包含事件收集器、事件發送器和事件處理器等三部分基本單元。Nginx的“事件收集器”和“事件發送器”的實現沒有太大的特點,重點介紹一下它的“事件處理器”。
通常,我們在編寫服務器處理模型的程序時,基於事件驅動模型,“目標對象”中的“事件處理器”可以有以下幾種實現辦法:
- “事件發送器”每傳遞過來一個請求,“目標對象”就創建一個新的進程,調用“事件處理器”來處理該請求。
- “事件發送器”每傳遞過來一個請求,“目標對象”就創建一個新的線程,調用“事件處理器”來處理該請求。
- “事件發送器”每傳遞過來一個請求,“目標對象”就將其放入一個待處理事件的列表,使用非阻塞I/O方式調用“事件處理器”來處理該請求。
以上的三種處理方式,各有特點,第一種方式,由於創建新的進程的開銷比較大,會導致服務器性能比較差,但其實現相對來說比較簡單。
第二種方式,由於要涉及到線程的同步,故可能會面臨死鎖、同步等一系列問題,編碼比較復雜。
第三種方式,在編寫程序代碼時,邏輯比前面兩種都復雜。
大多數網絡服務器采用了第三種方式,逐漸形成了所謂的“事件驅動處理庫”。
事件驅動處理庫又被稱為多路IO復用方法,最常見的包括以下三種:select模型,poll模型和epoll模型。Nginx服務器還支持rtsig模型、kqueue模型、dev/poll模型和eventport模型等。通過Nginx配置可以使得Nginx服務器支持這幾種事件驅動處理模型。這里詳細介紹以下它們。
select庫
select庫,是各個版本的Linux和Windows平台都支持的基本事件驅動模型庫,並且在接口的定義上也基本相同,只是部分參數的含義略有差異。使用select庫的步驟一般是:
首先,創建所關注事件的描述符集合。對於一個描述符,可以關注其上面的(Read)事件、寫(Write)事件以及異常發送(Exception)事件,所以要創建三類事件描述符集合,分別用來收集讀事件的描述符、寫事件的描述符和異常事件的描述符。
其次,調用底層提供的select()函數,等待事件發生。這里需要注意的一點是,select的阻塞與是否設置非阻塞I/O是沒有關系的。
然后,輪詢所有事件描述符集合中的每一個事件描述符,檢查是否有相應的事件發生,如果有,就進行處理。
Nginx服務器在編譯過程中如果沒有為其指定其他高性能事件驅動模型庫,它將自動編譯該庫。我們可以使用--with-select_module和--without-select_module兩個參數強制Nginx是否編譯該庫。
poll庫
poll庫,作為Linux平台上的基本事件驅動模型,實在Linux2.1.23中引入的。Windows平台不支持poll庫。
poll與select的基本工作方式是相同的,都是現創建一個關注事件的描述符集合,再去等待這些事件發生,然后在輪詢描述符集合,檢查有沒有事件發生,如果有,就進行處理。
poll庫與select庫的主要區別在於,select庫需要為讀事件、寫事件和異常事件分別創建一個描述符集合,因此在最后輪詢的時候,需要分別輪詢這三個集合。而poll庫只需要創建一個集合,在每個描述符對應的結構上分別設置讀事件、寫事件或者異常事件,最后輪詢的時候,可以同時檢查這三種事件是否發生。可以說,poll庫是select庫的優化實現。
Nginx服務器在編譯過程中如果沒有為其制定其他高性能事件驅動模型庫,它將自動編譯該庫。我們可以使用--with-poll_module和--without-poll_module兩個參數強制Nginx是否編譯該庫。
epoll庫
epoll庫是Nginx服務器支持的高性能事件驅動庫之一,它是公認的非常優秀的事件驅動模型,和poll庫及select庫有很大的不同。epoll屬於poll庫的一個變種,是在Linux 2.5.44中引入的,在Linux 2.6以上的版本都可以使用它。poll庫和select庫在實際工作中,最大的區別在於效率。
從前面的介紹我們知道,它們的處理方式都是創建一個待處理事件列表,然后把這個列表發給內核,返回的時候,再去輪詢檢查這個列表,以判斷事件是否發生。這樣在描述符比較多的應用中,效率就顯得比較低下了。一種比較好的做法是,把描述符列表的管理交給內核負責,一旦有某種事件發生,內核把發生事件的描述符列表通知給進程,這樣就避免了輪詢整個描述符列表。epoll庫就是這樣一種模型。
首先,epoll庫通過相關調用通知內核創建一個由N個描述符的事件列表。然后,給這些描述符設置所關注的事件,並把它添加到內核的事件列表中去,在具體的編碼過程中也可以通過相關調用對事件列表中的描述符進行修改和刪除。
完成設置之后,epoll庫就開始等待內核通知事件發生了。某一事件發生后,內核將發生事件的描述符列表上報給epoll庫。得到事件列表的epoll庫,就可以進行事件處理了。
epoll庫在Linux平台上是最高效的。它支持一個進程打開大數目的事件描述符,上限是系統可以打開文件的最大數目。同時,epoll庫的IO效率不隨描述符數目增加而線性下降,因為它只會對內核上報的“活躍”的描述符進行操作。
rtsig模型
rtsig是Real-Time Signal的縮寫,是實時信號的意思。從嚴格意義上說,rtsig模型並不是常用的事件驅動模型,但Nginx服務器使用了使用實時信號對事件進行響應的支持,官方文檔中將rtsig模型與其他的事件驅動模型並列。
使用rtsig模型時,工作進程會通過系統內核建立一個rtsig隊列用於存放標記事件發生(在Nginx服務器應用中特指客戶端請求發生)的信號。每個事件發生時,系統內核就會產生一個信號存放到rtsig隊列中等待工作進程的處理。
需要指出的是,rtsig隊列有長度限制,超過該長度后就會發生溢出。默認情況下,Linux系統事件信號隊列的最大長度設置為1024,也就是同時最多可以存放1024個發生事件的信號。在Linux 2.6.6-mm2之前的版本中,系統各個進程的事件信號隊列是由內核統一管理的,用戶可以通過修改內核參數/proc/sys/kernel/rtsig-max/來自定義該長度設置。在Linux 2.6.6-mm2之后的版本中,該內核參數被取消,系統各個進程分別擁有各自的事件信號隊列,這個隊列的大小由Linux系統的RLIMT_SIGPENGIND參數定義,在執行setrlimit()系統調用時確定該大小。Nginx提供了worker_rlimit_sigpending參數用於調節這種情況下的事件信號隊列長度。
當rtsig隊列發生溢出時,Nginx將暫時停止使用rtsig模型,而調用poll庫處理未處理的事件,直到rgsit信號隊列全部清空,然后再次啟動rtsig模型,以防止新的溢出發生。
Nginx在配置文件中提供了相關參數對rtsig模型的使用配置。編譯Nginx服務器時,使用--with-rtsig_module配置選項來啟用rtsig模型的編譯。
其他事件驅動模型
除了以上四種主要的事件驅動模型,Nginx服務器針對特定的Linux平台提供了響應的事件驅動模型支持。目前實現的主要有kqueue模型、/dev/poll模型和eventport模型等。
-
kqueue模型,是用於支持BSD系列平台的高效事件驅動模型,主要用在FreeBSD 4.1及以上版本、OpenBSD 2.9及以上版本、NetBSD 2.0及以上版本以及Mac OS X平台上。該模型也是poll庫的一個變種,其和epoll庫的處理方式沒有本質上的區別,都是通過避免輪詢操作提供效率。該模型同時支持條件觸發(level-triggered,也叫水平觸發,只要滿足條件就觸發一個事件)和邊緣觸發(edge-triggered,每當狀態變化時,觸發一個事件)。如果大家在這些平台下使用Nginx服務器,建議選在該模型用於請求處理,以提高Nginx服務器的處理性能。
-
/dev/poll模型,適用於支持Unix衍生平台的高效事件驅動模型,其主要在Solaris711/99及以上版本、HP/UX 11.22及以上版本、IRIX 6.5.15及以上版本和Tru64 UNIX 5.1A及以上版本的平台中使用。該模型是Sun公司在開發Solaris系列平台時提出的用於完成事件驅動機制的方案,它使用了虛擬的/dev/poll設備,開發人員可以將要監視的文件描述符加入這個設備,然后通過ioctl()調用來獲取事件通知。在以上提到的平台中,建議使用該模型處理請求。
-
eventport模型,適用於支持Solaris 10及以上版本平台的高效事件驅動模型。該模型也是Sun公司在開發Solaris系列平台時提出的用於完成事件驅動機制的方案,它可以有效防止內核崩潰情況的發生。Nginx服務器為此提供了支持。
以上就是Nginx服務器支持的事件驅動庫。可以看到,Nginx服務器針對不同的Linux或Unix衍生平台提供了多種事件驅動模型的處理,盡量發揮系統平台本身的優勢,最大程度地提高處理客戶端請求事件的能力。在實際工作中,我們需要根據具體情況和應用情景選擇使用不同的事件驅動模型,以保證Nginx服務器的高效運行。
有關事件處理模型的由淺入深介紹
有關事件處理模型的由淺入深介紹, 請參見 《尼恩三部曲之 Java 高並發核心編程 卷1 》
來自於《Java高並發核心編程卷1》一書,此書的最新電子版,已經免費贈送,大家找尼恩領取即可。
而且,《Java高並發核心編程卷1》的電子書,會不斷優化和迭代。最新一輪的迭代,增加了 消息驅動IO模型的內容,這是之前沒有的,使得在 Java NIO 底層原理這塊,書的內容變得非常全面。
另外,如果出現內容需要更新,到處要更新的話,工作量會很大,所以后續的更新,都會統一到電子書哦。
實操:Nginx的事件處理組件配置
Nginx 的連接處理機制在不同的操作系統會采用不同的 I/O 模型,要根據不同的系統選擇不同的事件處理模型,可供選擇的事件處理模型有:kqueue 、rtsig 、epoll 、/dev/poll 、select 、poll ,其中 select 和 epoll 都是標准的工作模型,kqueue 和 epoll 是高效的工作模型,不同的是 epoll 用在 Linux 平台上,而 kqueue 用在 BSD 系統中。
Nginx 默認的事件處理模型
Nginx 默認的事件處理模型為 poll /select, 根據系統而定, 比如linux 默認為poll, windows 默認為 select。
下面的內容,來自於官方
http://nginx.org/en/docs/events.html
nginx supports a variety of connection processing methods. The availability of a particular method depends on the platform used. On platforms that support several methods nginx will normally select the most efficient method automatically. However, if needed, a connection processing method can be selected explicitly with the use directive.
The following connection processing methods are supported:
-
select
— standard method. The supporting module is built automatically on platforms that lack more efficient methods. The--with-select_module
and--without-select_module
configuration parameters can be used to forcibly enable or disable the build of this module. -
poll
— standard method. The supporting module is built automatically on platforms that lack more efficient methods. The--with-poll_module
and--without-poll_module
configuration parameters can be used to forcibly enable or disable the build of this module. -
kqueue
— efficient method used on FreeBSD 4.1+, OpenBSD 2.9+, NetBSD 2.0, and macOS. -
epoll
— efficient method used on Linux 2.6+.The
EPOLLRDHUP
(Linux 2.6.17, glibc 2.8) andEPOLLEXCLUSIVE
(Linux 4.5, glibc 2.24) flags are supported since 1.11.3.Some older distributions like SuSE 8.2 provide patches that add epoll support to 2.4 kernels.
-
/dev/poll
— efficient method used on Solaris 7 11/99+, HP/UX 11.22+ (eventport), IRIX 6.5.15+, and Tru64 UNIX 5.1A+. -
eventport
— event ports, method used on Solaris 10+ (due to known issues, it is recommended using the/dev/poll
method instead).
推薦的Nginx 事件處理模型
(1) 推薦:在 Linux 下,Nginx 使用 epoll 的 I/O 多路復用模型
cat /usr/local/nginx/conf/nginx.conf
......
events {
use epoll;
}
(2) 推薦:在 Windows 下,Nginx 使用 select 多路復用模型
說明,網上的博客抄來抄去, 出現bug沒人改
請抱歉,我之前也借用了別人的材料,沒有檢查
網上有博客說 在 Windows 下,Nginx 使用 icop 的 異步IO模型
至於能否使用icop 的 異步IO模型 ,官方的文檔,沒有給出說明,本人也沒有做測試。
所以,上面特意貼出了官方的文檔
如果有技術問題需要切磋, 歡迎找 架構師 尼恩 交流。
高並發場景Nginx的建議配置
#user nobody;
#worker_processes 1;
worker_processes 8; #這個根據硬件有多少核CPU而定
#開發環境
#error_log logs/error.log debug;
#生產環境
error_log logs/error.log;
pid logs/nginx.pid;
events {
use epoll;
worker_connections 1024000;
}
http {
default_type 'text/html';
charset utf-8;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access_main.log main;
access_log off; #日志功能要關閉
#sendfile: 設置為on表示啟動高效傳輸文件的模式。
# sendfile可以讓Nginx在傳輸文件時直接在磁盤和tcp socket之間傳輸數據。
# 開啟這個參數后可以讓數據不用經過用戶buffer。表示開啟零復制,建議生產環境使用
sendfile off;
#sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
gzip off;
#gzip最小長度 一般設置成1K就行,小於1K的就不壓縮了 不然會越壓越大
gzip_min_length 1024;
#gzip壓縮比,1 壓縮比最小處理速度最快,9 壓縮比最大但處理最慢(傳輸快但比較消耗cpu)。
gzip_comp_level 1;
#匹配MIME類型進行壓縮
gzip_types text/plain application/json application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml font/woff;
gzip_vary on;
gzip_disable "MSIE [1-6]\.";
#設置系統獲取幾個單位的緩存用於存儲gzip的壓縮結 果數據流。 例如 4 4k 代表以4k為單位,按照原始數據大小以4k為單位的4倍申請內存。 4 8k 代表以8k為單位,按照原始數據大小以8k為單位的4倍申請內存。
#如果沒有設置,默認值是申請跟原始數據相同大小的內存空間去存儲gzip壓縮結果。
gzip_buffers 4 8k;
#gzip默認最低支持1.1現在改成最低支持1.0 近代瀏覽器基本不設置
gzip_http_version 1.0;
#Nginx作為反向代理的時候啟用,開啟或者關閉后端服務器返回的結果,匹配的前提是后端服務器必須要返回包含"Via"的 header頭。
#off - 關閉所有的代理結果數據的壓縮
#expired - 啟用壓縮,如果header頭中包含 "Expires" 頭信息
#no-cache - 啟用壓縮,如果header頭中包含 "Cache-Control:no-cache" 頭信息
#no-store - 啟用壓縮,如果header頭中包含 "Cache-Control:no-store" 頭信息
#private - 啟用壓縮,如果header頭中包含 "Cache-Control:private" 頭信息
#no_last_modified - 啟用壓縮,如果header頭中不包含 "Last-Modified" 頭信息
#no_etag - 啟用壓縮 ,如果header頭中不包含 "ETag" 頭信息
#auth - 啟用壓縮 , 如果header頭中包含 "Authorization" 頭信息
#any - 無條件啟用壓縮
gzip_proxied expired no-cache no-store private auth;
#指定緩存信息
lua_shared_dict ngx_cache 128m;
#指定緩存信息
lua_shared_dict seckill_cache 128m;
#保證只有一個線程去訪問redis或是mysql-lock for cache
lua_shared_dict cache_lock 100k;
#lua擴展加載
# for linux
# lua_package_path "./?.lua;/vagrant/LuaDemoProject/src/?.lua;/usr/local/ZeroBraneStudio-1.80/?/?.lua;/usr/local/ZeroBraneStudio-1.80/?.lua;;";
# lua_package_cpath "/usr/local/ZeroBraneStudio-1.80/bin/clibs/?.so;;";
lua_package_path "./?.lua;/vagrant/LuaDemoProject/src/?.lua;/vagrant/LuaDemoProject/vendor/template/?.lua;/vagrant/LuaDemoProject/src/?/?.lua;/usr/local/openresty/lualib/?/?.lua;/usr/local/openresty/lualib/?.lua;;";
lua_package_cpath "/usr/local/openresty/lualib/?/?.so;/usr/local/openresty/lualib/?.so;;";
# for windows
# lua_package_path "./?.lua;C:/dev/refer/LuaDemoProject/src/vendor/jwt/?.lua;C:/dev/refer/LuaDemoProject/src/?.lua;E:/tool/ZeroBraneStudio-1.80/lualibs/?/?.lua;E:/tool/ZeroBraneStudio-1.80/lualibs/?.lua;E:/tool/openresty-1.13.6.2-win32/lualib/?.lua;;";
# lua_package_cpath "E:/tool/ZeroBraneStudio-1.80/bin/clibs/?.dll;E:/tool/openresty-1.13.6.2-win32/lualib/?.dll;;";
# 初始化項目
init_by_lua_file luaScript/initial/loading_config.lua;
#調試模式(即關閉lua腳本緩存)
#lua_code_cache off;
lua_code_cache on;
#內部網關的代理,內部網關帶有 token 認證
upstream zuul {
# idea 開發環境
# server 192.168.56.121:7799;
# centos 自驗證環境
server "cdh1:8888";
keepalive 1000;
}
underscores_in_headers on;
limit_req_zone $arg_sku_id zone=skuzone:10m rate=6r/m;
limit_req_zone $http_user_id zone=userzone:10m rate=6r/m;
limit_req_zone $binary_remote_addr zone=perip:10m rate=6r/m;
limit_req_zone $server_name zone=perserver:1m rate=10r/s;
limit_req_zone $server_name zone=seckill_server:1m rate=20000r/s;
server {
listen 80;
server_name admin.nginx.server;
default_type 'text/html';
charset utf-8;
limit_req zone=perip;
limit_req zone=perserver;
#管理控制台的web頁面
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Max-Age 600000;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, token';
return 204;
}
# IDEA 管理控制台的web頁面
proxy_pass http://192.168.56.121:8066/ ;
# proxy_pass http://zuul;
}
}
server {
listen 80 default;
server_name nginx.server *.nginx.server;
default_type 'text/html';
charset utf-8;
# 轉發 zuul
location / {
if ($request_method = 'OPTIONS') {
add_header Access-Control-Max-Age 600000;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Credentials true;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT, X-Mx-ReqToken, Keep-Alive, User-Agent, X-Requested-With, If-Modified-Since, Cache-Control, Content-Type, token';
return 204;
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
proxy_pass http://zuul;
}
# 開發調試: 用戶服務
location ^~ /uaa-provider/ {
# idea 開發環境
# proxy_pass http://192.168.56.121:7702/;
# centos 自驗證環境
proxy_pass http://192.168.56.121:7702/uaa-provider/ ;
}
# 開發調試: 秒殺服務
location ^~ /seckill-provider/ {
proxy_pass http://192.168.56.121:7701/seckill-provider/ ;
}
# 開發調試: 管理服務
location ^~ /backend-provider/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header backend 'true'; # 給后台的請求加上自定義頭,方便session區分
proxy_set_header X-Nginx-Proxy true;
# 指向微服務
proxy_pass http://192.168.56.121:6600/backend-provider/ ;
#指向gate way
# proxy_pass http://zuul;
}
# 反向代理:秒殺web頁面
location ^~ /seckill-web/ {
proxy_pass http://192.168.56.121:6601/seckill-web/ ;
}
# Nginx+lua 秒殺:獲取秒殺 token
location = /seckill-provider/api/seckill/redis/token/v2 {
default_type 'application/json';
charset utf-8;
# 限流的 lua 腳本
access_by_lua_file luaScript/module/seckill/getToken_access_limit.lua;
# 獲取秒殺token lua 腳本
content_by_lua_file luaScript/module/seckill/getToken.lua;
}
# ratelimit by sku id
location = /ratelimit/sku {
limit_req zone=skuzone;
echo "正常的響應";
}
# ratelimit by user id
location = /ratelimit/demo {
limit_req zone=userzone;
echo "正常的響應";
}
location = /50x.html{
echo "限流后的降級內容";
}
error_page 502 503 =200 /50x.html;
# 訪問的路徑 http://cdh1/ratelimit/demo2?seckillSkuId=3
# ratelimit by sku id
location = /ratelimit/demo2 {
# 限流的 lua 腳本
access_by_lua_file luaScript/module/seckill/getToken_access_limit.lua;
echo "正常的響應";
}
}
server {
listen 8080 default;
server_name nginx.server *.nginx.server ;
#limit_req zone=seckill_server;
#第一個lua腳本 hellword
location /helloworld {
default_type 'text/html';
charset utf-8;
content_by_lua_file luaScript/module/demo/helloworld.lua;
}
location / { # 自動匹配到(htm|html)格式
## 開發階段,配置頁面不緩存html和htm結尾的文件
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
index index.html;
root /vagrant/LuaDemoProject/src/www/static; #服務器路徑
default_type 'text/html';
}
location ~ .*\.(htm|html)$ { # 自動匹配到(htm|html)格式
## 開發階段,配置頁面不緩存html和htm結尾的文件
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
root /vagrant/LuaDemoProject/src/www/static; #服務器路徑
default_type 'text/html';
}
location ~ .*\.(js|script)$ { # 自動匹配到(jpg|gif|png)格式
add_header Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate";
root /vagrant/LuaDemoProject/src/www/static; #服務器路徑
default_type 'application/javascript';
}
location ~ .*\.(css)$ { # 自動匹配到(css)格式
root /vagrant/LuaDemoProject/src/www/static; #服務器路徑
default_type 'text/css';
}
# 開發調試: 庫存服務
location ^~ /stock-provider/ {
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://zuul/stock-provider/ ;
}
# 開發調試: 秒殺服務
location ^~ /seckill-provider/ {
# proxy_pass http://localhost:7701/seckill-provider/ ;
#指向gate way
proxy_set_header Host $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://zuul/seckill-provider/;
}
# Nginx+lua :獲取 商品信息
location = /stock-lua/gooddetail {
default_type 'application/json';
charset utf-8;
# 限流的 lua 腳本
#access_by_lua_file luaScript/module/seckill/getToken_access_limit.lua;
# 獲取秒殺token lua 腳本
content_by_lua_file luaScript/module/seckill/good_detail.lua;
}
# Nginx+lua 秒殺:獲取秒殺 token
location ~ /seckill-lua/(.*)/getToken/v3 {
default_type 'application/json';
charset utf-8;
set $skuId $1;
limit_req zone=userzone;
limit_req zone=seckill_server;
# 限流的 lua 腳本
# access_by_lua_file luaScript/module/seckill/getToken_access_limit.lua;
# 獲取秒殺token lua 腳本
content_by_lua_file luaScript/module/seckill/getToken_v3.lua;
}
location = /echo {
echo "echo";
}
location = /50x.html{
echo "限流后的降級內容";
}
error_page 502 503 =200 /50x.html;
}
}