OpenResty: 介紹 (摘抄)

 

 

 

 

原文連接:http://www.javashuo.com/article/p-rsupxyac-bq.html    css

 

Nginx 是俄羅斯人發明的, Lua 是巴西幾個教授發明的,中國人章亦春把 LuaJIT VM 嵌入到 Nginx 中,實現了 OpenResty 這個高性能服務端解決方案。html

經過 OpenResty,你能夠把 nginx 的各類功能進行自由拼接, 更重要的是,開發門檻並不高,這一切都是用強大輕巧的 Lua 語言來操控。node

它主要的使用場景主要是:python

在 Lua 中揉和和處理各類不一樣的 nginx 上游輸出(Proxy,Postgres,Redis,Memcached 等)

在請求真正到達上游服務以前,Lua 能夠爲所欲爲的作複雜的訪問控制和安全檢測

爲所欲爲的操控響應頭裏面的信息

從外部存儲服務(好比 Redis,Memcached,MySQL,Postgres)中獲取後端信息,並用這些信息來實時選擇哪個後端來完成業務訪問

在內容 handler 中隨意編寫複雜的 Web 應用,使用 同步但依然非阻塞 的方式,訪問後端數據庫和其餘存儲 在 rewrite 階段,經過 Lua 完成很是複雜的 URL dispatch 用 Lua 能夠爲 nginx 子請求和任意 location,實現高級緩存機制

組織 OpenResty 技術大會以前,我一直認爲本身是一個孤獨的 OpenResty 使用者,以爲本身在使用一個冷門的技術。nginx

雖然你們都據說過 OpenResty 或者 ngx_lua,但感受用在生產環境中使用的卻少之又少,除了幾個 CDN 公司外,好像沒有據說過哪家知名互聯網公司在使用。而 CDN 行業之因此使用,不少是受到 cloudflare 技術棧的影響,OpenResty 的做者也在國外這家 CDN 公司。git

但辦完這個大會,我發現使用者真的挺多,奇虎360的全部服務端團隊都在使用,京東、百度、魅族、知乎、優酷、新浪這些互聯網公司都在使用。有用來寫 WAF、有作 CDN 調度、有作廣告系統、消息推送系統,還有像咱們部門同樣,用做 API server 的。有些還用在很是關鍵的業務上,好比開濤在高可用架構分享的京東商品詳情頁,是我知道的 ngx_lua 最大規模的應用。程序員

  1. 奇虎企業安全服務端技術選型的標準

先說下 3 年多前作架構選型的時候,我爲何會選擇 OpenResty?github

其實架構如何設計並不重要,由於每家公司,每一個團隊,他們的公司文化和技術背景各不相同,生搬硬套會拔苗助長。重要的是當初爲何這麼選擇,中途爲何調整。sql

咱們的產品要求單機上面,服務端提供高性能的 API 接口, QPS 至少過萬,將來須要支撐到 10 萬。咱們並無急於去使用 PHP 、 Python 或者其餘的語言來實現功能,而是先勾勒出一個理想化的技術模型。docker

這個模型應該具有:

非阻塞的訪問網絡IO。在鏈接 MySQL 、Redis 和發起 HTTP 請求時,工做進程不能傻傻的等待網絡IO的返回,而是須要支持事件驅動,用協程的方式讓 CPU 資源更有效的去處理其餘請求。不少語言並不具有這樣的能力和周邊庫。

有完備的緩存機制。不只須要支持 Redis 、Memcached 等外部緩存,也應該在本身的進程內有緩存系統。咱們但願大部分的請求都能在一個進程中獲得數據並返回,這樣是最高效的方法,一旦有了網絡IO和進程間的交互,性能就會受到很大影響。

同步的寫代碼邏輯,不要讓開發者感知到回調和異步。這個也很重要,程序員也是人,代碼應該更符合人的思惟習慣,顯式的回調和異步關鍵字,會打斷思路,也給調試帶來困難。

最好是站在巨人肩上,基於成熟的技術上搭建。採用一門全新誕生的語言和技術,須要經歷語言自身發展期頻繁調整的陣痛,還可能站錯隊。

不只支持 Linux 平臺,還須要支持 Windows 平臺,這個是咱們產品很特別的需求,不少中小企業用戶仍是習慣 Windows 的操做,不具有 Linux 的維護能力。

基於以上幾點的考慮,考察了當時的一些方案,選擇了 OpenResty 。

首先,它最大的特色就是用同步的代碼邏輯實現非阻塞的調用,其次它有單進程內的 LRU cache 和進程間的 share DICT cache,並且它是揉合 nginx 和 LuaJIT 而產生的。並且 nginx 有 Windows 版本,雖然有很是多的限制,但這些限制都是能夠解決的, nginx 官方 Windows 版本中不支持的特性,咱們開源出來的版本都解決了。

第一次看到這樣的方案,我以爲它確定會顛覆高性能服務端的開發。爲何呢?在我以前的公司裏,天天會有近百億次的查詢請求,而服務器只用了十臺。

咱們採用了 nginx C 模塊 + 內置在 nginx 中的 K-V 數據庫(本身開發的),來實現全部的業務邏輯,達到這個目標。聽上去很簡單,可是過程很是艱辛,兩三個十幾年工做經驗的大牛作了一年多才穩定下來。絕大部分開發能力不足,只能可望不可即。並且後續的調試和維護,也會花費很多精力。

可是 OpenResty 的出現改變了這一切, OpenResty 很是的 pythonic ,適合人類的正常思惟。新手通過一兩個月的學習,作出來的 API, 就能夠達到 nginx C 模塊的性能,並且代碼量大大減小,也方便調試。

  1. 以奇虎和新浪爲例,如何在項目中引入新技術

技術選型只是第一步,如何才能在一個產品或者項目中引入 OpenResty 這個新的技術呢?我拿奇虎企業安全和新浪移動這兩家公司真實發生的案例給你們看看。我和新浪移動的周晶,都是在一個有成熟產品的部門,用一兩我的的力量,把一個新技術,替換掉了原有的技術架構。但因爲企業產品和我的產品的不一樣,方法有很大的不同。

先說我所在奇虎企業安全。我在 2012 年初加入這個部門,當時產品主打免費,目標用戶是小企業。因此架構設計上面,只考慮了幾十點、幾百點的終端請求,使用了很是強綁定的 Windows 平臺技術,並且傾向於不用開源軟件,本身新作一個更適合本身的框架。包括本身用 C++ 開發的 Web server,本身寫的 PHP 路由和框架,數據存儲在 sqlite 裏面。

我幫忙修改了兩個月 PHP 的 bug,看明白了技術架構的思路以後,就去新開的一個產品線了。這是一個實驗性的產品,主要面對央企和專用網,一個網絡中有上百萬的終端。

剛開始沒有什麼人關注,我就直接採用了 Linux + OpenResty + Redis + Postgres 的開源組件,性能測試甩以前的N條街。後面這個實驗性的產品,和以前的產品,合併爲一個產品,技術上面就割裂爲兩套架構。老功能用老架構,新功能用新架構。

隨着愈來愈多大用戶的增長,原有的技術架構開始捉襟見肘,技術債務越積壓越多。隨着用戶的抱怨,sqlite 被拋棄,全面換成 Postgres。但對於本身開發的框架仍是有些敝帚自珍。

期間經過對比測試、OpenResty 培訓還有屢次用戶性能問題排查,讓開發同窗們都知道這門技術的優點。快被加班壓垮的開發同窗,逐漸開始選擇使用 OpenResty 而不是自研的框架,來進行新功能的開發,以及舊功能的遷移,來避免加班。

在產品重構的時候,以前自研的服務端框架被徹底拋棄,服務端開發的同窗從 8 、9 我的減小到 3 我的。在新技術的引入過程當中,咱們沒有采用強制的舉措,由於企業產品須要穩定,用戶處部署的版本更新很慢。

而新浪移動周晶的實踐,對你們更有參考意義。新浪移動最開始是基於 Apache,用 PHP 來處理用戶請求。Apache 是同步多進程模型,在併發請求很少的狀況下沒有問題。

可是老是會有突發新聞,好比馬航失聯、文章×××等,突發的高流量把後臺壓垮了幾回。並且能夠預見世界盃的流量也會很大,因此周晶花幾個月時間,用 nginx 替換了 Apache,使用 nginx 的 fast_cgi_cache,QPS 提高了一個數量級。

新浪移動後臺的接口都是使用 PHP 來實現的,在高併發下有些力不從心。而 nginx 簡單的緩存雖然能知足性能,但不能知足業務精細化和數據一致性的要求,須要找 PHP 以外的解決方案,前提是讓 PHP 的開發可以溫馨的使用。 node.js 的回調地獄、Go 的調試不方便,都是一個阻礙。

他們最後選擇了 OpenResty,並且基於 OpenResty 開源了一個 Web 框架 Vanilla(香草),模仿了 Yaf 的使用習慣,讓 PHP 的開發更容易接受和上手。 Vanilla 已經在新浪移動開始使用,一些核心業務,好比高清圖和體育直播,正在向這個框架遷移中。

  1. 入門痛點,以及學習的正確方法

我和周晶的入門,都是本身摸着石頭過河。當時除了 Python 社區「大媽」的那篇使用文章外,找不到其餘的資料。

奇虎和新浪都用 OpenResty 成功替換了以前的技術,但問題仍是挺明顯,就是你們都認爲本身是孤獨的使用者,同事中基本沒有人認同。在關鍵和支撐業務上,使用 OpenResty 有些不放心,都會在邊緣業務上先作嘗試和驗證。

雖然 OpenResty 的性能作的很棒,比肩或者超過其餘全部的高性能解決方案,可是擔憂沒有學習資料、擔憂招不到人、擔憂沒人交流,可能還擔憂做者章亦春哪天撂挑子不幹了,這個項目就黃了。

高可用架構羣裏的各位都是架構師,是技術決策者,在引入一門新技術的時候,確定會考慮到這些風險。好比小米科技馬利超在高可用架構的分享,他們在搶購系統中曾經使用過 ngx_lua,雖然性能知足需求,可是團隊裏面熟悉的人少,最後仍是改爲了 Go 語言實現。

如何解決這些擔心? 社區是有過思考和討論的,咱們放在分享最後講。先從一個嘗試使用這門技術的開發者的角度看,OpenResty 很多基礎工做沒有完善,友好程度不夠:

只能從源碼安裝,沒有 apt-get、brew 等軟件倉庫安裝方法;安裝第三方庫沒有 PIP、NPM 之類的包管理工具,須要去先谷歌,而後拷貝代碼文件到指定的目錄下,才能 require 使用。 代碼編寫須要修改 nginx.conf 和對應的 lua 代碼,即便是 hello world 也是如此。固然你能夠把代碼寫在 nginx 的配置文件裏面,可是生產環境確定是要分離的。這種編寫代碼的方式,不像是一個編程語言,和常規的編程方式不一樣。 有獨特的執行階段概念,由於 OpenResty 是基於 nginx 的,因此也繼承它的這種概念。你的代碼邏輯,可能須要放在不一樣的階段裏面運行,才能獲取你想要的預期。而這些階段間信息如何傳遞,以及哪些 API 不能在某些階段使用,就會常常攔住新手。 遇到問題只有郵件列表這一種方式來溝通,而郵件列表是被牆的。文檔也只有英文版本,致使不少新手的問題沒法被解決。 沒有系統學習 OpenResty 的手段,大都是業務須要實現什麼功能,就去文檔和 API 裏面去找。至於方式對不對,能不能優化,就不知道了。

而 Lua 語言自身也有一些特別的地方:

下標從 1 開始,這個是和其餘編程語言很大的不一樣。 不區分 array 和 dict ,會致使處理 json 的時候,沒法區分 array 和 object。 默認全局變量,須要在全部變量前加 local,忘記的話,可能致使各類難查的 bug。 自帶的字符串正則匹配規則和一般的 PCRE 不一樣,使用的話,學習成本較高。 Lua 標準庫和周邊庫,都是阻塞的,須要本身甄別哪些能夠和 OpenResty 搭配使用。新手很容易使用了阻塞的庫,而致使性能急劇降低。

有沒有好的入門方法?

咱們團隊正在作這方面的努力,儘可能在現有的基礎上,下降學習的門檻。 對於新手,能夠看 StuQ 上面 OpenResty 的系列視頻教程 (http://www.stuq.org/course/detail/1015),咱們計劃有 4 季,分別是入門、進階、實戰和源碼分析。如今第一季已經上線,第二季正在後期製做。看完前兩季,基本上就能夠在項目裏面用了。

對於已經使用了 OpenResty 的開發者,咱們把這兩三年遇到的坑,都記錄在 GitHub 的《OpenResty最佳實踐》上面(https://github.com/moonbingbing/openresty-best-practices),你們能夠當作 cookbook 來使用。

  1. nginScript 這樣的嘗試會替代 OpenResty 嗎?

nginScript 是今年 nginx 大會上,Nginx 官方推出的一個新的配置語言。它是模仿了 OpenResty 的作法,把 JavaScript VM 嵌入到 nginx 中,提供簡單的 nginx 配置功能。

咱們看下它的 hello world:

OpenResty的現狀、趨勢、使用及學習方法

再對比下 OpenResty 的 hello world:
OpenResty的現狀、趨勢、使用及學習方法

看上去差很少,只是 OpenResty 簡潔一些。根據 nginx 官方的說明,nginScript 只是想提供一種更方便配置 nginx 的方法,並不想取代 ngx_lua。

考慮到 JavaScript 自己的流行和開發社區的強大,若是將來兩三年它從一個簡單的 nginx 配置語言,逐漸演變成相似 ngx_lua 這樣功能很是完備的開發語言,甚至替代 OpenResty 也是有可能的。

固然,這個前提是 OpenResty 停滯不前。如今 OpenResty 已經有的功能,和計劃開發的功能,傾向於覆蓋 nginx Plus 的功能。因此 nginx 和 OpenResty 之間,有一個良性的競爭關係,這是你們都樂意看到的。

6 將來重點解決的問題和新增特性

短時間內的目標,是想下降入門的難度:

提供官方二進制發佈包。相似於 docker 的安裝方法,一行命令,下載一個sh腳本,增長一個源地址,不用手工解決依賴,不用源碼編譯,直接就能夠試用。 並且會發布 Windows 的二進制包,方便這個平臺的開發者本機作一些測試。 增長包管理。命令行工具叫 iresty,能夠從 iresty.org 上面搜索、安裝須要的 lua resty 庫,避免找錯庫或者放錯目錄。 寫一本書《 OpenResty 編程》,這本書會成爲官方的入門書籍,框架和關鍵內容由做者春哥直接操刀,我和社區的其餘同窗幫助一塊兒完成。

作完上面3點,OpenResty 的入門難度會下降到和其餘編程語言同樣。

在功能上面,會增長不少激動人心的新特性:

支持 TCP 和 UDP 。Nginx 最新的 stream 子系統已經支持了 TCP,OpenResty 的 ngx_stream_lua 模塊正在開發中,會擁有和現有的 nginx http modlue 相同的 lua API,因此不少應用和庫,能夠不加修改的運行在一個新的子系統上面。

更好的支持推送場景。增長 shared list 共享內存的隊列,能夠用於 worker 間的通信;增長 semaphore 特性,用於 ngx_lua 輕量級線程間的通信。酷狗音樂的推送服務就是基於這些實現的,這些改動點會在這個月併入 master。能夠邀請酷狗音樂的同窗,來給你們詳細分享下里面的細節。 創建一個開源的 WAF 平臺。如今阿里雲和 cloudflare 的 WAF 作的都很棒,經受住了不少實際的考驗。可是都沒有開源,咱們但願最好的 WAF 是開源的,並且是基於 OpenResty 的。 在 OpenResty 中增長內存數據庫。能夠有持久化,或者就是全內存的,支持 SQL 的查詢。這個也是出於極致性能的考慮,有時候咱們仍是須要使用 SQL 來作一些複雜的查詢,但有不想使用那麼重的關係型數據庫,並且數據是能夠丟失的。那麼這個就能夠排上用場。 實現 PHP、Python 等方言,讓 PHP、Python 等程序員能夠用本身喜歡的語言寫 OpenResty 的代碼,底層轉換爲 LuaJIT 的字節碼。

春哥在 OpenResty 技術大會上面說了很是多的新特性,包括 streaming RegEx 正則引擎等等,很是高端,我挑了幾個我以爲有意思的作介紹。

  1. 開源社區建設
    OpenResty 誕生於 2011 年,大多數時間都是春哥主力在維護這個項目,固然也有不少開發者提交 feature 和 bugfix ,但基本上算單打獨鬥。

社區有 github 和郵件列表,大部分仍是提問的。春哥天天會花費不少的時間,來詳細的回答各類基礎問題。

今年新增了 QQ 羣和微信羣, QQ 羣的質量很高,天天都會有不少提問,非技術問題是被禁止的。並且還有了本身的技術大會,能給你們面對面交流的機會。

咱們翻譯了 ngx_lua 的英文文檔,能讓你們更方便的查找資料;咱們搭建了一個不用×××就能訪問的論壇: bbs.iresty.com,用做提問和知識積累的地方。後面會把谷歌郵件列表的內容同步過來。

只有上面這些是不夠的,在 OpenResty 技術大會的次日,咱們召集了一個很小規模的閉門會議,決定成立 OpenResty 諮詢委員會。

這個委員會,是以我的名字參加的,成員來自奇虎 360、新浪、又拍雲、酷狗音樂等公司和社區的開發者,但願把國內社區的核心使用者和開發者團結在一塊兒,促進 OpenResty 的發展。

同時,OpenResty 軟件基金會也開始籌備工做,咱們但願走規範的非盈利組織的模式,來保證 OpenResty 長期穩定發展。給開發者和使用者信心,勇於在關鍵業務上面使用 OpenResty。

Q & A

一、請問 OpenResty 的定位是什麼,從分享來看彷佛全棧了?

定位主要是高性能,全部的新功能和優化,都是針對性能的。 可是也有人拿來作頁面,好比京東;也有人拿來替代 PHP 作 Web server,好比新浪。 我以爲它愈來愈像一個獨立的開發語言。

二、請問 Lua 是否是能夠實現動態配置 location?好比動態切流量?
balancer_by_lua 多是你須要的,你能夠用 Lua 來定義本身的負載均衡器,能夠在每一個請求的級別上去定義,當前訪問的後端的節點地址、端口,還能夠定製很細力度的訪問失敗以後的重試策略。

三、OpenResty 是能夠拿到 nginx 請求裏面的全部信息?那是否是能夠作一些更復雜的轉發操做?能介紹一下 OpenResty 在 cdn 裏面的應用場景嗎?

能夠看下 iresty.com 的分享,又拍的張聰很是詳細的介紹了 OpenResty 在又拍 CDN 的使用。

四、OpenResty 是否修改了 nginx 的源碼,仍是和 nginx 徹底可剝離開的?Nginx 版本升級,OpenResty 也跟着升級嗎?例如 nginx 修復漏洞 bug 等狀況。

OpenResty 不修改 nginx 的源碼,能夠跟隨 nginx 無痛升級。 若是你以爲 OpenResty 升級慢了, 你能夠只拿 ngx_lua 出來,當作 nginx 的一個模塊來編譯。實際上,OpenResty 在測試過程當中,發現了不少 nginx 自身的 bug 。

五、軟 WAF nginx + Lua 是主流和將來方向麼?

我以爲 WAF 應該基於 nginx,無論是性能仍是流行程度。而 OpenResty 具備更靈活操控 nginx 的能力,因此我以爲 OpenResty 在 WAF 領域很是合適。cloudflare 的 WAF 就是基於 OpenResty。

六、看樣子將來可能有各類 ngx_xx,最有可能的是 js,不知道這方面有什麼前沿的動向?
咱們組在嘗試把 PHP 嵌入到 nginx 中,固然性能確定不如 LuaJIT,可是會方便不少 PHP 同窗,有進展的話,咱們會開源出來 :)

七、OpenResty 目前看彷佛是一個 proxy 的配置框架(糅合了 nginx + Lua),但之後的發展是什麼樣子?會不會之後更進一步,好比作一個 API gateway 之類的。OpenResty實際上是但願你們忽略 nginx 的存在,直接使用 ngx_lua 提供的 API 實現本身的業務邏輯。更像一門獨立的開發語言,只不過底層使用 nginx 的網絡庫而已。你能夠按照你的想法搭建任何好玩的服務端應用出來。

相關文章
相關標籤/搜索