Web開發平臺OpenResty(一):學習資料、基本組成與使用方法

做者: 李佶澳   轉載請保留:原文地址   發佈時間:2018-10-25 10:12:32 +0800html

 

說明

OpenResty是什麼?被擴展的Nginx,擴展到能夠直接執行Lua代碼,處理業務邏輯,訪問緩存和數據庫等。mysql

能夠先看一下Nginx、OpenResty和Kong的基本概念與使用方法,對OpenResty有一個總體感知。nginx

學習資料

使用OpenResty,須要對Nginx和Lua比較熟悉。git

Nginx是OpenResty的執行引擎,Lua是OpenResty平臺上使用的開發語言。github

OpenResty的網站給出了幾本關於Lua、Nginx、OpenResty的電子書web

1 OpenResty的主要做者章宜春寫的Programming OpenResty,好像是剛開始寫…redis

2 章宜春寫的Nginx Tutorials (version 2016.07.21),這本書有中文版sql

3 360公司的moonbingbing(真名不知道)組織編寫的OpenResty 最佳實踐,其中對Lua和Nginx也作了不錯的介紹。數據庫

編程語言Lua(一):入門學習資料、基本語法與項目管理工具中收集了更多關於Lua的內容。編程

開發環境搭建

在mac上能夠直接安裝:

brew untap homebrew/nginx
brew install openresty/brew/openresty

在CentOS上的安裝以及源代碼編譯安裝,參考OpenResty編譯安裝

須要安裝lua5.1:

brew install lua@5.1

須要安裝luarocks,這裏不使用brew安裝luarocks,直接下載源代碼安裝:

brew中的luarocks使用的是lua5.3,openresty使用的是lua5.1,系統上同時存在lua5.3和lua5.1,後續用luarocks管理依賴的package、運行openresty應用時可能會遇到麻煩。

wget https://luarocks.org/releases/luarocks-3.0.3.tar.gz
tar zxpf luarocks-3.0.3.tar.gz
cd luarocks-3.0.3
$ ./configure
$ sudo make bootstrap

第一個OpenResty項目

OpenResty應用能夠用openresty定製的nginx(命令openresty)運行,也能夠用resty命令運行(本質上是同樣的,resty是一個perl腳本,最終使用的仍是openresty定製的nginx)。

用resty命令運行

用resty命令直接執行Lua代碼

例如在直接寫一個Lua文件

$cat hello.lua
ngx.say("hello world")

而後用OpenResty的Resty命令執行:

$ resty hello.lua
hello world

用openresty運行

能夠寫一個包含lua代碼的nginx.conf,用openresty命令或者openresty帶的nginx啓動

mkdir -p  hello-world/logs
cd hello-world

建立hello-world/nginx.conf

worker_processes  1;        #nginx worker 數量
error_log logs/error.log;   #指定錯誤日誌文件路徑
events {
    worker_connections 1024;
}

http {
    server {
        #監聽端口,若你的6699端口已經被佔用,則須要修改
        listen 6699;
        location / {
            default_type text/html;

            content_by_lua_block {
                ngx.say("HelloWorld")
            }
        }
    }
}

在hello-world目錄中啓動:

openresty -p `pwd` -c nginx.conf

這時候用ps命令能夠看到nginx進程(openresty命令是鏈接到nginx命令的符號鏈接):

$ ps aux|grep nginx
nginx: worker process
nginx: master process openresty -p /Users/lijiao/study-OpenResty/example/01-hello-world -c nginx.conf

訪問應用:

$ curl 127.0.0.1:6699
HelloWorld

OpenResty的退出、重啓、從新加載等操做,用-s指定對應的信號:

-s signal : send signal to a master process: stop, quit, reopen, reload

例如從新加載:

openresty -s reload

OpenResty與Lua的關係

OpenResty和Lua不是一回事。

Lua是一個小巧精煉編程語言,Lua的解釋器有不少種,能夠到編程語言Lua(一):介紹、入門學習資料、基本語法與項目管理中瞭解。

OpenResty是一個高度定製的Nginx,集成了NginxLua模塊,支持Lua語言。

一樣一段Lua代碼,用OpenResty能夠執行,直接用Lua命令可能不能執行:

例以下面的代碼:

$ cat hello.lua
#! /usr/bin/env lua
--
-- hello.lua
-- Copyright (C) 2018 lijiaocn <lijiaocn@foxmail.com>
--
-- Distributed under terms of the GPL license.
--

ngx.say("hello world")

用OpenResty能夠執行:

$ resty hello.lua
hello world

用Lua不能夠:

$ lua-5.1 ./hello.lua
lua-5.1: ./hello.lua:9: attempt to index global 'ngx' (a nil value)
stack traceback:
	./hello.lua:9: in main chunk
	[C]: ?

用Lua命令執行的時候,提示找不到ngx。

這是由於OpenResty包含的一些Lua Package不在Lua的安裝目錄中,而是在OpenResty本身的安裝目錄中。

以Mac爲例,用brew install openresty/brew/openresty安裝的openresty,它的Package目錄是:

$ ls /usr/local/Cellar/openresty/1.13.6.2/
COPYRIGHT                     homebrew.mxcl.openresty.plist pod
INSTALL_RECEIPT.json          luajit                        resty.index
README.markdown               lualib                        site
bin                           nginx
$ ls /usr/local/Cellar/openresty/1.13.6.2/lualib
cjson.so ngx      redis    resty

所以你會發現,使用openresty的項目代碼中引用require "resty.core",在lua的package目錄中卻怎麼也找不到。

由於它是openresty中的模塊,位於openresty的安裝目錄中:

$ ls /usr/local/Cellar/openresty/1.13.6.2/lualib/resty/core
base.lua     base64.lua   ctx.lua      exit.lua  ....

在使用IDE開發代碼時,爲了可以跳轉到OpenResty的模塊中,須要將OpenResty的模塊目錄加入到SDK的ClassPath/SourcePath中。

OpenResty項目示例:Kong

Kong是一個在OpenResty上實現的API網關應用,這裏經過kong來了解OpenResty應用的源碼的組織方式。

下載Kong的代碼:

git clone https://github.com/Kong/kong
cd kong

kong使用luarocks管理依賴,依賴的package記錄在kong-0.14.1-0.rockspec文件中:

$ cat kong-0.14.1-0.rockspec
...
dependencies = {
  "inspect == 3.1.1",
  "luasec == 0.6",
  "luasocket == 3.0-rc1",
  "penlight == 1.5.4",
  "lua-resty-http == 0.12",
  "lua-resty-jit-uuid == 0.0.7",
  "multipart == 0.5.5",
...

kong項目的發佈方式也記錄在kong-0.14.1-0.rockspec文件中,記錄了模塊與代碼文件的對應關係:

kong-0.14.1-0.rockspec

build = {
  type = "builtin",
  modules = {
    ["kong"] = "kong/init.lua",
    ["kong.meta"] = "kong/meta.lua",
    ["kong.cache"] = "kong/cache.lua",
    ["kong.global"] = "kong/global.lua",
    ["kong.router"] = "kong/router.lua",
    ...

make的時候,是直接用luarocks命令將kong安裝到系統中:

install:
   @luarocks make OPENSSL_DIR=$(OPENSSL_DIR) CRYPTO_DIR=$(OPENSSL_DIR)

安裝以後,在經過OpenResty執行的lua腳本中就能夠引用kong了,例如文件bin/kong中引用kong的模塊kong.cmd.init

$ cat bin/kong
#!/usr/bin/env resty

require "luarocks.loader"

package.path = "./?.lua;./?/init.lua;" .. package.path

require("kong.cmd.init")(arg)

OpenResty項目IDE設置

使用OpenResty的項目可使用Lua的IDE,OpenResty雖然和Lua不是一回事,但它能夠複用Lua的項目工具,使用的時候別忘了將OpenResty的模塊導入到SDK中。

在IntelliJ Idea中的設置方法參考:Lua的項目管理工具-IntelliJ Idea

OpenResty對Nginx的擴展

在前面的例子中,nginx.conf中有一段配置是這樣的:

content_by_lua_block {
                ngx.say("HelloWorld")
            }

這裏的content_by_lua_block指令不是原生的nginx指令,是OpenResty爲Nginx增長的指令。

Nginx使用模塊化設計,支持接入第三方的模塊,第三方模塊能夠爲nginx添加新的配置指令。

OpenResty爲標準的Nginx添加了不少模塊,大大加強了Nginx的能力。

OpenResty收錄的Nginx模塊

OpenResty的應用開發過程,主要就是與OpenResty添加的Nginx模塊,以及各類Lua的Package打交道的過程。

熟悉OpenResty爲Nginx添加的每一個模塊的用途是必須的,下面是OpenResty的網站上列出的Nginx模塊:

array-var-nginx-module,爲nginx.conf增長數組類型的變量

ngx_http_auth_request_module,爲nginx.conf增長了受權指令

ngx_coolkit,收集了一些比較小巧有用的插件

drizzle-nginx-module,增長了訪問mysql的功能

echo-nginx-module,增長了echo系列響應指令

encrypted-session-nginx-module,增長了加解密功能

form-input-nginx-module,讀取解析POST和PUT請求的body

headers-more-nginx-module,修改響應頭

iconv-nginx-module,編碼轉換

memc-nginx-module,對接memcache

lua-nginx-module,使nginx可以識別執行lua代碼

lua-upstream-nginx-module,將lua-nginx-module模塊中的lua api導入到upstreams配置中。

ngx_postgres,增長了訪問postgre數據庫的功能

rds-csv-nginx-module,將RDS格式數據轉換成CSV格式

rds-json-nginx-module,將RDS格式數據轉換成JSON格式

HttpRedisModule,增長了訪問redis的功能

redis2-nginx-module,支持redis 2.0協議

set-misc-nginx-module,爲ngxin的rewrite模塊增長的set_XX指令

srcache-nginx-module,增長了緩存功能

ngx_stream_lua_module,爲Nginx的stream/tcp增長lua支持

xss-nginx-module,添加跨站支持

模塊示例:LuaNginxModule

每一個模塊都定義了本身的指令,能夠到它們各自的項目中查看,OpenResty Componentes

LuaNginxModule爲例,增長了下面的Nginx指令(directives)

lua_capture_error_log
lua_use_default_type
lua_malloc_trim
lua_code_cache
lua_regex_cache_max_entries
lua_regex_match_limit
...
content_by_lua
content_by_lua_block
content_by_lua_file
rewrite_by_lua
rewrite_by_lua_block
rewrite_by_lua_file
...

其中content_by_lua_block等指令,支持lua代碼:

content_by_lua_block {
     ngx.say("I need no extra escaping here, for example: \r\nblah")
 }

LuaNginxModule還實現了Nginx的lua接口,能夠在**_lua_block樣式的指令中直接調用,例如上面的ngx.say

Nginx的lua接口比較多,下面只列出了一部分,能夠到連接中查看所有: … ngx.ctx ngx.location.capture ngx.location.capture_multi ngx.status ngx.header.HEADER ngx.resp.get_headers ngx.req.is_internal …

OpenResty收錄的Lua Package

除了Nginx模塊,OpenResty還收錄了一些Lua Package,這些Lua Package有一些是用C語言開發的,能夠用Lua調用,但在IDE中沒法跳轉到它們的實現。

OpenResty收錄的這些Lua Package,被安裝到了OpenResty的安裝目錄中:

$ ls /usr/local/Cellar/openresty/1.13.6.2/lualib/resty/
aes.lua       core.lua      limit         lrucache      md5.lua       mysql.lua
...

下面是OpenResty網站列出的收錄的Package,有的項目中有多個Lua模塊,導入一欄中只列出了其中一個,能夠它們的源碼中查看:

語言    導入 源碼
C require 「cjson」 LuaCjsonLibrary
C require 「rds.parser」 LuaRdsParserLibrary
C require 「redis.parser」 LuaRedisParserLibrary
Lua require 「resty.core」 LuaRestyCoreLibrary
Lua require 「resty.dns.resolver」 LuaRestyDNSLibrary
Lua require 「resty.lock」 LuaRestyLockLibrary
Lua require 「resty.lrucache」 LuaRestyLrucacheLibrary
Lua require 「resty.memcached」 LuaRestyMemcachedLibrary
Lua require 「resty.mysql」 LuaRestyMySQLLibrary
Lua require 「resty.redis」 LuaRestyRedisLibrary
Lua require 「resty.sha1」 LuaRestyStringLibrary
Lua require 「resty.upload」 LuaRestyUploadLibrary
Lua require 「resty.upstream.healthcheck」   LuaRestyUpstreamHealthcheckLibrary
Lua require 「resty.websocket.server」 LuaRestyWebSocketLibrary
Lua require 「resty.limit.conn」 LuaRestyLimitTrafficLibrary

還有處於試驗狀態的opm命令,用來管理在OpenResty中使用的Lua Package。

OpenResty的接口調用

OpenResty自身的接口有兩部分,一部分是集成的Nginx模塊實現的Lua接口,另外一部分是收錄的Lua Package,它們都位於lualib目錄中:

$ ls -F  /usr/local/Cellar/openresty/1.13.6.2/lualib
cjson.so* ngx/      redis/    resty/

若是集成的Nginx的模塊實現的Lua接口,能夠直接在Lua代碼中調用。(不是十分肯定,下文的ngx.say()是不須要明確引入package就能夠執行的 2018-10-27 14:40:34)

例如「第一個OpenResty項目」的例子中,直接調用LuaNginxModule實現的Nginx的Lua接口ngx.say,不須要引入lua的package。

$ cat hello.lua
ngx.say("hello world")

Lua Package用require引用,例如:

require "resty.core"

須要注意的是lua-nginx-module的部分接口不在lua代碼中,見nginx api for lua

ngx.arg
ngx.var.VARIABLE
Core constants
HTTP method constants
HTTP status constants
Nginx log level constants
print
ngx.ctx
ngx.location.capture
ngx.location.capture_multi
ngx.status
ngx.header.HEADER
ngx.resp.get_headers
ngx.req.is_internal
...

參考

  1. Nginx、OpenResty和Kong的基本概念與使用方法
  2. OpenResty Website
  3. 編程語言(一):Lua介紹、入門學習資料、基本語法與項目管理工具
  4. OpenResty 最佳實踐
  5. OpenResty編譯安裝
  6. OpenResty Reference
  7. Project:lua-nginx-module
  8. lua-nginx-module directives
  9. lua-nginx-module: nginx lua api
  10. Lua的項目管理工具
  11. OpenResty Components
相關文章
相關標籤/搜索