<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                > 轉載聲明: 本文轉載自https://yxudong.github.io/%E3%80%8AOpenResty%E7%B2%BE%E5%8D%8E%E6%95%B4%E7%90%86%E3%80%8B3.OpenResty%20%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%E5%8E%9F%E5%9B%A0/,原作者為`Yxd`。本轉載僅出于學習和分享之目的,并不代表本公眾號作者觀點。版權屬于原作者,未經允許不得用于商業用途。如需轉載或引用,請與原作者聯系。 > ## 運行在 Nginx 整體架構之上 OpenResty 的 master 和 worker 進程中,都包含一個 LuaJIT VM。在同一個進程內的所有協程,都會共享這個 VM,并在這個 VM 中運行 Lua 代碼。 而在同一個時間點上,每個 worker 進程只能處理一個用戶的請求,也就是只有一個協程在運行。 NGINX 實際上是通過 epoll 的事件驅動,來減少等待和空轉,才盡可能地讓 CPU 資源都用于處理用戶的請求。 畢竟,只有單個的請求被足夠快地處理完,整體才能達到高性能的目的。 如果采用的是多線程模式,讓一個請求對應一個線程,那么在 C10K 的情況下,資源很容易就會被耗盡的。 > OpenResty 和 LuaJit 架構圖 ![](https://img.kancloud.cn/5c/36/5c364d956b0b0c2c612c7fe17138835f_1146x828.png) ## cosocket 是 OpenResty 的核心和精髓。 在早期的 OpenResty 版本中,如果想要去與 Redis、memcached 這些服務交互的話,需要使用 redis2-nginx-module、redis-nginx-module 和 memc-nginx-module這些 C 模塊。 這些模塊至今仍然在 OpenResty 的發行包中。不過,cosocket 功能加入以后,它們都已經被 lua-resty-redis 和 lua-resty-memcached 替代,基本上沒人再去使用 C 模塊連接外部服務了。 實際上,cosocket 是 OpenResty 中的專有名詞,是把協程和網絡套接字的英文拼在一起形成的,即 cosocket = coroutine + socket。 cosocket 是各種 lua-resty-\* 非阻塞庫的基礎,沒有 cosocket,開發者就無法用 Lua 來快速連接各種外部的網絡服務。 cosocket 不僅需要 Lua 協程特性的支持,也需要 Nginx 中非常重要的事件機制的支持,這兩者結合在一起,最終實現了非阻塞網絡 I/O。 如果我們在 OpenResty 中調用一個 cosocket 相關函數,內部實現便是下面這張圖的樣子: ![](https://img.kancloud.cn/4e/1d/4e1d3fb5e387576e4396b3e7b7d2f506_1692x756.png) cosocket 函數流程 遇到網絡 I/O 時,它會交出控制權(yield),把網絡事件注冊到 Nginx 監聽列表中,并把權限交給 Nginx;當有 Nginx 事件達到觸發條件時,便喚醒對應的協程繼續處理(resume)。 ### cosocket API 和指令簡介 * 創建對象:ngx.socket.tcp。 * 設置超時:tcpsock:settimeout 和 tcpsock:settimeouts。 * 建立連接:tcpsock:connect。 * 發送數據:tcpsock:send。 * 接受數據:tcpsock:receive、tcpsock:receiveany 和 tcpsock:receiveuntil。 * 連接池:tcpsock:setkeepalive。 * 關閉連接:tcpsock:close。 這些 API 可以使用的上下文: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer., ssl_certificate_by_lua, ssl_session_fetch_by_lua*_ 在某些階段是不能使用的,比如 init_by_lua,log_by_lua*,參考 https://github.com/openresty/lua-nginx-module#cosockets-not-available-everywhere ## LuaJit 通過 tracing 對熱代碼進行編譯。 ### LuaJIT 在 OpenResty 整體架構中的位置 ![](https://img.kancloud.cn/47/cc/47cc765271f06716cf0fa668c9bbadf7_1180x874.png) OpenResty 的 worker 進程都是 fork master 進程而得到的,master 進程中的 LuaJIT 虛擬機也會一起 fork 過來。 在同一個 worker 內的所有協程,都會共享這個 LuaJIT 虛擬機,Lua 代碼的執行也是在這個虛擬機中完成的。 ### LuaJIT vs Lua 標準 Lua 和 LuaJIT 是兩回事兒,LuaJIT 只是兼容了 Lua 5.1 的語法。 在 OpenResty 中,可以用 Lua C API 來調用 C 函數,還可以在 LuaJIT 中使用 FFI。 #### 性能 其實標準 Lua 出于性能考慮,也內置了虛擬機 (Lua VM),所以 Lua 代碼并不是直接被解釋執行的,而是先由 Lua 編譯器編譯為字節碼(Byte Code),然后再由 Lua 虛擬機執行。 而 LuaJIT 的運行時環境,除了一個匯編實現的 Lua 解釋器外,還有一個可以直接生成機器代碼的 JIT 編譯器。 開始的時候,LuaJIT 和標準 Lua 一樣,Lua 代碼被編譯為字節碼,字節碼被 LuaJIT 的解釋器解釋執行。 但不同的是,LuaJIT 的解釋器會在執行字節碼的同時,記錄一些運行時的統計信息,當這些次數超過某個隨機的閾值時,便認為對應的 Lua 函數入口或者對應的 Lua 循環足夠熱,這時便會觸發 JIT 編譯器開始工作。 編譯的過程,是把 LuaJIT 字節碼先轉換成 LuaJIT 自己定義的中間碼(IR),然后再生成針對目標體系結構的機器碼。 所以,所謂 LuaJIT 的性能優化,本質上就是讓盡可能多的 Lua 代碼可以被 JIT 編譯器生成機器碼,而不是回退到 Lua 解釋器的解釋執行模式。 #### FFI 除了兼容 Lua 5.1 的語法并支持 JIT 外,LuaJIT 還緊密結合了 FFI(Foreign Function Interface),可以直接在 Lua 代碼中調用外部的 C 函數和使用 C 的數據結構。 類似的,我們可以用 FFI 來調用 NGINX、OpenSSL 的 C 函數,來完成更多的功能。 ![](https://img.kancloud.cn/cb/26/cb26ae78e158ccd9692f9be711d22032_550x140.png) 實際上,FFI 方式比傳統的 Lua/C API 方式的性能更優,這也是 lua-resty-core 項目(后面會介紹)存在的意義。 #### JIT 為什么不是全程編譯? 既然編譯過后效率更高,為什么不采用全程編譯,而是只針對熱代碼編譯? 1. 時間:如果是少量運行,得不償失 2. 空間 編譯后占用的內存會變大 3. JIT 編譯優化需要運行的信息 并不是所有的編譯執行都比解釋執行效率高,給的運行時信息越多,效果越好
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看