热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何通过Lua扩展Nginx

这篇文章主要讲解了“如何通过Lua扩展Nginx”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习

这篇文章主要讲解了“如何通过 Lua 扩展 Nginx”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何通过 Lua 扩展 Nginx”吧!

1. ngx_lua 模块


  • Nginx 模块需要用 C 开发,而且必须符合一系列复杂的规则,最重要的用 C 开发模块必须要熟悉 Nginx 的源代码,使得开发者对其望而生畏。

  • ngx_lua 模块通过将 lua 解释器集成进 Nginx,可以采用 lua 脚本实现业务逻辑。

  • 该模块具有以下特性:

    • 高并发、非阻塞地处理各种请求。

    • Lua 内建协程,这样就可以很好地将异步回调转换成顺序调用的形式。

    • 每个协程都有一个独立的全局环境(变量空间),继承于全局共享的、只读的“comman data”。

  • 得益于 Lua 协程的支持,ngx_lua 在处理 10000 个并发请求时只需要很少的内存。根据测试,ngx_lua 处理每个请求只需要 2KB 的内存,如果使用 LuaJIT 则会更少。

  • ngx_lua 非常适合用于实现可扩展的、高并发的服务。

2. 协程(Coroutine)


1. 协程类似一种多线程,与多线程的区别
  • 协程并非 os 线程,所以创建、切换开销比线程相对较小。

  • 协程与线程一样有自己的栈、局部变量等,但是协程的栈是在用户进程空间模拟的,所以创建、开销很小。

  • 多线程程序是多个线程并发执行,也就是说在一瞬间有多个控制流在执行。而协程强调的是一种多个协程间协作的关系,只有当一个协程主动放弃执行权,另一个协程才能取得执行权,所以在某一瞬间,多个协程间只有一个在运行。

  • 由于多个协程是只有一个在运行,所以对于临界区的访问不需要加锁,而多线程的情况则必须加锁。

  • 多线程程序由于有多个控制流,所以程序的行为不可控,而多个协程的执行是由开发者定义的所以是可控的。

Nginx 的每个 Worker 进程都是在 epoll 或 kqueue 这样的事件模型之上,封装成协程,每个请求都有一个协程进行处理。这正好与 Lua 内建协程的模型是一致的,所以即使 ngx_lua 需要执行 lua,相对 C 有一定的开销,但依然能保证高并发能力。

3. Nginx 进程模型


  • Nginx 采用多进程模型,单Master-多Worker,Master 进程主要用来管理 Worker 进程。

  • Worker 进程采用单线程、非阻塞地事件模型(Event Loop,事件循环)来实现端口的监听及客户端请求的处理和响应,同时 Worker 还要处理来自 Master 的信号。Worker 进程个数一般设置为机器 CPU 核数。

1. Master 进程具体包括如下 4 个主要功能
  • 接受来自外界的信号。

  • 向各 Worker 进程发送信号。

  • 监控 Worker 进程的运行状态。

  • 当 Worker 进程退出后(异常情况下),会自动重新启动新的 Worker 进程。

2. 进程模型

如何通过 Lua 扩展 Nginx

4. HTTP 请求处理


阶段说明
post-read读取请求内容阶段,nginx 读取并解析完请求头之后就立即开始运行
server-rewriteserver 请求地址重写阶段
find-config配置查找阶段,用来完成当前请求与 location 配置块之间的配置工作
rewritelocation 请求地址重写阶段,当 ngx_rewrite 指令用于 location 中,就是在这个阶段运行的
post-rewrite请求地址重写阶段,当 nginx 完成 rewrite 阶段所要求的内部跳转动作,如果 rewrite 阶段有这个要求的话
preaccess访问权限检查准备阶段,ngx_limit_req 和 ngx_limit_zone 在这个阶段运行,ngx_limit_req 可以控制请求的访问频率,ngx_limit_zone 可以控制访问的并发度。
access权限检查阶段,ngx_access 在这个阶段运行,配置指令多是执行访问控制相关的任务,入检查用户的访问权限,检查用户的来源 IP 是否合法
post-access访问权限检查提交阶段
try-files配置 try_files 处理阶段
content内容产生阶段,是所有请求处理阶段中最为重要的阶段,因为这个阶段的指令通常是用来生成 HTTP 响应内容的
log日志模块处理阶段

5. ngx_lua 指令


  • ngx_lua 属于 nginx 的一部分,它的执行指令都包含在 nginx 的 11 个步骤之中了,相应的处理阶段可以做插入式处理,即可插拔式架构,不过 ngx_lua 并不是所有阶段都会运行的;另外指令可以在 http、server、server if、location、location if 几个范围进行配置。

指令所处处理阶段使用范围解释
init_by_lua
init_by_lua_file
loading-confighttpnginx Master 进程加载配置时执行;
通常用于初始化全局配置/预加载 Lua 模块
init_worker_by_lua
init_worker_by_lua_file
starting-workerhttp每个 Nginx Worker 进程启动时调用的计时器,如果 Master 进程不允许
则只会在 init_by_\lua 之后调用;通常用于定时拉取配置/数据,
或者后端服务的健康检查。
set_by_lua
set_by_lua_file
rewriteserver,server if,location,location if设置 nginx 变量,可以实现复杂的赋值逻辑;此处是阻塞的,Lua 代码要做到非常快
write_by_lua
rewrite_by_lua_file
rewrite tailhttp,server,location,location ifrewrite 阶段处理,可以实现复杂的转发/重定向逻辑。
access_by_lua
access_by_lua_file
access tailhttp,server,location,location if请求访问阶段处理,用于访问控制
content_by_lua
content_by_lua_file
contentlocation,location if内容处理器,接受请求处理并输出响应
header_filter_by_lua
header_filter_by_lua_file
output-header-firsthttp,server,location,location if设置 header 和 COOKIE
body_filter_by_lua
body_filter_by_lua_file
output-body-filterhttp,server,location,location if对响应数据进行过滤,比如截断、替换
log_by_lua
log_by_lua_file
loghttp,server,location,location iflog 阶段处理,比如记录访问量/统计平均响应时间

6. OpenResty


1. 概念
  • OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。

2. 工作原理
  • OpenResty 通过汇聚各种设计精良的 Nginx 模块(主要由 OpenResty 团队自主开发),从而将 Nginx 有效地变成一个强大的通用 Web 应用平台。这样,Web 开发人员和系统工程师可以使用 Lua 脚本语言调用 Nginx 支持的各种 C 以及 Lua 模块,快速构造出足以胜任 10k 乃至 1000k 以上单机并发连接的高性能 Web 应用系统。

3. 目标
  • OpenResty 的目标是让你的 Web 服务直接跑在 Nginx 服务内部,充分利用 Nginx 的非阻塞 I/O 模型,不仅仅对 HTTP 客户端请求,甚至于对远程后端诸如 MySQL、PostgreSQL、Memcached 以及 Redis 等都进行一致的高性能响应。

7. ngx_lua 实例


  • content_by_lua:内容处理器,接收请求处理并输出响应。

  • 该指令工作在 Nginx 处理流程的 content 阶段,即内容产生阶段,是所有请求处理阶段中最为重要的阶段,因为这个阶段的指令通常是用来生成 HTTP 响应内容的。

  • 测试

    输出:
    $ curl http://127.0.0.1/
    $ Hello,world


1. 简单示例
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("

Hello, world!

")             ';         }     } }
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua_block {
                ngx.say('Hello, world!')
            }
        }
    }

}
启动
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_01.conf

测试
curl -i http://127.0.0.1/
2. 休眠示例
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location /lua_1 {
            default_type text/html;
            content_by_lua_block {
                ngx.say('Hello, world! @ Time 1!')
                ngx.sleep(3)
                ngx.say('Hello, world! @ Time 2!')
            }
        }
    }

}
启动
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_02.conf

测试
curl -i http://127.0.0.1/lua_1
curl -i http://127.0.0.1/lua_1
3. 带参数示例
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location /lua_1 {
            default_type text/html;
            content_by_lua_block {
                ngx.say(ngx.var.arg_a)
            }
        }
    }

}
启动
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_03.conf

测试
curl -i http://127.0.0.1?a=nginx_lua

8. OpenResty 连接 redis


配置文件
user www-data;
worker_processes auto;
pid /run/nginx.pid;

error_log logs/error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 8080;
        location ~/redis_lua/(\d+)$ {
            default_type text/html;
            charset utf-8;
            lua_code_cache on;
            content_by_lua_file '/home/zp/openresty/lua/redis.lua';
        }
    }

}
lua 脚本
local json = require("cjson")
local redis = require("resty.redis")
local red = redis:new()
red:set_timeout(1000)
local ip = "127.0.0.1"
local port = 6379
local ok, err = red:connect(ip, port)
if not ok then
    ngx.say('connect to redis error: ', err)
    return ngx.exit(500)
end

local id = ngx.var[1]
local value = "calue-"..id

red:set(id, value)

local resp, err = red:get(id)

if not resp then
    ngx.say('get from redis error: ', err)
    return ngx.exit(500)
end

red:close()

ngx.say(json.encode({cOntent=resp}))
测试
启动
/usr/local/openresty/nginx/sbin/nginx -p `pwd` -c conf/nginx_openresty_04.conf

测试
curl -i http://127.0.0.1/redis_lua/1
curl -i http://127.0.0.1/redis_lua/2
curl -i http://127.0.0.1/redis_lua/3

感谢各位的阅读,以上就是“如何通过 Lua 扩展 Nginx”的内容了,经过本文的学习后,相信大家对如何通过 Lua 扩展 Nginx这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程笔记,小编将为大家推送更多相关知识点的文章,欢迎关注!


推荐阅读
  • 网站访问全流程解析
    本文详细介绍了从用户在浏览器中输入一个域名(如www.yy.com)到页面完全展示的整个过程,包括DNS解析、TCP连接、请求响应等多个步骤。 ... [详细]
  • HTTP(HyperTextTransferProtocol)是超文本传输协议的缩写,它用于传送www方式的数据。HTTP协议采用了请求响应模型。客服端向服务器发送一 ... [详细]
  • 如何使用 `org.apache.tomcat.websocket.server.WsServerContainer.findMapping()` 方法及其代码示例解析 ... [详细]
  • 华为捐赠欧拉操作系统,承诺不推商用版
    华为近日宣布将欧拉开源操作系统捐赠给开放原子开源基金会,并承诺不会推出欧拉的商用发行版。此举旨在推动欧拉和鸿蒙操作系统的全场景融合与生态发展。 ... [详细]
  • 本文详细解析了ASP.NET 2.0中的Callback机制,不仅介绍了基本的使用方法,还深入探讨了其背后的实现原理。通过对比Atlas框架,帮助读者更好地理解和应用这一机制。 ... [详细]
  • 为什么多数程序员难以成为架构师?
    探讨80%的程序员为何难以晋升为架构师,涉及技术深度、经验积累和综合能力等方面。本文将详细解析Tomcat的配置和服务组件,帮助读者理解其内部机制。 ... [详细]
  • 用阿里云的免费 SSL 证书让网站从 HTTP 换成 HTTPS
    HTTP协议是不加密传输数据的,也就是用户跟你的网站之间传递数据有可能在途中被截获,破解传递的真实内容,所以使用不加密的HTTP的网站是不 ... [详细]
  • 单片微机原理P3:80C51外部拓展系统
      外部拓展其实是个相对来说很好玩的章节,可以真正开始用单片机写程序了,比较重要的是外部存储器拓展,81C55拓展,矩阵键盘,动态显示,DAC和ADC。0.IO接口电路概念与存 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 解决问题:1、批量读取点云las数据2、点云数据读与写出3、csf滤波分类参考:https:github.comsuyunzzzCSF论文题目ÿ ... [详细]
  • 在CentOS 7环境中安装配置Redis及使用Redis Desktop Manager连接时的注意事项与技巧
    在 CentOS 7 环境中安装和配置 Redis 时,需要注意一些关键步骤和最佳实践。本文详细介绍了从安装 Redis 到配置其基本参数的全过程,并提供了使用 Redis Desktop Manager 连接 Redis 服务器的技巧和注意事项。此外,还探讨了如何优化性能和确保数据安全,帮助用户在生产环境中高效地管理和使用 Redis。 ... [详细]
  • 服务器部署中的安全策略实践与优化
    服务器部署中的安全策略实践与优化 ... [详细]
  • 在配置Nginx的SSL证书后,虽然HTTPS访问能够正常工作,但HTTP请求却会遇到400错误。本文详细解析了这一问题,并提供了Nginx配置的具体示例。此外,还深入探讨了DNS服务器证书、SSL证书的申请与安装流程,以及域名注册、查询方法和CDN加速技术的应用,帮助读者全面了解相关技术细节。 ... [详细]
  • 在ElasticStack日志监控系统中,Logstash编码插件自5.0版本起进行了重大改进。插件被独立拆分为gem包,每个插件可以单独进行更新和维护,无需依赖Logstash的整体升级。这不仅提高了系统的灵活性和可维护性,还简化了插件的管理和部署过程。本文将详细介绍这些编码插件的功能、配置方法,并通过实际生产环境中的应用案例,展示其在日志处理和监控中的高效性和可靠性。 ... [详细]
  • 在优化Nginx与PHP的高效配置过程中,许多教程提供的配置方法存在诸多问题或不良实践。本文将深入探讨这些常见错误,并详细介绍如何正确配置Nginx和PHP,以实现更高的性能和稳定性。我们将从Nginx配置文件的基本指令入手,逐步解析每个关键参数的最优设置,帮助读者理解其背后的原理和实际应用效果。 ... [详细]
author-avatar
付枪_枪
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有