关注「WeiyiGeek」公众号

设为「特别关注」每天带你玩转网络安全运维、应用开发、物联网IOT学习!

希望各位看友【关注、点赞、评论、收藏、投币】,助力每一个梦想。


本章目录

目录

首发地址: https://mp.weixin.qq.com/s/u-zb-BxG6VyaLY4EQLKlOQ


0x0n 前言简述

为啥有此篇文章?

描述: 在进行公司的图片存储解决方案研究中,最开始准备使用的是FastDFS,但是经过深思熟虑,以及后期运维成本考虑还是放弃了,只能转而使用存储直接存放图片文件,直接请求效率提示杠杠的,但如何最大限度保证业务安全以及减少业务对数据库增删改查的压力? 在 Google 、Github一番查找后发现可以直接使用 Nginx + Lua 进行访问数据进行获取静态资源信息,而不用业务系统进行访问数据库直接获取静态资源路径,而显式的展现资源真实暴露给外部,非常容易被批量抓取。

其次笔者在实践中发现当前搜索到的安装部署Nginx+Lua可能已将不适用最新稳定版本的Nginx版本,基本上都是 1.15.x ~ 1.18.x,对于当前Nginx 1.22.0 版本来说显然是太老了。

所以本章就该问题进行 Nginx + Lua + Redis 模块环境的安装以及简单的实践,希望能帮助到各位有相同需求的Person。

基础知识:

  • Nginx: 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务, 其三大核心功能,包含静态资源、反向代理、api模块扩展,对于lua脚本的扩展,例如由lua-nginx-module模块,就是api模块扩展的一部分,并且nginx可以通过lua脚本直接调用redis服务器;
  • Lua: 是一种功能强大,高效,轻量级,可嵌入的脚本语言,非常容易嵌入到我们应用程序中, 它用于各种应用程序,从游戏到Web应用程序和图像处理。
  • lua-nginx-module : 该模块是 OpenResty 的核心组件,目录是将lua的功能嵌入到Nginx http服务器中。
  • lua-resty-redis : 该模块是在 OpenResty 项目下基于 cosocket API 的 ngx_lua 的 Lua redis 客户端驱动。

温馨提示: 如果不是现有业务大量使用Nginx进行承载不能直接替换其它优秀的解决方案,只能一步一步来,从而转入 OpenResty 或者 caddy 搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

原文地址: https://blog.weiyigeek.top


知识引入

Nginx 的指令的都是安装执行顺序的吗?

答: 既然我都这样问了答案则是显而易见的,这也是大多数新手频繁遇到的一个困惑,当然也困惑了笔者,否则我也不会这样问。

那我们下来来看这么一个示例: (验证此示例你可能需要先按照下一章的【0x01 部署环境】进行准备相关环境), 此时你可能会说输出不就是WeiyiGeek吗?

  1. location /sequence_demo_1 {
  2. set $a Weiyi;
  3. echo $a;
  4. set $a Geek;
  5. echo $a;
  6. }

但如果请求该URL你会发现实时并非如此。

  1. $ curl http://demo.weiyigeek.top/sequence_demo_1
  2. Geek
  3. Geek

那为什么出现了这种不合常理的现象呢?

答: 为了解释此现象, 我们不得不介绍Nginx的请求处理的11阶段,分别是post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、precontent、content以及log,其中3个比较常见的按照执行时的先后顺序依次是rewrite阶段、access阶段以及content阶段。

Nginx 配置指令一般只会注册并运行在其中的某一个处理阶段,比如 set 指令就是在rewrite阶段运行的,而echo指令只会在content阶段运行, 在一次请求处理流程中rewrite阶段总是在content阶段之前执行。

因此,属于rewrite阶段的配置指令(示例中的set)总是会无条件地在content阶段的配置指令(示例中的echo)之前执行,即便是echo指令出现在set指令的前面, 上面例子中的指令按照请求处理阶段的先后次序排序,实际的执行次序如下:

  1. location /sequence_demo_1 {
  2. # rewrite阶段的配置指令,执行在前面
  3. set $a Weiyi;
  4. set $a Geek ;
  5. # content阶段的配置指令,执行在后面
  6. echo $a;
  7. echo $a;
  8. }

所以,输出的结果就是Weiyi Geek了。

Lua模块指令阶段

各阶段使用Lua模块指令

描述: 由于本章 Nginx 也是使用 OpenResty Lua 模块实现的解析Lua脚本,所以其指令我们也需要做一个简单了解,对于后续学习有非常大的帮助。

指令语法: https://github.com/openresty/lua-nginx-module#synopsis

使用Lua来构建nginx脚本就是通过一条条指令来完成的,指令常用于指定 Lua 代码是什么时候执行的以及如何使用运行的结果,lua 指令分为配置指令、控制指令, 而控制指令分为两种方式。

  • lua脚本块 :*_by_lua_block
  • lua脚本文件 :*_by_lua_file

下图展示了指令执行的顺序:从上至下:初始化、重写/访问、内容处理、日志输出四个阶段

lua-nginx-module Directives Document(Lua Nginx 模块指令文档):

值得注意的是Nginx可以提前终止请求(至少),这意味着跳过正常运行的阶段,例如重写或访问阶段。这也意味着,不管运行的后期阶段(例如log_by_lua)将无法访问通常在这些阶段中设置的信息。

  1. 400 (Bad Request)
  2. 405 (Not Allowed)
  3. 408 (Request Timeout)
  4. 413 (Request Entity Too Large)
  5. 414 (Request URI Too Large)
  6. 494 (Request Headers Too Large)
  7. 499 (Client Closed Request)
  8. 500 (Internal Server Error)
  9. 501 (Not Implemented)

好了,此处就只是先简单点一下,在后续实践中您在回过头来看即可。


0x01 部署环境

安装说明

环境描述:

  1. # 系统信息
  2. $ cat /etc/issue.net
  3. Ubuntu 20.04.3 LTS
  4. $ uname -a
  5. Linux weiyigeek.top 5.4.0-92-generic \#103-Ubuntu SMP Fri Nov 26 16:13:00 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
  6. # 软件版本
  7. Nginx - 1.22.0 (stable 版本)
  8. pcre - 8.45
  9. zlib - 1.2.12
  10. Lua - 5.4
  11. openssl - 1.1.1q
  12. ngx_devel_kit - v0.3.1
  13. lua-nginx-module - v0.10.21
  14. echo-nginx-module - v0.62
  15. lua-resty-core - v0.1.23
  16. lua-resty-lrucache - v0.13
  17. lua-resty-redis - v0.29

温馨提示: 此处使用的是 Ubuntu 20.04 操作系统, 该系统已做安全加固和内核优化符合等保2.0要求【SecOpsDev/Ubuntu-InitializeSecurity.sh at master · WeiyiGeek/SecOpsDev 】, 如你的Linux未进行相应配置环境可能与读者有些许差异, 如需要进行(windows server、Ubuntu、CentOS)安全加固请参照如下加固脚本进行加固, 请大家疯狂的 star 。

加固脚本地址:【 https://github.com/WeiyiGeek/SecOpsDev/blob/master/OS-操作系统/Linux/Ubuntu/Ubuntu-InitializeSecurity.sh

为了节省大家的实践时间,我已经把需要用到的源码包上传到空间中,有需要的朋友可以看一下,下载地址: [http://share.weiyigeek.top/d/36158960-50338508-7c5982?p=2088](http://share.weiyigeek.top/d/36158960-50338508-7c5982?p=2088)(访问密码:2088)

温馨提示: 如提示证书不对,请点击高级继续访问即可.

安装部署

源代码编译构建

Step 1.在 Ubuntu 20.04 LTS 系统安装编译所需环境.

  1. apt install -y gcc g++ make perl net-tools

Step 2.下载 Nginx、PCRE、zlib、OpenSSL 源代码包,并编译构建 PCRE、zlib、OpenSSL.

  1. cd /usr/local/src
  2. # Nginx 轻量级的Web代理服务器。
  3. # 官网: https://nginx.org/en/download.html
  4. wget -c https://nginx.org/download/nginx-1.22.0.tar.gz -O /usr/local/src/nginx-1.22.0.tar.gz
  5. tar -zxf nginx-1.22.0.tar.gz
  6. # PCRE – 支持正则表达式,NGINX Core 和 Rewrite 模块需要
  7. # 官网: http://pcre.org/
  8. wget -c https://nchc.dl.sourceforge.net/project/pcre/pcre/8.45/pcre-8.45.tar.bz2
  9. tar -jxf pcre-8.45.tar.bz2 && cd pcre-8.45
  10. ./configure
  11. make && sudo make install
  12. # zlib – 支持标头压缩, NGINX Gzip 模块需要。
  13. # 官网:http://www.zlib.net/
  14. wget -c http://www.zlib.net/zlib-1.2.12.tar.gz
  15. tar -zxf zlib-1.2.12.tar.gz && cd zlib-1.2.12
  16. ./configure
  17. make && sudo make install
  18. # OpenSSL – 支持 HTTPS 协议, NGINX SSL 模块和其他模块需要。
  19. # 官网: https://www.openssl.org/source/
  20. wget -c https://www.openssl.org/source/openssl-1.1.1q.tar.gz
  21. tar -zxf openssl-1.1.1q.tar.gz && cd openssl-1.1.1q
  22. ./config --prefix=/usr/local/openssl
  23. make && sudo make install
  24. ln -s /usr/local/openssl/bin/openssl /usr/local/bin/openssl
  25. # lib 库加载到系统
  26. echo "/usr/local/openssl/lib" >> /etc/ld.so.conf.d/libc.conf
  27. ldconfig
  28. # 执行命令验证系统的 OpenSSL 版本
  29. /usr/local/bin/openssl version
  30. OpenSSL 1.1.1q 5 Jul 2022

温馨提示: 如./configure未指定--prefix参数的将会直接安装在/usr/local目录下的bin、lib、share等子目录中。

Step 3.下载编译构建Lua解析器以及Nginx所需的开发工具包和Lua模块。

  1. cd /usr/local/src
  2. # ngx_devel_kit - 是Nginx开发工具包,实际上可以看做一个Nginx模块,它添加了额外的通用工具,模块开发人员可以在自己的模块中使用这些工具。
  3. # 项目地址: https://github.com/simpl/ngx_devel_kit
  4. # 项目地址: https://github.com/vision5/ngx_devel_kit
  5. wget -c https://github.com/vision5/ngx_devel_kit/archive/refs/tags/v0.3.1.tar.gz -O ngx_devel_kit-v0.3.1.tar.gz
  6. tar -zxf ngx_devel_kit-v0.3.1.tar.gz && ls ngx_devel_kit-0.3.1
  7. # auto config docs examples LICENSE ngx_auto_lib_core notes objs patches README_AUTO_LIB.md README.md src
  8. # lua-nginx-module - 将Lua的强大功能嵌入到NGINX HTTP服务器中
  9. # 项目地址: https://github.com/openresty/lua-nginx-module
  10. wget -c https://github.com/openresty/lua-nginx-module/archive/refs/tags/v0.10.21.tar.gz -O /usr/local/src/lua-nginx-module-v0.10.21.tar.gz
  11. tar -zxf lua-nginx-module-v0.10.21.tar.gz && ls lua-nginx-module-0.10.21
  12. # config doc dtrace misc README.markdown src t tapset util valgrind.suppress
  13. # echo-nginx-module - 一个Nginx的输出模块,用于将“echo”、“sleep”、“time”等功能引入Nginx的配置文件, 此模块不随Nginx源一起分发。
  14. # 项目地址: https://github.com/openresty/echo-nginx-module
  15. wget --no-check-certificate -c https://github.com/openresty/echo-nginx-module/archive/refs/tags/v0.62.tar.gz -O /usr/local/src/echo-nginx-module-v0.62.tar.gz
  16. tar -zxf echo-nginx-module-v0.62.tar.gz && ls echo-nginx-module-0.62
  17. # config LICENSE README.markdown src t util valgrind.suppress
  18. # luajit2 - lua 解析器 LuaJIT 2 OpenResty 的分支,且注意解析器的Lua版本为5.1
  19. # 项目地址: https://github.com/openresty/luajit2
  20. wget -c https://github.com/openresty/luajit2/archive/refs/tags/v2.1-20220411.tar.gz -O /usr/local/src/luajit2-v2.1-20220411.tar.gz
  21. tar -zxvf luajit2-v2.1-20220411.tar.gz && cd luajit2-2.1-20220411
  22. make PREFIX=/usr/local/luajit && make install PREFIX=/usr/local/luajit
  23. ln -s /usr/local/luajit/bin/luajit /usr/local/bin/luajit
  24. # 链接库设置
  25. echo "/usr/local/luajit/lib" >> /etc/ld.so.conf.d/libc.conf
  26. ldconfig
  27. # 临时生效
  28. export LUAJIT_LIB=/usr/local/luajit/lib
  29. export LUAJIT_INC=/usr/local/luajit/include/luajit-2.1
  30. /usr/local/bin/luajit -v
  31. # LuaJIT 2.1.0-beta3 -- Copyright (C) 2005-2017 Mike Pall. http://luajit.org/

温馨提示: 上述 lua 解析器此处采用的是 LuaJIT 官方的 OpenResty 分支, 而不是 luajit 的主分支https://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz,后面入坑出坑会解释为啥这样做。

Step 4.为了使Nginx可以连接到redis数据库中执行一些列操作,此处借助于lua-nginx-module模块下载并解压所需的lua-resty-core、lua-resty-lrucache、lua-resty-redis。

  1. cd /usr/local/src
  2. # 基于 FFI 的 lua-nginx-module API
  3. # 项目地址: https://github.com/openresty/lua-resty-core
  4. wget -c https://github.com/openresty/lua-resty-core/archive/refs/tags/v0.1.23.tar.gz -O /usr/local/src/lua-resty-core.tar.gz
  5. tar -zxvf lua-resty-core.tar.gz && ls lua-resty-core-0.1.23
  6. # dist.ini lib Makefile README.markdown t valgrind.suppress
  7. # 基于 LuaJIT FFI 的 Lua-land LRU Cache
  8. # 项目地址: https://github.com/openresty/lua-resty-lrucache
  9. wget -c https://github.com/openresty/lua-resty-lrucache/archive/refs/tags/v0.13.tar.gz -O /usr/local/src/lua-resty-lrucache-v0.13.tar.gz
  10. tar -zxvf lua-resty-lrucache-v0.13.tar.gz && ls lua-resty-lrucache-0.13/
  11. # dist.ini lib Makefile README.markdown t valgrind.suppress
  12. # 基于 cosocket API 的 ngx_lua 的 Lua redis 客户端驱动
  13. # 项目地址: https://github.com/openresty/lua-resty-redis
  14. wget -c https://github.com/openresty/lua-resty-redis/archive/refs/tags/v0.29.tar.gz -O /usr/local/src/lua-resty-redis-v0.29.tar.gz
  15. tar -zxvf lua-resty-redis-v0.29.tar.gz && ls lua-resty-redis-0.29/
  16. # 在使用时可将lua脚本放入到nginx配置目录中。
  17. mkdir -vp /usr/local/nginx/lua/
  18. cp -a /usr/local/src/lua-resty-redis-0.29/lib /usr/local/nginx/lua/
  19. # 以树形结构显示该目录
  20. $ tree /usr/local/nginx/lua/
  21. /usr/local/nginx/lua/
  22. ├── hello.lua
  23. └── lib
  24. └── resty
  25. └── redis.lua

Step 5.在上面步骤操作完毕之后,我们便可以进行nginx编译安装了,构建流程如下(在博主的前面讲解的Nginx系列教程就已经有详细讲述 【[Nginx进阶学习之最佳配置实践指南][https://blog.weiyigeek.top/2019/9-1-124.html]】,此处就不在大篇幅累述了):

  1. # 创建允许用户和组,不需要家目录不登录bash
  2. useradd -M -s /sbin/nologin nginx
  3. # 创建 Nginx 所需目录
  4. sudo mkdir -vp /usr/local/nginx/{module,modules,lua} /var/cache/nginx/{client_temp,proxy_temp,fastcgi_temp,uwsgi_temp,scgi_temp}
  5. cd /usr/local/src/nginx-1.22.0
  6. # Nginx 预编译参数设置
  7. ./configure \
  8. --prefix=/usr/local/nginx \
  9. --user=nginx --group=nginx \
  10. --with-pcre=../pcre-8.45 \
  11. --with-zlib=../zlib-1.2.12 \
  12. --with-openssl=../openssl-1.1.1q \
  13. --sbin-path=/usr/sbin/nginx \
  14. --conf-path=/usr/local/nginx/nginx.conf \
  15. --pid-path=/usr/local/nginx/nginx.pid \
  16. --error-log-path=/var/log/nginx/error.log \
  17. --http-log-path=/var/log/nginx/access.log \
  18. --lock-path=/var/run/nginx.lock \
  19. --modules-path=/usr/local/nginx/modules \
  20. --http-client-body-temp-path=/var/cache/nginx/client_temp \
  21. --http-proxy-temp-path=/var/cache/nginx/proxy_temp \
  22. --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
  23. --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
  24. --http-scgi-temp-path=/var/cache/nginx/scgi_temp \
  25. --with-threads \
  26. --with-http_sub_module --with-http_v2_module \
  27. --with-http_auth_request_module --with-http_realip_module --with-http_secure_link_module \
  28. --with-http_gunzip_module --with-http_gzip_static_module --with-http_ssl_module \
  29. --with-http_slice_module --with-http_stub_status_module \
  30. --with-http_dav_module --with-http_flv_module --with-http_mp4_module \
  31. --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-stream_geoip_module \
  32. --with-mail --with-mail_ssl_module \
  33. --with-http_addition_module --with-http_random_index_module \
  34. --with-compat --with-file-aio \
  35. --with-cc-opt='-Os -fomit-frame-pointer -g' \
  36. --with-ld-opt='-Wl,-rpath,/usr/local/luajit/lib,--as-needed,-O1,--sort-common' \
  37. --add-module=/usr/local/src/ngx_devel_kit-0.3.1 \
  38. --add-module=/usr/local/src/lua-nginx-module-0.10.21 \
  39. --add-dynamic-module=/usr/local/src/echo-nginx-module-0.62 \
  40. # 编译构建安装
  41. make & make install

温馨提示: 上述 ./configure 编译配置中使用静态链接库方式来添加ngx_devel_kit-0.3.1/lua-nginx-module-0.10.21 模块, 又为了演示加入动态链接库的使用方式,此处使用--add-dynamic-module参数指定echo-nginx-module-0.62的解压目录,如果使用动态连接库的方式加载模块将会在后续实践中展示。

构建结果:

  1. # configure 结果
  2. Configuration summary
  3. # + using threads
  4. # + using PCRE library: ../pcre-8.45
  5. # + using OpenSSL library: ../openssl-1.1.1q
  6. # + using zlib library: ../zlib-1.2.12
  7. # nginx path prefix: "/usr/local/nginx"
  8. # ....................................
  9. # nginx http scgi temporary files: "/var/cache/nginx/scgi_temp"
  10. # Make 构建安装后提示lib动态链接库地址。
  11. - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable during execution
  12. - add LIBDIR to the 'LD_RUN_PATH' environment variable during linking
  13. - use the '-Wl,-rpath -Wl,LIBDIR' linker flag # 或者在编译是添加依赖的Lib目录。
  14. - have your system administrator add LIBDIR to '/etc/ld.so.conf'
  15. /usr/local/src/nginx-1.22.0# ls objs/
  16. # ls objs/
  17. # addon ngx_auto_config.h
  18. # autoconf.err ngx_auto_headers.h
  19. # Makefile ngx_http_echo_module_modules.c
  20. # nginx ngx_http_echo_module_modules.o
  21. # ngx_modules.c src
  22. # nginx.8 ngx_http_echo_module.so ngx_modules.o

Step 6.在Nginx安装部署成功后,为了验证Nginx + Lua安装环境,我们需要再 nginx 主配置文件入口配置如下关键内容,注意下面带有文字注释部分。

  1. $ grep -v "^#|^$|#" /usr/local/nginx/conf.d/nginx.conf
  2. worker_processes 1;
  3. events {
  4. worker_connections 1024;
  5. }
  6. http {
  7. include mime.types;
  8. default_type application/octet-stream;
  9. # 去除 log_format 前者的注释符 `#`
  10. log_format main '$remote_addr - $remote_user [$time_local] "$request" '
  11. '$status $body_bytes_sent "$http_referer" '
  12. '"$http_user_agent" "$http_x_forwarded_for"';
  13. sendfile on;
  14. keepalive_timeout 65;
  15. # lua 包模块依赖路径
  16. lua_package_path '/usr/local/src/lua-resty-core-0.1.23/lib/?.lua;/usr/local/src/lua-resty-lrucache-0.13/lib/?.lua;';
  17. ...
  18. # 添加加载nginx家目录下的conf.d/目录子配置文件 (通配符)
  19. include conf.d/*.conf;
  20. }

然后再创建子配置目录与demo.weiyigeek.top站点配置demo.conf文件中,添加如下server字段内容片段。

  1. mkdir /usr/local/nginx/conf.d
  2. tee /usr/local/nginx/conf.d/demo.conf <<'EOF'
  3. # https - demo.weiyigeek.top
  4. server {
  5. listen 80;
  6. server_name demo.weiyigeek.top;
  7. charset utf-8;
  8. access_log /var/log/nginx/demo-access.log main buffer=128k flush=1m;
  9. # 方式1.content_by_lua_block lua 片段
  10. location /hello-lua {
  11. default_type 'text/plain';
  12. content_by_lua_block {
  13. ngx.say("Hello World! Lua & Nginx .")
  14. }
  15. }
  16. # 方式2.content_by_lua_file lua 脚本文件路径
  17. location /hello-lua-file {
  18. default_type 'text/html';
  19. content_by_lua_file ./lua/hello.lua;
  20. }
  21. # 方式3.access_by_lua 在请求访问阶段处理用于访问控制。
  22. location /hello-lua-access {
  23. default_type 'text/html';
  24. access_by_lua '
  25. local message = "403 - Hello World! Lua & Nginx access_by_lua"
  26. ngx.say(message)
  27. ';
  28. }
  29. # 方式4.content_by_lua 在内容处理阶段接受请求并输出响应。
  30. location /hello-lua-content {
  31. default_type 'text/html';
  32. content_by_lua "ngx.print('Hello World!')";
  33. }
  34. }
  35. EOF

温馨提示:access_by_lua content_by_lua 的区别是对于Nginx请求的不同处理阶段,前者是访问阶段处理用于访问控制(适用于http、server、location、location if),后者内容处理器接受请求并输出响应,适用于location、location if

Step 7.上述配置完成后为了验证配置文件是否存在问题,可执行如下命令如果显示 successful 表示配置没有问题,之后就可重载 nginx 服务。

  1. $ nginx -t
  2. # nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
  3. # nginx: configuration file /usr/local/nginx/nginx.conf test is successful
  4. $ /usr/sbin/nginx -s reload
  5. $ ps -ef | grep "nginx"
  6. # root 244962 1 0 16:40 ? 00:00:00 nginx: master process nginx
  7. # nginx 245707 244962 0 21:42 ? 00:00:00 nginx: worker process
  8. # root 245710 245523 0 21:42 pts/0 00:00:00 grep nginx

Step 8.验证基本的Nginx+Lua环境,我们访问上述配置文件中的域名和子目录,访问结果如下图所示则表示环境OK,否则请排查错误或者查看是否存在下述的入坑出坑中相关问题。

  1. curl -H "host:demo.weiyigeek.top" 10.20.172.201/hello-lua
  2. Hello World! Lua & Nginx .
  3. curl -H "host:demo.weiyigeek.top" 10.20.172.201/hello-lua-file
  4. <h2> Hello world! Lua & Nginx with Hello.lua. </h2>
  5. curl -H "host:demo.weiyigeek.top" 10.20.172.201/hello-lua-access
  6. Hello World! Lua & Nginx access_by_lua
  7. curl -H "host:demo.weiyigeek.top" 10.20.172.201/hello-lua-content
  8. Hello World!

知识扩展: 编译构建nginx后我们可通过nginx -V命令查看曾经./configure预编译参数的设置。

  1. $ nginx -V
  2. nginx version: nginx/1.22.0
  3. built by gcc 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
  4. built with OpenSSL 1.1.1q 5 Jul 2022
  5. TLS SNI support enabled
  6. configure arguments: --prefix=/usr/local/nginx
  7. ....
  8. --add-module=/usr/local/src/lua-nginx-module-0.10.21 --add-dynamic-module=/usr/local/src/echo-nginx-module-0.62 -

0x02 使用实践

1.Nginx 实践使用 echo-nginx-module 模块之动态加载链接库

描述: 从 NGINX 1.9.11 开始,您还可以将此模块编译为动态模块,方法是在上面的 ./configure 命令行中使用 --add-dynamic-module=PATH 选项而不是--add-module=PATH选项,然后你可以通过 load_module 指令在你的 nginx.conf 中显式加载模块,注意必须在 events{} 片段之前.

模块语法: https://github.com/openresty/echo-nginx-module#synopsis

Step 1.在Nginx.conf文件中配置load_module指令以动态加载 echo-nginx-module 模块。

  1. # 方式1.绝对路径
  2. load_module /usr/local/nginx/modules/ngx_http_echo_module.so;
  3. # 方式2.相对路径
  4. load_module ./modules/ngx_http_echo_module.so;
  5. .....
  6. events {
  7. worker_connections 1024;
  8. }

Step 2.同样在demo.conf文件中的进行该模块常规的使用实践。

  1. $ cat conf.d/demo.conf
  2. server {
  3. ...
  4. # 示例1.常规输出(注意文本类型则网页中反馈展现数据也不相同)。
  5. location /nginx-module/echo {
  6. default_type 'text/html';
  7. echo -n "<b>Domain: demo.weiyigeek.top</b> <br/>";
  8. echo "Hello World! by ngx_http_echo_module.so";
  9. }
  10. # 示例2.请求延时显示以及重置时间定时器。
  11. location /nginx-module/timed {
  12. default_type 'text/plain';
  13. echo "Hello World! by ngx_http_echo_module.so \r";
  14. echo_reset_timer;
  15. echo "1.takes about $echo_timer_elapsed sec \r";
  16. echo_flush;
  17. echo_sleep 2.5; # in sec
  18. echo "2.takes about $echo_timer_elapsed sec.";
  19. echo "End";
  20. }
  21. # 示例3.Body文档前后插入数据以及在中部插嵌入反向代理网站源码。
  22. location /nginx-module/body {
  23. resolver 223.6.6.6;
  24. default_type 'text/html';
  25. echo "Hello World! by ngx_http_echo_module.so";
  26. echo_before_body 'Blog - ';
  27. proxy_pass $scheme://www.weiyigeek.top:$server_port/index.html;
  28. echo_before_body 'www.WeiyiGeek.top';
  29. echo_after_body '[END]';
  30. }
  31. # 示例4.多次输出同一个字符串以及显示客户端请求header与请求body主体参数
  32. location /nginx-module/duplicate {
  33. default_type 'text/plain';
  34. echo_duplicate 3 "--";
  35. echo_duplicate 1 "\rHello World! by ngx_http_echo_module.so \r\r";
  36. # echo_duplicate 1000_000 "Hello World! by ngx_http_echo_module.so";
  37. echo "\r";
  38. echo_duplicate 1 $echo_client_request_headers;
  39. echo "\r";
  40. echo_read_request_body;
  41. echo "\r";
  42. echo_request_body;
  43. echo_duplicate 3 "--";
  44. echo;
  45. }
  46. # 示例5.正则匹配请求参数,注意`$arg_var`后面的var是可以自定义设置,此处为flag参数。
  47. location ^~ /nginx-module/if {
  48. default_type 'text/plain';
  49. set $res default;
  50. echo $arg_flag;
  51. if ($arg_flag ~* '^a') {
  52. set $res change;
  53. echo $arg_flag, $res;
  54. }
  55. echo $res;
  56. }
  57. ....
  58. }

补充 echo_subrequest_async 异步请求

描述: 使用 HTTP 方法、可选的 url 参数(或查询字符串)和可选的请求主体发起异步子请求,请求主体可以定义为字符串或包含主体的文件的路径。

  1. # GET /multi will yields
  2. # querystring: foo=Foo
  3. # method: POST
  4. # body: hi
  5. # content length: 2
  6. # ///
  7. # querystring: bar=Bar
  8. # method: PUT
  9. # body: hello
  10. # content length: 5
  11. # ///
  12. location /multi {
  13. echo_subrequest_async POST '/sub' -q 'foo=Foo' -b 'hi';
  14. echo_subrequest_async PUT '/sub' -q 'bar=Bar' -b 'hello';
  15. }
  16. location /sub {
  17. echo "querystring: $query_string";
  18. echo "method: $echo_request_method";
  19. echo "body: $echo_request_body";
  20. echo "content length: $http_content_length";
  21. echo '///';
  22. }

Step 3.完成配置后重载nginx服务, 通过浏览器访问上述路径验证模块使用与输出,效果如下图所示:

该模块的其它使用请参考其项目地址Readme文档,此处演示了如何加载动态链接库到nginx,并且使用链接库中的模块。

2.Nginx 实践使用 lua-resty-redis 模块连接 Redis 进行数据操作与展示

描述: 前面环境部署中已下载 ngx_lua_nginx 模块的 Redis 客户端驱动程序Lua库, 下面将演示如何在 Nginx 基于 ngx_lua_nginx 模块连接到Redis内存数据库进行相应数据查找,好了本小节就直奔主题。

语法参考: https://github.com/openresty/lua-resty-redis#synopsis

废话不多说,实践出真知

Step 1.在前面环境安装中我们解压在 ngx_lua_nginx 模块使用 Redis 客户端驱动程序Lua库,并将其 Lib 目录复制到 /usr/local/nginx/lua/ 目录中,其次我也准备了Redis数据库环境,针对安装部署步骤就不在详述了, 想要快速安装的朋友可以参考我的此篇文章【[Redis内存数据库环境快速搭建部署][https://blog.weiyigeek.top/2022/4-24-653.html]】。

  1. $ tree /usr/local/nginx/lua/lib/
  2. /usr/local/nginx/lua/lib/
  3. └── resty
  4. └── redis.lua
  5. # Redis 数据库 & 为了演示数据准备两个Key即domain/blog
  6. 192.168.1.22 6379 weiyigeek.top
  7. /data # redis-cli
  8. 127.0.0.1:6379> auth weiyigeek.top
  9. OK
  10. 127.0.0.1:6379> ping
  11. PONG
  12. 127.0.0.1:6379> set domain www.weiyigeek.top
  13. OK
  14. 127.0.0.1:6379> set blog blog.weiyigeek.top
  15. OK

Step 2.想要在Nginx使用该redis.lua链接到数据库,首先我们需要在nginx.conf配置文件中加入该lua包路径/usr/local/nginx/lua/lib/,例如:

  1. $ grep "lua_package_path" /usr/local/nginx/nginx.conf
  2. lua_package_path '/usr/local/nginx/lua/lib/?.lua;/usr/local/src/lua-resty-core-0.1.23/lib/?.lua;/usr/local/src/lua-resty-lrucache-0.13/lib/?.lua;'

Step 3.此处也是在 demo.conf 中进行配置使用Redis客户端驱动程序Lua库,连接到Redis数据库中, 此处为了方便演示就直接在该配置文件content_by_lua_block 代码块中使用lua语法,在企业生产实践环境中一定要将其写入到lua文件文件中。

  1. # /usr/local/nginx/conf.d/demo.conf
  2. server {
  3. ...
  4. location /redis/get {
  5. default_type 'text/html';
  6. set $key $arg_key;
  7. content_by_lua_block {
  8. -- # 引入resty.redis模块与创建实例化对象
  9. local redis = require "resty.redis"
  10. local client = redis:new()
  11. local REDIS_HOST = "192.168.1.22"
  12. local REDIS_PROT = 6379
  13. local REDIS_AUTH = "weiyigeek.top"
  14. -- # ngx.log(ngx.ERR, ngx.var.key)
  15. -- # 分别设置连接、发送和读取超时阈值(以毫秒为单位),用于后续套接字操作。
  16. client:set_timeouts(1000, 1000, 1000)
  17. -- # 创建链接对象, 连接到Redis数据库
  18. ngx.say("1.connect redis server..... <br>");
  19. local ok, err = client:connect(REDIS_HOST, REDIS_PROT)
  20. if not ok then
  21. ngx.say("failed to connect: ", err)
  22. return
  23. end
  24. -- # 认证
  25. ngx.say("2.auth redis server..... <br>");
  26. local res, err = client:auth(REDIS_AUTH)
  27. if not res then
  28. ngx.say("failed to authenticate: ", err)
  29. return
  30. end
  31. -- # 获取指定请求键值
  32. ngx.say("3.get custom KV for redis server, Key = ",ngx.var.key," <br>");
  33. local res, err = client:get(ngx.var.key)
  34. if not res then
  35. ngx.say("failed to get key: ", err)
  36. return
  37. end
  38. if res == ngx.null then
  39. ngx.say("key not found.")
  40. return
  41. end
  42. -- # 输出结果
  43. ngx.say("<b style='color:red'>4.result value: ",res,"</b><br/>")
  44. -- # 使用完毕后立即关闭销毁Redis连接(短连接可以如此使用,如果是长链接建议回收该连接池对象即可)
  45. local ok, err = client:close()
  46. if not ok then
  47. ngx.say("failed to close: ", err)
  48. return
  49. else
  50. ngx.say("5.just close the Redis connection right away <br/>")
  51. end
  52. }
  53. }
  54. ...
  55. }

Step 5.在演示一个示例,我们可以一次性执行多个redis操作命令 lua-resty-redis 库支持pipeline提交,下面我们演示使用 content_by_lua_file 关键字指定连接操作redis的lua脚本地址(/usr/local/nginx/lua/custom/nginx-redis.lua)实践, 该方式在线上环境中推荐使用。

  1. # 1) 操作 redis 数据库的 lua 脚本示例。
  2. tee /usr/local/nginx/lua/custom/nginx-redis.lua <<'EOF'
  3. -- # 引入resty.redis模块与创建实例化对象
  4. local redis = require "resty.redis"
  5. local client = redis:new()
  6. local REDIS_HOST = "192.168.1.22"
  7. local REDIS_PROT = 6379
  8. local REDIS_AUTH = "weiyigeek.top"
  9. -- # ngx.log(ngx.ERR, ngx.var.key)
  10. -- # 分别设置连接、发送和读取超时阈值(以毫秒为单位),用于后续套接字操作。
  11. client:set_timeouts(1000, 1000, 1000)
  12. -- # 验证请求的参数是否存在
  13. if (ngx.var.key == ngx.null and ngx.var.value == ngx.null)
  14. then
  15. ngx.say("Request parameters : key + value not found!")
  16. ngx.exit(404)
  17. end
  18. -- # 创建链接对象, 连接到Redis数据库
  19. ngx.say("1.connect redis server..... <br>");
  20. local ok, err = client:connect(REDIS_HOST, REDIS_PROT)
  21. if not ok then
  22. ngx.say("failed to connect: ", err)
  23. return
  24. end
  25. -- # 认证
  26. ngx.say("2.auth redis server..... <br>");
  27. local res, err = client:auth(REDIS_AUTH)
  28. if not res then
  29. ngx.say("failed to authenticate: ", err)
  30. return
  31. end
  32. -- # 使用 pipeline 通道方式进行redis 数据库操作
  33. client:init_pipeline()
  34. client:set(ngx.var.key, ngx.var.value)
  35. client:get(ngx.var.key)
  36. client:get("domain")
  37. local results, err = client:commit_pipeline()
  38. if not results then
  39. ngx.say("failed to commit the pipelined requests: ", err)
  40. return
  41. end
  42. -- 结果遍历
  43. for i, res in ipairs(results) do
  44. if type(res) == "table" then
  45. if res[1] == false then
  46. ngx.say("failed to run command ", i, ": ", res[2],"<br/>")
  47. else
  48. -- process the table value
  49. ngx.say("3) 3.",i, ": ", res[2],"<br/>")
  50. end
  51. else
  52. -- process the scalar value
  53. ngx.say("<p style='color:red'>3) ",i,"---",res,"</p>")
  54. end
  55. end
  56. -- 将当前 Redis 连接立即放入 ngx_lua cosocket 连接池(将其放入大小为100的连接池中,最大空闲时间为10秒)。
  57. local ok, err = client:set_keepalive(10000, 100)
  58. if not ok then
  59. ngx.say("failed to set keepalive: ", err)
  60. return
  61. end
  62. ngx.say("4.将当前 Redis 连接立即放入 ngx_lua cosocket 连接池<br/>")
  63. EOF
  64. # 2) 配置 demo.conf 文件 同样在 server 片段中加入如下 location 片段。
  65. server {
  66. ....
  67. location /redis/pipeline {
  68. default_type 'text/html';
  69. # 获取请求参数中key的值与value的值并存放到nginx环境变量中
  70. set $key $arg_key;
  71. set $value $arg_value;
  72. # 调用并执行指定的lua脚本
  73. content_by_lua_file ./lua/custom/nginx-redis.lua;
  74. }
  75. ....
  76. }

在配置完成后我们便可以重载nginx,并使用访问浏览器访问上述路径,例如: http://demo.weiyigeek.top/redis/pipeline?key=name&value=WeiyiGeek,此处我演示的结果如下图所示。

3.Nginx 实践读取Redis数据库中图片绑定对应键值并进行图片展示

描述: 假如在这样一个场景中,为了避免恶意用户遍历有规律的图片进行下载,那如何解决这个问题呢?

方法是有得但也不限于本节实践的案例,此处我们可以将其图片名称或者图片md5值存入到Redis数据库中作为Key,而实际的图片路径作为Value,在请求时我们将该md5值作为参数进行传入,经过 Nginx 对请求参数的处理,使用前面的方式在 Lua 脚本中连接Redis,并将URL传递的md5参数作为key进行get查询,并将查询到的图片路径,反馈给set指令设置的变量之中,然后我们便可以通过 proxy_pass 进行代理访问(地址栏中的url不会变化,保证实际的图片路径),或者也可以加上一个头Content-Disposition直接进行图片下载。

不在多说废话了,只有实践才是王道。

实践流程:

  • Step 1.准备一个图片目录以及放入几张图片进行演示,此处你可以使用图片名称md5也可使用图形文件本身md5效验值。
  1. $ tree /usr/local/nginx/html/
  2. /usr/local/nginx/html/
  3. ├── 50x.html
  4. ├── images
  5.    ├── 1562941454569.jpeg
  6.    ├── 1562941454570.jpeg
  7.    └── 1562941454571.png
  8. └── index.html
  9. # 文件的MD5值
  10. /usr/local/nginx/html/images# md5sum * | awk '{print "set "$1" "$2}'
  11. set 6fad4c2466dc7f61fb055021ec65324d 1562941454569.jpeg
  12. set 611877180883388de4752ded33a81165 1562941454570.jpeg
  13. set 6636d52bfbe068177df5219edf4dd456 1562941454571.png
  14. # 写入KV到redis数据库中
  15. 127.0.0.1:6379> set 6fad4c2466dc7f61fb055021ec65324d 1562941454569.jpeg
  16. OK
  17. 127.0.0.1:6379> set 611877180883388de4752ded33a81165 1562941454570.jpeg
  18. OK
  19. 127.0.0.1:6379> set 6636d52bfbe068177df5219edf4dd456 1562941454571.png
  20. OK
  • Step 2.在demo.conf文件中的server片段中增加 location 片段,其中进行如下配置:
  1. $ vim conf.d/demo.conf
  2. server {
  3. ......
  4. location = /api/v2/images/get {
  5. resolver 223.6.6.6;
  6. set $key $arg_md5sum;
  7. set $name "";
  8. access_by_lua_block {
  9. local redis = require "resty.redis"
  10. local client = redis:new()
  11. local REDIS_HOST = "192.168.1.22"
  12. local REDIS_PROT = 6379
  13. local REDIS_AUTH = "weiyigeek.top"
  14. client:set_timeouts(1000, 1000, 1000)
  15. local ok, err = client:connect(REDIS_HOST, REDIS_PROT)
  16. if not ok then
  17. ngx.say("failed to connect: ", err)
  18. return
  19. end
  20. local res, err = client:auth(REDIS_AUTH)
  21. if not res then
  22. ngx.say("failed to authenticate: ", err)
  23. return
  24. end
  25. local res, err = client:get(ngx.var.key)
  26. if not res then
  27. ngx.say("failed to get key: ", err)
  28. return
  29. end
  30. if res == ngx.null then
  31. ngx.say("key not found.")
  32. return
  33. else
  34. -- # 关键点将redis中指定键的值赋予给nginx指定变量
  35. ngx.var.name = res
  36. end
  37. local ok, err = client:set_keepalive(10000, 100)
  38. if not ok then
  39. ngx.say("failed to set keepalive: ", err)
  40. return
  41. end
  42. }
  43. proxy_pass $scheme://$server_name/images/$name;
  44. }
  45. ......
  46. }

在配置完成后我们重载 Nginx,然后利用浏览器进行访问如上URL,例如http://demo.weiyigeek.top/api/v2/images/get?md5sum=6636d52bfbe068177df5219edf4dd456,执行结果如下所示:

  • Step 3.如果我们想通过浏览器访问上述地址就直接弹出源文件名称进行下载的,我们则可以在 proxy_pass 片段后加上如下 header 头: add_header Content-Disposition "attachment;filename=$name";
  1. ...
  2. proxy_pass $scheme://$server_name/images/$name;
  3. add_header Content-Disposition "attachment;filename=$name";
  4. ...
  5. # 重载Nginx后利用CURL访问该URL
  6. $ curl -I http://demo.weiyigeek.top/api/v2/images/get?md5sum=6636d52bfbe068177df5219edf4dd456
  7. HTTP/1.1 200 OK
  8. Server: nginx/1.22.0
  9. Date: Tue, 02 Aug 2022 02:23:12 GMT
  10. Content-Type: image/png
  11. Content-Length: 32641
  12. Connection: keep-alive
  13. Last-Modified: Wed, 23 Mar 2022 00:48:26 GMT
  14. ETag: "623a6e5a-7f81"
  15. Accept-Ranges: bytes
  16. Content-Disposition: attachment;filename=1562941454571.png

  • Step 4.当然,你也可使用rewrite_by_lua_block代码块包含Lua可直接或者图片路径,然后使用ngx.redirect()方法进行跳转。
  1. $ vim conf.d/demo.conf
  2. server {
  3. ......
  4. location = /api/v1/images/get {
  5. resolver 223.6.6.6;
  6. set $key $arg_md5sum;
  7. rewrite_by_lua_block {
  8. local redis = require "resty.redis"
  9. local client = redis:new()
  10. local REDIS_HOST = "192.168.1.22"
  11. local REDIS_PROT = 6379
  12. local REDIS_AUTH = "weiyigeek.top"
  13. client:set_timeouts(1000, 1000, 1000)
  14. local ok, err = client:connect(REDIS_HOST, REDIS_PROT)
  15. if not ok then
  16. ngx.say("failed to connect: ", err)
  17. return
  18. end
  19. local res, err = client:auth(REDIS_AUTH)
  20. if not res then
  21. ngx.say("failed to authenticate: ", err)
  22. return
  23. end
  24. local res, err = client:get(ngx.var.key)
  25. if not res then
  26. ngx.say("failed to get key: ", err)
  27. return
  28. end
  29. if res == ngx.null then
  30. ngx.say("key not found.")
  31. else
  32. -- # 关键点图片格式化。
  33. return ngx.redirect(string.format("%s%s","/images/",res))
  34. end
  35. local ok, err = client:set_keepalive(10000, 100)
  36. if not ok then
  37. ngx.say("failed to set keepalive: ", err)
  38. return
  39. end
  40. }
  41. # 若没有匹配搭配到进行跳转进行跳转则访问首页
  42. proxy_pass $scheme://$server_name/index.html;
  43. }
  44. ......
  45. }

好了,本章实践就到此处了,更多的奇技淫巧尽在 [weiyigeek] 公众号.


0x03 扩展补充

示例1.使用 ngx.location.capture() 请求内部接口

  1. location = /auth {
  2. internal;
  3. retur 200 '{"status":"$auth_status"}'
  4. }
  5. # 此处根据业务的需求来写正则表达式,一定要个 redis 里的 KEY 对应上
  6. location ~/[0-9].*\.(gif|jpg|jpeg|png)$ {
  7. set $target '';
  8. access_by_lua '
  9. # 使用 nginx 的内部参数 ngx.var.uri 来获取请求的 uri 地址,如 /000001.jpg
  10. local key = ngx.var.uri
  11. # 根据正则匹配到 KEY ,从 redis 数据库里获取文件 ID (路径和文件名)
  12. local res = ngx.location.capture(
  13. "/Redis", { args = { key = key } }
  14. )
  15. if res.status ~= 200 then
  16. ngx.log(ngx.ERR, "Redis server returned bad status: ",res.status)
  17. ngx.exit(res.status)
  18. end
  19. if not res.body then
  20. ngx.log(ngx.ERR, "Redis returned empty body")
  21. ngx.exit(500)
  22. end
  23. local parser = require "Redis.parser"
  24. local filename, typ = parser.parse_reply(res.body)
  25. if typ ~= parser.BULK_REPLY or not server then
  26. ngx.log(ngx.ERR, "bad Redis response: ", res.body)
  27. ngx.exit(500)
  28. end
  29. ngx.var.target = filename
  30. ';
  31. proxy_pass http://10.20.172.196/$target;
  32. }

0x0n 入坑出坑

问题1. 当编译 Nginx 时报checking for LuaJIT 2.x ... not found, ./configure: error: unsupported LuaJIT version; ngx_http_lua_module requires LuaJIT 2.x. 错误时的解决办法。

问题描述: tell nginx's build system where to find LuaJIT 2.1

解决办法:

  1. # 临时生效
  2. export LUAJIT_LIB=/usr/local/luajit/lib
  3. export LUAJIT_INC=/usr/local/luajit/include/luajit-2.1
  4. # 永久生效
  5. tee -a /etc/profile <<'EOF'
  6. export LUAJIT_LIB=/usr/local/luajit/lib
  7. export LUAJIT_INC=/usr/local/luajit/include/luajit-2.1
  8. EOF
  9. source /etc/profile

问题2.在使用luajit官方主分支LuaJIT-2.1.0-beta3提供LuaJIT安装部署出现nginx: [alert] detected a LuaJIT version which is not OpenResty's;以及nginx: [alert] failed to load the 'resty.core' module警告。

错误信息:

  1. $ /usr/sbin/nginx
  2. nginx: [alert] detected a LuaJIT version which is not OpenResty's; many optimizations will be disabled and performance will be compromised (see https://github.com/openresty/luajit2 for OpenResty's LuaJIT or, even better, consider using the OpenResty releases from https://openresty.org/en/download.html)
  3. nginx: [alert] failed to load the 'resty.core' module (https://github.com/openresty/lua-resty-core); ensure you are using an OpenResty release from https://openresty.org/en/download.html (reason: module 'resty.core' not found:
  4. no field package.preload['resty.core']
  5. no file './resty/core.lua'
  6. no file '/usr/local/share/luajit-2.1.0-beta3/resty/core.lua'
  7. no file '/usr/local/share/lua/5.1/resty/core.lua'
  8. no file '/usr/local/share/lua/5.1/resty/core/init.lua'
  9. no file './resty/core.so'
  10. no file '/usr/local/lib/lua/5.1/resty/core.so'
  11. no file '/usr/local/lib/lua/5.1/loadall.so'
  12. no file './resty.so'
  13. no file '/usr/local/lib/lua/5.1/resty.so'
  14. no file '/usr/local/lib/lua/5.1/loadall.so') in /usr/local/nginx/nginx.conf:117

问题原因1: 提示LuaJIT的版本不匹配OpenResty's内核版本, 让我不要用这个luajit版本,可以用openresty提供的luajit优化版本,或者干脆直接用openresty,下面将安装卸载luajit官网版本,下载openresty提供的luajit优化版本(即上面环境安装已经实践了,按照上面版本进行安装一般不会存在该问题)。

  1. # 你可能会进行 Lua 脚本解释器的安装 LuaJIT
  2. http://luajit.org/download.html
  3. wget -c https://luajit.org/download/LuaJIT-2.1.0-beta3.tar.gz
  4. tar -zxf LuaJIT-2.1.0-beta3.tar.gz && cd LuaJIT-2.1.0-beta3
  5. make && make install
  6. ln -sf /usr/local/bin/luajit-2.1.0-beta3 /usr/local/bin/luajit
  7. # 卸载LuaJIT官网主分支版本,然后重新安装openresty提供的luajit优化版即可
  8. make uninstall
  9. make clean

问题原因2: 提示加载'resty.core'模块失败,其解决办法,按照https://github.com/openresty/lua-nginx-module/issues/1509上面所说, 安装lua-resty-core和依赖文件lua-resty-lrucache解决问题,即我前面实践中已经进行此部分操作,若不会操作请上翻到 【安装部署】标题进行查看。

原文地址: https://blog.weiyigeek.top/2022/7-2-676.html

本文至此完毕,更多技术文章,尽情期待下一章节!


WeiyiGeek Blog 个人博客 - 为了能到远方,脚下的每一步都不能少 】

欢迎各位志同道合的朋友一起学习交流,如文章有误请在下方留下您宝贵的经验知识!

作者主页: 【 https://weiyigeek.top

博客地址: 【 https://blog.weiyigeek.top 】

专栏书写不易,如果您觉得这个专栏还不错的,请给这篇专栏 【点个赞、投个币、收个藏、关个注,转个发,留个言】(人间六大情),这将对我的肯定,谢谢!。

  • echo "【点个赞】,动动你那粗壮的拇指或者芊芊玉手,亲!"

  • printf("%s", "【投个币】,万水千山总是情,投个硬币行不行,亲!")

  • fmt.Printf("【收个藏】,阅后即焚不吃灰,亲!")

  • console.info("【转个发】,让更多的志同道合的朋友一起学习交流,亲!")

  • System.out.println("【关个注】,后续浏览查看不迷路哟,亲!")

  • cout << "【留个言】,文章写得好不好、有没有错误,一定要留言哟,亲! " << endl;

更多网络安全、系统运维、应用开发、物联网实践、网络工程、全栈文章,尽在 https://blog.weiyigeek.top 之中,谢谢各位看又支持!

运维实践-最新Nginx二进制构建编译lua-nginx-module动态链接Lua脚本访问Redis数据库读取静态资源隐式展现的更多相关文章

  1. vivo大规模 Kubernetes 集群自动化运维实践

    作者:vivo 互联网服务器团队-Zhang Rong 一.背景 随着vivo业务迁移到K8s的增长,我们需要将K8s部署到多个数据中心.如何高效.可靠的在数据中心管理多个大规模的K8s集群是我们面临 ...

  2. HBase运维实践-聊聊RIT的那点事

    相信长时间运维HBase集群的童鞋肯定都会对RIT(Region-In-Transition,很多参考资料误解为Region-In-Transaction,需要注意)有一种咬牙切齿的痛恨感,一旦Reg ...

  3. 关于Prometheus运维实践项目

    关于Promethues运维实践项目 1. 什么是Prometheus运维实践项目 ​ 是什么 ​ Prometheus,普罗米修斯,是古希腊神话中为人间带来火种的神. ​ Prometheus运维实 ...

  4. elasticsearch基本概念理解+elasticsearch 的shards unassigned处理方法 -- 最佳运维实践 - 集群规划

    1.es与MySQL的概念对比 2.概念理解 2.1 Index : 一个索引即是文档的集合 2.2 Document : 一个文档即是一个可被索引的基础单元信息,一条记录: 2.3 Replicas ...

  5. 华为刘腾:华为终端云Cassandra运维实践分享

    点击此处观看完整活动视频 各位线上的嘉宾朋友大家好,我是来自华为消费者BG云服务部的刘腾,我今天给大家分享的主题是华为终端云Cassandra运维实践.和前面王峰老师提到的Cassandra在360中 ...

  6. 阿里智能运维实践|阿里巴巴DevOps实践指南

    编者按:本文源自阿里云云效团队出品的<阿里巴巴DevOps实践指南>,扫描上方二维码或前往:https://developer.aliyun.com/topic/devops,下载完整版电 ...

  7. 企业运维实践-Nginx使用geoip2模块并利用MaxMind的GeoIP2数据库实现处理不同国家或城市的访问最佳实践指南

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 0x00 前言 ...

  8. 企业运维实践-丢弃手中的 docker build , 使用Kaniko直接在Kubernetes集群或Containerd环境中快速进行构建推送容器镜像

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 首发地址: h ...

  9. 企业运维实践-还不会部署高可用的kubernetes集群?使用kubeadm方式安装高可用k8s集群v1.23.7

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 文章目录: 0x00 前言简述 ...

随机推荐

  1. 归约与分组 - 读《Java 8实战》

    区分Collection,Collector和collect 代码中用到的类与方法用红框标出,可从git库中查看 收集器用作高级归约 // 按货币对交易进行分组 Map<Currency, Li ...

  2. 141_Power Query之获取钉钉审批流自动刷新Power BI报告

    博客:www.jiaopengzi.com 焦棚子的文章目录 请点击下载附件 一.背景 钉钉办公给很多企业带来了很多方便,比如审批流线上化,通用化.线上化填写后,数据自动获取又是一个硬伤了,虽然数据可 ...

  3. 利用 Onekey Theater 改善屏幕显示效果

    介绍 Onekey Theater(一键影音),它是联想笔记本带的一键影音功能,使用它能够更改笔记本的显示效果和音效,以此模仿电影院的效果,为用户带来更好是视听效果及享受. 作用 之前的联想笔记本自带 ...

  4. ACM 刷题记录

    HDU Multi-University Training Contest 题目来源 题目 知识点 时间复杂度 完成情况 2019 Contest8 A Acesrc and Cube Hyperne ...

  5. C++ 智能指针浅析

    C++ 智能指针浅析 为了解决 C++ 中内存管理这个老大难问题,C++ 11 中提供了三种可用的智能指针.(早期标准库中还存在一种 auto_ptr,但由于设计上的缺陷,已经被 unique_ptr ...

  6. 快速 IO

    IO 的进化史 cin和cout 刚开始学的时候,老师叫我们用 cin 和 cout 大概是因为这最简单吧 cin>>x; cout<<x scanf和printf 学到函数了 ...

  7. idea 中菜单栏定位到类的图标消失(小齿轮按钮)

    本文链接:https://www.cnblogs.com/hchengmx/p/14533349.html 在2019.2以及以下版本 勾选:Autoscroll from source: 在2019 ...

  8. 5种在TypeScript中使用的类型保护

    摘要:在本文中,回顾了TypeScript中几个最有用的类型保护,并通过几个例子来了解它们的实际应用. 本文分享自华为云社区<如何在TypeScript中使用类型保护>,作者:Ocean2 ...

  9. JVM学习笔记-从底层了解程序运行(一)

    1:JVM基础知识 什么是JVM 1. java虚拟机,跨语言的平台,实现java跨平台 2. 可以实现多种语言跨平台,只要该语言可以编译成.class文件 3. 解释执行.class文件 java是 ...

  10. Python量化-如何获取实时股票信息

    如何获取实时股票信息 股票信息的接口有很多,之前大家常用的是新浪的,但在年初的时候,新浪的接口突然不能使用,给大家造成了很大的困扰,为此网上也有很多教程教大家如何从新浪获取数据,跟着教程弄了半天也不行 ...