nginx でブラックリストを直接構成し、論理ブロックを記述して実装します。
サーバー (Java) で書き込みます。フィルターを作成し、フィルター内で均一にインターセプトします;
サーバー (Java) にインターセプターを作成し、インターセプター内で均一にインターセプトします;
ここで実装のアイデアとしては、他にもあるかもしれませんが、よく考えてみると、nginx で論理ブロックを書くのは多くの人が得意なことではないようです。コードで実行することは不可能ではありません。このように、同時実行性が高いビジネスのピーク時には、必然的にバックエンド サービスへの負荷が大きくなります。
これは Lua に関するものです。つまり、nginx はゲートウェイとして機能し、プロキシ サーバーとしても機能します。nginx は Lua を統合できるため、Lua を使用して連携して上記のビジネス実装の設計を完了します。
ngx_lua モジュールは、lua インタープリターを Nginx に統合することにより、淘宝網技術チームによって開発されました。
Lua スクリプトは、ビジネス ロジックの実装に使用すると、Lua のコンパクトさ、速度、組み込みコルーチンにより、高い同時実行サービス機能を確保しながら、ビジネス ロジック実装のコストが大幅に削減されます;
OpenRestry
OpenResty は、Nginx と Lua をベースとした高性能 Web プラットフォームです。多数の洗練された Lua ライブラリ、サードパーティ モジュール、およびほとんどの依存関係が統合されており、Web を簡単に構築するために使用されます。超高同時実行性、拡張性の高い動的 Web アプリケーション、Web サービス、動的ゲートウェイを処理できるプラットフォーム;
OpenResty は Nginx と Lua を統合しているため、より使いやすくなります;
簡単に言えば、OpenRestry を直接インストールして使用することで、Nginx と Lua を同時に使用する効果を得ることができます。 mysql、redis、kafka などの他のミドルウェアを内部で操作して、ビジネス アーキテクチャの設計の柔軟性を高めます。
wget https://openresty.org/download/openresty-1.15.8.2.tar.gzをダウンロードします。
tar -zxf openresty-1.15.8.2.tar.gz
このステップは、nginx ソース コードのインストールと関連する環境変数の構成に似ています。デフォルトのものはここにあります;
./configure
nginx ディレクトリに入ると、内部のディレクトリは実行後の nginx 自体の設定とほぼ同じであることがわかります。インストール
conf と入力し、nginx.conf 構成ファイルを見つけて、次の内容を追加します:
location /lua { default_type 'text/html'; content_by_lua 'ngx.say(" <h2>hello,openRestry lua</h2>")'; }
nginx の sbin ディレクトリに入って nginx を起動します
起動が完了したら、ブラウザでサーバーにアクセスするだけです。 nginx サービス自体が開始されました。
アクセスが設定されました。Lua アドレスを確認すると、正常にアクセスできていることがわかります。モジュールは正常にインストールされました。
Lua を使用して Nginx スクリプトを記述する基本構造 ブロックは命令であり、いつ実行するかを指定するために使用されます。ユーザーの Lua コードを実行し、その結果を使用する方法を示します。以下は、一般的に使用される命令の簡単な説明です。
#1、init_by_lua
#このコマンドは、 Nginx が構成をリロードするたびに実行されます。時間のかかる操作モジュールのロードを完了するため、または一部のグローバル構成を初期化するために使用されます
2, init_worker_by_lua*
このコマンドは、ハートビート チェック、スケジュールされたプル サーバー構成などのスケジュールされたタスクを開始するために使用されます。##3, set_by_lua
## この命令は、変数に値を割り当てるためにのみ使用する必要があります。この命令は一度に 1 つの値のみを返すことができ、結果の値は Nginx の指定された変数に与えられます。
4, rewrite_by_lua*
は、内部 URL 書き換えまたは外部リダイレクト (通常は擬似静的 URL 書き換えなど) を実行するために使用されます。このフェーズはデフォルトで最後に実行されます。書き換え処理フェーズの(nginx独自の書き換え関数にも同様の箇所があります)
5、access_by_lua*
该指令用于访问控制,例如,只允许内网IP访问
6、content_by_lua*
该指令是使用最多的指令,大部分任务是在这个阶段完成的,其他过程往往为这个阶段准备数据,正式处理往往都在本阶段执行
7、header_filter_by_lua*
用于设置应答消息的头部信息
8、body_filter_by_lua*
该指令对响应数据进行过滤,如截断、替换
9、log_by_lua*
该指令用于log请求处理阶段,用Lua代码处理日志,但并不替换原有 log处理
10、balancer_by_lua*
该指令主要作用是用来实现上游服务器的负载均衡器算法
11、ssl_certificate_by_*
该指令作用在Nginx和下游服务开始一个SSL握手操作时将允许本配置项的Lua代码
一个使用指令的需求
接下来针对上面提到的各种指令,来做一个简单的需求
nginx接收到请求后,根据参数中gender传入的值,如果gender传入的是1 则在页面上展示 “先生” , 如果gender传入的是0,则在页面上展示“女士”
注意:使用指令编写的基本步骤是,在nginx.conf模块中,自定义localtion块中编写lua的相关代码即可
location /getByGender { default_type 'text/html'; set_by_lua $param " local uri_args = ngx.req.get_uri_args() local gender = uri_args['gender'] local name = uri_args['name'] if gender =='1' then return name..':先生' elseif gender=='0' then return name..':女士' else return name end "; charset utf-8; return 200 $param; }
然后启动nginx做一下测试
1)访问服务,不携带任何参数
这时候无任何返回信息
2)访问服务,携带name参数
3)访问服务,携带name和gender参数
更多的指令可以参照此类方式编写,但是前提需要掌握一点lua的基本语法
Redis在系统中经常作为数据缓存、内存数据库使用,在各类互联网项目中扮演着非常重要的作用;
Lua-resty-redis库是OpenResty提供的一个操作Redis的接口库,可根据自己的业务情况做一些逻辑处理,适合做复杂的业务逻辑。所以下面将以Lua-resty-redis来进行说明。
1、提前安装好redis并启动服务
2、测试下redis客户端
lua-resty-redis提供了访问Redis的详细API,包括创建对接、连 接、操作、数据处理等。这些API基本上与Redis的操作是对应起来的
1、lua中导入redis依赖
redis = require "resty.redis"
2、new,创建一个Redis对象
redis,err = redis:new()
3、创建redis连接
ok:连接成功返回 1,连接失败返回nil;
err:返回对应的错误信息;
ok,err=redis:connect(host,port[,options_table])
4、设置请求操作Redis的超时时间
redis:set_timeout(time)
5、close,关闭连接
关闭当前连接,成功返回1;
失败返回nil和错误信息;
ok,err = redis:close()
补充说明:
在lua-resty-redis中,所有的Redis命令都有自己的方法;方法名字和命令名字相同,只是全部为小写;
具体实现效果展示
在nginx.conf模块下,添加如下的location内容
location /redis { default_type "text/html"; content_by_lua_block { local redis = require "resty.redis" -- 引入 Redis local redisObj = redis:new() --创建Redis对象 redisObj:set_timeout(3000) --设置超时数据为3s local ok,err = redisObj:connect("IP",6379) --设置redis连接信息 if not ok then --判断是否连接成功 ngx.say("failed to connection redis",err) return end ok,err = redisObj:set("username","TOM") --存入 数据 if not ok then --判断是否存入成功 ngx.say("failed to set username",err) return end local res,err = redisObj:get("username") --从 redis中获取数据 ngx.say(res) --将数据写会消息体中 redisObj:close() } }
重启nginx,进行测试,直接在浏览器访问一下如下地址,可以看到数据成功写入到redis
MySQL是一个使用广泛的关系型数据库。在ngx_lua中,MySQL有两种访问模式,分别是
用ngx_lua模块和lua-resty-mysql模块: 这两个模块是安装OpenResty时默认安装的;
使用drizzle_nginx_module(HttpDrizzleModule)模块:需要单独
安装,这个库现不在OpenResty中
lua-resty-mysql
lua-resty-mysql是OpenResty开发的模块,使用灵活、功能强大,适合复杂的业务场景,同时支持存储过程访问;
lua-resty-mysql实现数据库查询
1、准备好mysql服务
2、提前创建一张表
CREATE TABLE `users` ( `id` int(10) NOT NULL AUTO_INCREMENT, `username` varchar(255) DEFAULT NULL, `birthday` date DEFAULT NULL, `salary` double(10,2) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
并提前准备几条数据
INSERT INTO `mydb`.`users` (`id`, `username`, `birthday`, `salary`) VALUES ('1', 'xiaowang', '1991-03-15', '9000.00'); INSERT INTO `mydb`.`users` (`id`, `username`, `birthday`, `salary`) VALUES ('2', 'xiaoma', '1992-07-15', '8000.00');
1、引入"resty.mysql"模块
local mysql = require "resty.mysql"
2、创建MySQL连接对象
遇到错误时,db为nil,err为错误描 述信息
db,err = mysql:new()
3、创建连接对象
ok,err=db:connect(options)
options是一个参数的 Lua表结构,里面包含数据库连接的相关信息
host:服务器主机名或IP地址
port:服务器监听端口,默认为3306
user:登录的用户名
password:登录密码
database:使用的数据库名
4、设置子请求的超时时间(ms)
包括connect方法
db:set_timeout(time)
5、关闭当前MySQL连接并返回状态
如果成功,则返回1;如果出现任 何错误,则将返回nil和错误描述
db:close()
6、异步向远程MySQL发送一个查询
如果成功则返回成功发送的字节 数;如果错误,则返回nil和错误描述
bytes,err=db:send_query(sql)
7、从MySQL服务器返回结果中读取一行数据
res返回一个描述OK包 或结果集包的Lua表
rows指定返回结果集的最大值,默认为4
如果是查询,则返回一个容纳多行的数组。每行是一个数据列的 key-value对
res, err, errcode, sqlstate = db:read_result() res, err, errcode, sqlstate = db:read_result(rows)
返回结果类似下面这样
{ {id=1,username="TOM",birthday="1988-11- 11",salary=10000.0}, {id=2,username="JERRY",birthday="1989-11- 11",salary=20000.0} }
如果是增删改,则返回类似如下数据
{ insert_id = 0, server_status=2, warning_count=1, affected_rows=2, message=nil }
返回值说明:
res:操作的结果集
err:错误信息
errcode:MySQL的错误码,比如1064
sqlstate:返回由5个字符组成的标准SQL错误码,比如 42000
具体操作案例
将下面的内容添加到server块,然后重启nginx
location /mysql { content_by_lua_block{ default_type "text/html"; local mysql = require "resty.mysql" local db = mysql:new() local ok,err = db:connect{ host="127.0.0.1", port=3306, user="root", password="123456", database="mydb" } db:set_timeout(3000) db:send_query("select * from users where id =1") local res,err,errcode,sqlstate = db:read_result() ngx.say(res[1].id..","..res[1].username..","..res[1]. birthday..","..res[1].salary) db:close() } }
可以看到,通过访问mysql这个路径,成功查询到数据库中ID为1的这条数据
使用cjson对查询结果进行格式化
从上面的返回结果来看,这种形式的返回数据在解析的时候其实并不是很友好,于是可以使用lua-cjson处理查询结果
使用步骤
步骤一:引入cjson
local cjson = require “cjson”
步骤二:调用cjson的encode方法进行类型转换
cjson.encode(res)
下面对上面程序模块做简单的改造
location /mysql-cjson { default_type "text/html"; content_by_lua_block{ local cjson = require "cjson" local mysql = require "resty.mysql" local db = mysql:new() local ok,err = db:connect{ host="127.0.0.1", port=3306, user="root", password="123456", database="mydb" } db:set_timeout(3000) db:send_query("select * from users") local res,err,errcode,sqlstate = db:read_result() ngx.say(cjson.encode(res)) for i,v in ipairs(res) do ngx.say(v.id..","..v.username..","..v.birthday..",".. v.salary) end db:close() } }
然后再次进行测试,这时候就以json的格式对数据进行了展现
增删改操作
location /mysql-cjson { default_type "text/html"; content_by_lua_block{ local cjson = require "cjson" local mysql = require "resty.mysql" local db = mysql:new() local ok,err = db:connect{ host="127.0.0.1", port=3306, user="root", password="123456", database="mydb" } db:set_timeout(3000) -- 查询操作 db:send_query("select * from users where id=1") -- 插入数据 --local res,err,errcode,sqlstate = db:query("insert into users(id,username,birthday,salary) values(3,'lifei','1995-10-17',3000)") -- 修改数据 --local res,err,errcode,sqlstate = db:query("update users set username='lisi' where id = 1") -- 删除数据 --local res,err,errcode,sqlstate = db:query("delete from users where id = 2") db:close() } }
以上がnginx と lua を統合して mysql を操作する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。