一、OpenResty基础
简介
『OpenResty』是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库、第三方模块以及大多数的依赖项。用于方便地搭建能够处理超高并发、扩展性极高的动态 Web 应用、Web 服务和动态网关。
OpenResty通过汇聚各种设计精良的Nginx模块,从而将Nginx有效地变成一个强大的通用Web应用平台。这样,Web开发人员和系统工程师可以使用Lua脚本语言调动Nginx支持的各种C以及Lua模块,快速构造出足以胜任10K乃至1000K以上单机并发连接的高性能Web应用系统。
OpenResty的目标是让你的Web服务直接跑在Nginx服务内部,充分利用Nginx的非阻塞I/O模型,不仅仅对HTTP客户端请求,甚至于对远程后端诸如MySQL、PostgreSQL、Memcached以及Redis等都进行一致的高性能响应。
OpenResty基于Nginx和Lua/LuaJIT,充分利用了两者的优势,能够无阻塞地处理海量并发连接,任意操纵HTTP/TCP/UDP数据流,而且功能代码不需要编译,可以就地修改脚本并运行,简化了开发流程,加快了开发和调试的速度,同时也缩短了开发周期。
应用场景
由于OpenResty具有优秀的反向代理功能,以及负载均衡、内容缓冲、安全防护等高级特性,所以最常见的用法是部署在网站架构的最前端,作为流量的总入口,提高系统的整体稳定性和可靠性。
OpenResty内嵌方便快捷的Lua脚本,完全能够取代PHP、Python、Ruby来编写应用服务,把业务逻辑跑在高性能的Nginx里,去掉不必要的中间环节直接操作Redis、MySQL等数据库,减少内部的网络消耗,节约系统资源。
OpenResty也可以充当API Gateway,以RESTful接口为基础聚合整理各种后端服务,并增加监控、缓存、权限控制等功能,改善系统的运行效率。
OpenResty使用四位数字作为版本号,形式是:a.b.c.x,其中前三位数字是内部Nginx的版本,作为大版本号,第四位数字是OpenResty自己的发布版本号,也就是小版本号。
Mac安装
1 | $ brew install openresty/brew/openresty |
Windows安装
去官网下载安装包。
1 | $ start nginx |
另外,如果windows环境没有安装perl,可去『strawberryperl』 下载安装。
docker安装
1 | $ docker run -d --name openresty1 -p 8090:8090 -v ~/docker/openresty/conf/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf -v ~/docker/openresty/logs:/usr/local/openresty/nginx/logs openresty/openresty:alpine |
conf/nginx.conf文件
1 | worker_processes 1; #设置worker进程数为1 |
linux安装
1 | #可参考nginx安装 |
openresty常用命令
1 | # cd到~/docker/openresty后执行 |
包管理工具
开发语言/环境都会提供配套的包管理工具,例如npm/Node.js、cpan/Perl、gem/Ruby等,OpenResty可使用opm。
opm的用法很简单,常用的命令有:
- search :以关键字检索相关的组件;
- get :安装功能组件(注意不是install);
- info :显示已安装组件的详细信息;
- list :列出所有本地已经安装的组件;
- upgrade:更新某个已安装组件;
- update :更新所有已安装组件;
- remove :移除某个已安装组件。
二、OpenResty核心组件
OpenResty的核心组成部分有四个,分别是:
- Nginx:高性能的Web服务器;
- LuaJIT:高效的Lua语言解释器/编译器;
- ngx_lua(http_lua):处理HTTP协议,让Lua程序嵌入在Nginx里运行;
- stream_lua:与ngx_lua类似,但处理的是TCP/UDP协议。
还包含许多nginx组件,以C模块的方式提供,集成在Nginx内部。
- ngx_iconv:转换不同的字符集编码;
- ngx_encrypted:使用AES-256算法执行简单的加密运算;
- ngx_echo:提供一系列“echo”风格的指令和变量;
- ngx_set_misc:增强的“set_xxx”指令,用来操作变量;
- ngx_headers_more:更方便地处理HTTP请求头和响应头的指令;
- ngx_memc:支持各种memcached操作;
- ngx_redis2:支持各种Redis操作;
- ngx_dizzle:支持各种MySQL操作;
- ngx_postgres:支持各种PostgreSQL操作。
OpenResty里的Lua组件通常以Lua源码的方式提供(*.lua),但个别组件为追求效率会以C语言实现,是动态链接库的形式( *.so)。
- lua_core:OpenResty的核心功能库;
- lua_cjson:处理JSON格式的数据,速度很快(使用C语言实现);
- lua_string:hex/md5/sha1/sha256等字符串功能;
- lua_upload:流式读取HTTP的上行数据;
- lua_healthcheck:后端集群健康检查;
- lua_limit_traffic:定制流量控制策略;
- lua_lock:基于共享内存的非阻塞锁;
- lua_lrucache:高效的LRU缓存功能;
- lua_dns:高效、非阻塞的DNS解析功能;
- lua_websocket:高效、非阻塞的WebSocket功能;
- lua_redis:Redis客户端,用起来比ngx_redis2更灵活;
- lua_memcached:Memcached客户端,用起来比ngx_memc更灵活;
- lua_mysql:MySQL客户端,用起来比ngx_dizzle更灵活。
OpenResty目前提供的辅助工具有:
- opm :类似rpm、npm的管理工具,用来安装各种功能组件;
- resty-cli :以命令行的形式直接执行OpenResty/Lua程序;
- restydoc :类似man的参考手册,非常详细。
三、Lua语言
Lua是OpenResty的工作语言,是一种动态脚本语言。开发工具可以是IDEA + EmmyLua插件。windows平台推荐使用luaDist。
基本语法
- 单行注释使用–。多行注释使用–[[ … ]]–
- 有六种基本数据类型,nil,boolean,number,string,function,table。使用函数type()测试数据类型。
- string,字符串不可变,单引号或双引号都可以。\代表转义字符。使用[[ … ]]可避免转义。
- 变量,区分大小写,局部变量使用local关键字声明,没有使用local的都是全局变量,且不需要声明就可以直接使用。没有常量说法。
- 逻辑运算使用and、or和not。nil和false为假,其他都是真,包括0
- 字符串运算有个..,用于连接多个字符串。
- 语句块使用do…end形式声明,赋值使用=号。
- 分支语句 if condition1 then … elseif condition2 then … else … end。
- 循环语句有while、repeat-until和for三种。while condition do … end。repeat … until condition。for var=m,n,step do … end。
- 支持使用break和return跳出循环,但不支持continue。
- 模块通过require关键字来引用。自行编写Lua模块时,创建一个表,将函数作为表的元素,用return返回这个表即可。
函数
1 | local function f1(a) |
表
表(table)是Lua里唯一的数据结构。类似于字典、数组等,能模拟出array、list、dict、set、map等常见数据结构。
1 | local a ={1,2,3} --声明数组形式的表 |
面向对象
- 面向对象的设计原则并不完全适用Lua。字典形式的表本身就是对象,可以存储任意变量和函数。
- 封装,但不提供private、public等关键字,所有成员都是公开的。如需要实现私有成员,则在模块文件里用local修饰变量。
- 多态,表是动态的,成员在运行时可以随意替换,没有编译型语言静态绑定的烦恼。
- 继承,在Lua里不提倡,替代方案是使用“原型”模块,克隆出一个新对象,然后在动态变更其属性,达到继承类似的效果。
- 原型模式,需要使用Lua的高级特性,元表metatable和函数setmetatable()。
- 元表需要在表里使用”__index”元方法,重载Lua里查找key的操作。
- 函数setmetatable(t,meta)是把表t的元表设置为meta并返回t。如果meta里设置了__index方法,那么对t的操作t.key会作用在meta上,即meta.key。这样表t就克隆了表meta的所有成员,表meta就成了表t的原型。
- self关键字代表对象自身,调用函数时可以使用”:”替代”.”,这样会隐含传入一个self参数。
1 | local proto = {} --首先声明一个原型对象 ,暂时是空表 |
标准库
- base,最核心的函数。type()、print()、iparis()、pairs()、assert()、error()、loadstring()等函数,可直接调用。
- package,管理Lua的模块。require()用来加载模块,package.path和package.cpath用来查找require函数查找*.lua和.so时的路径,package.loaded是个表,保存了已加载的模块。
- string,字符串相关函数,如取子串、格式化、大小写转换等。
- table,表相关函数,如插入删除元素、排序等。
- math,数学计算相关函数,如三角函数、平方根等。math.floor()和math.ceil()用来对数字向下或向上取整。math.min()和math.max()获取最小值和最大值。math.randomseed()设置伪随机数种子,math.random(m,n)用来产生[0,1),[1,m],[m,n]之间的伪随机数。
- io,文件相关函数,如打开、关闭、读写文件,注意是阻塞的。io.open(filename,mode)用来打开文件,io.popen(prog,mode)用来执行prog命令,io.tmpfile()用来创建临时文件。
- OS,操作系统相关函数。os.execute(command)阻塞执行操作系统命令,如shell命令。os.remove(filename)和os.rename(oldname,newname)文件删除和改名。os.date(format,time)做时间戳格式化。
- debug,调试用的函数。debug.traceback()输出Lua代码的调用栈信息,追踪代码执行情况。
1 | local str ='Hello' |
高级特性
- 闭包,参考js的闭包,Lua函数天然就是闭包,在声明的同时就捕获了之前的所有变量。
- 保护调用,可以使用base库的pcall或xpcall函数,来保护程序执行不会出错,并返回调用结果。
- 可变参数,在参数列表里用”…”表示接受不确定数量的参数。
1 | local ok, v = pcall(math.sqrt, 2) |
LuaJIT
- 『LuaJIT传送门』
- 为了追求极致的性能, OpenResty里使用的却不是官方Lua解释器,而是一个非官方的开源实现LuaJIT。
- LuaJIT是Lua语言的另一个实现,包括一个汇编语言编写的解释器和一个JIT编译器。由于使用的是汇编语言,可以把Lua语言用Just-In-Time技术直接编译为目标机器码,使运行速度达到或接近C代码的程度。
- LuaJIT基于Lua 5.1,适当引入5.2和5.3的语言特性,还提供了特别的优化和库。
- LuaJIT执行Lua程序时会将源程序转换成字节码,再倒入LuaVM里解释运行。再运行时做热点分析,热点代码触发JIT编译器,尝试将字节码再变异成本地的机器码。
新特性包括:
- goto语句,用于不支持continue情况下的变通实现。
- jit库,包含一些环境信息
- table库,添加了一些新函数,table.new创建表,table.clear置为空表,table.clone浅拷贝表。
- bit库,增强整数类型的位运算能力。包括进制转换,按位操作等。
- ffi库,简化Lua代码调用c接口,还可以加载so形式的动态库并调用函数,灵活拓展Lua功能。
四、OpenResty和Lua开发
- 由于Nginx的模块化架构具有良好的扩展性,OpenResty实现了ngx_lua和stream_lua等模块,把Lua/LuaJIT完美地整合进了Nginx,从而让我们能够在Nginx内部的多个关键节点里嵌入Lua脚本,用Lua这种便捷的语言来实现复杂的HTTP/TCP/UDP业务逻辑,同时依然保持着高度的并发服务能力。
- OpenResty的开发服务本质上是编写conf配置文件。
运行机制
nginx的一个web服务的生命周期可以分成三个阶段。
- initing,服务启动,工作通常是读取配置文件,初始化内部数据结构。
- running,服务运行,接受客户端的请求,返回响应结果。
- exiting,服务停止,做一些必要的清理工作,如关闭监听端口。
initing阶段在OpenResty里分为三个子阶段。
- configuration,读取配置文件,解析配置指令,设置运行参数。
- master-initing,配置文件解析完毕,master进程初始化公用的数据。
- worker-initing,worker 进程自己的初始化,进程专用的数据。
running阶段,收到客户端请求后,OpenResty对每个请求都会使用一个专门的“流水线”顺序进行处理,就是 OpenResty 定义的处理阶段,包括:
- ssl,SSL/TLS安全通信和验证。
- preread,在正式处理之前预数据,接收HTTP请求头。
- rewrite,检查、改写URI,实现跳转重定向。
- access,访问权限控制。
- content,产生响应内容。
- filter,对content阶段产生的内容进行过滤加工处理。
- log,请求处理完毕,记录日志,或者其他的收尾工作。
对应以上的处理阶段,OpenResty提供了一些”xxx by lua”指令,开发Web应用时使用它们就可以在这些阶段里插入Lua代码,执行业务逻辑,常用的有:
- init_by_lua,master-initing 阶段,初始化全局配置或模块。可启动定时器,定时从redis获取数据等
- init_worker_by_lua,worker-initing阶段,初始化进程专用功能。
- ssl_certificate_by_luassl 阶段,在“握手”时设置安全证书。
- set_by_lua,rewrite阶段,改写Nginx变量。
- rewrite_by_lua,rewrite阶段,改写URI,实现跳转/重定向。
- access_by_lua,access阶段,访问控制或限速。
- content_by_lua,content阶段,产生响应内容。可运行主要的业务逻辑。
- balancer_by_lua,content阶段,反向代理时选择后端服务器。
- header_filter_by_lua,filter阶段,加工处理响应头。
- body_filter_by_lua,filter阶段,加工处理响应体。可进行数据编码,加密等。
- log_by_lua,log阶段,记录日志或其他的收尾工作。可发送处理完毕的回调等。
以上指令通常都有3种形式:
- xxx_by_lua,执行字符串形式的Lua代码。由于涉及到单引号和双引号冲突,不推荐使用。
- xxx_by_lua_block,功能相同,但指令后是{ … }的Lua代码块。由于代码混在了配置文件里,不建议过多使用。
- xxx_by_lua_file,功能相同,但执行磁盘上的源码文件。推荐使用,彻底分离了配置文件和业务代码,可以独立部署和以模块的方式管理Lua程序。
功能接口
OpenResty为用户提供了上百个功能接口,可分为如下几类。
- 基础功能,系统信息、日志、时间日期、数据编码、正则表达式等功能。如ngx.print,ngx.say,ngx.get_phase()等。
- 高级功能,共享内存、定时器、轻量级线程、信号量等功能。
- 请求处理,处理TCP/UDP/HTTP协议,响应或拒绝请求。
- 访问后端,无阻塞地与各种后端服务通信(如Redis、MySQL)。
- 反向代理,管理上游服务器集群,健康检查。
- 负载均衡,自定义负载均衡策略,选择上游服务器。
- 安全通信,SSL、OSCP、WAF等密码、证书、安全相关功能。
这些接口大部分位于全局表ngx里,无须require即可访问。与Lua 自带的标准库函数不同,它们基于nginx的事件机制和Lua的协程特性,都是”100 nonblocking”的,能够轻松编写出同步非阻塞的高效代码。
1 | -- 1、系统信息 |
正则表达式
提供6个正则表达式相关函数,底层实现是PCRE库。函数有个名为options的参数,-j代表PCRE-JIT编译,-o代表仅编译1次并缓存,正则替换时尽量不要使用o选项。
- match,单词正则匹配
- gmatch,多次正则匹配
- find,同match,返回的是查到的位置索引
- sub,正则替换
- gsub,多次正则替换
- split,正则切分
1 | local str ='abcd-123' |
cache高速缓存
Cache的容量通常都是有限的,需要使用某种算法更新淘汰数据,较常见的有FIFO、LFU、LRU等,OpenResty基于LRU算法提供了一个方便易用的Cache库lua-resty-lru-cache,并且支持过期时间功能(expire)。该库内部有两个模块:resty.lrucache适用于
高命中率低更新率的场景。resty.lru-cache.pureffi适用于低命中率
高更新率的场景,必须使用require加载后才能使用。
1 | local lrucache = require "resty.lrucache" -- 加载lrucache |
HTTP服务
开发HTTP服务主要用到的执行阶段有:set_by_lua,rewrite_by_lua,access_by_lua,content_by_lua,header_filter_by_lua,body_filter_by_lua,log_by_lua。
请求和响应常用函数:
- 函数ngx.req.get_method和set_method用于读写当前请求方法。
- 函数ngx.req.set_uri(uri,jump),用来改写请求行的地址。
- 函数ngx.req.get_uri_args和set_uri_args用来读写URI里的参数。
- 函数ngx.req.get_post_args用来获取POST的参数。
- 函数ngx.req.get_headers和set_header用来解析或改写请求头字段。
- 函数ngx.req.discard_body可以丢失请求体。
- 函数ngx.req.read_body会开始读取请求体数据。则可以用ngx.req.get_body_data来获取请求体,可以用ngx.req.set_body_data或ngx.req.set_body_file来改写请求体。
- 使用ngx.status读写响应状态码。
- ngx.header可以读取或修改响应头字段,ngx.resp.add_header添加响应头字段。ngx.send_headers可以显式的发送响应头。
- ngx.print和ngx.say用来发送响应体数据。内部使用缓冲机制,可以用函数ngx.flush来强制刷新缓冲区发送。
- ngx.req.socket函数用来获取连接客户端的cosocket对象,直接和客户端通信。
流程控制:
- ngx.redirect(uri,status),标准的301/302重定向
- ngx.exec(uri,args),跳转到内部的其他location
- ngx.exit(status),结束请求的处理
- ngx.eof(),发送EOF标志,不会再响应数据
案例:
- 只支持 GET POST 方法:
- 只支持 HTTP 1.1 /2 协议
- 只允许某些ip的用户访问服务
- GET方法获取当前时间,以http时间格式输出
- POST方法在请求体里传入时间戳,服务器转换为http时间格式输出
- 可以使用URI参数need_encode=1,则输出会做Base64编码
划分为4个模块,对应的nginx总体配置文件如下,对应的lua文件需要放置到openresty目录下。
1 | location /http { |
1 | --lua/http_rewrite.lua文件 |
1 | --lua/http_access.lua文件 |
1 | --lua/http_content.lua文件 |
1 | --lua/http_filter.lua文件 |
四、访问后端
OpenResty可以通过后台通信,与Redis、Mysql、消息队列、tomcat等业务服务,ZooKeeper等配置服务等,构建复杂的业务逻辑,变身为动态网关。
子请求(location capture)
- 是较传统的方式,基于Nginx平台内部的子请求机制,需要配合Nginx反向代理模块(如ngx_proxy,ngx_redis2,ngx_fastcgi等),间接地访问后端服务,接口参数较多,调用成本也略高。
- 基本原理是在本请求内向另外的location再发起一个HTTP请求一这被称为子请求,原请求则称为父请求,并完整地“捕获”处理后的所有数据,就像是调用了location。
- ngx.location.capture只能在rewrite_by_lua、access_by_lua和content_by_lua三个执行阶段。
- 缺点是配置不够灵活,需要访问新的后端必须要改写文件,配置新的location。如果后端服务没有对应的nginx模块就需要用C语言开发,难度较大。
1 | location = /hello { |
1 | local capture = ngx.location.capture --别名简化调用 |
协程套接字(corountine based socket,cosocket)
- 是OpenResty独有的特性,结合了Nginx的事件机制和Lua的协程特性,以同步非阻塞的方式实现了socket编程,高效的与任意的后端服务通信。
- 利用bit/ffi库解析二进制数据,能够支持任意的通信协议。
- 内建了连接池机制,实现了长连接。支持TCP、UDP和UNIX Domain Socket。
- 能在rewrite_by_lua、access_by_lua、content_by_lua、ssl_certificate_by_lua和ngx.timer里运行。
1 | local sock = ngx.socket.tcp() --创建cosocket对象 |
其他功能
- DNS客户端,使用lua-resty-dns库来实现域名解析功能
- HTTP客户端,使用lua-resty-http库来实现HTTP协议的接口调用
- WebSocket客户端,使用lua-resty-websocket库来实现WebSocket协议的接口调用
- Redis客户端,使用lua-resty-redis库来实现Redis命令和管道操作
- Mysql客户端,使用lua-resty-mysql库来实现Mysql数据库操作
以下为redis的操作
1 | local redis = require "resty.redis" --加载resty.redis模块 |
以下为mysql的操作
1 | local mysql = require("resty.mysql") --加载msyql库 |
五、高级特性
反向代理
上游集群配置如下,
1 | upstream backend1{ #第1个上游集群 |
1 | local upstream = require "ngx.upstream" --显式加载ngx.upstream库 |
共享内存
- 共享内存是进程间通信(IPC)的一种常用手段,它在系统内存里开辟了一个特别的区域,多个进程可以共享所有权读写数据,比起信号、管道、消息队列、套接字等其他方式来说速度
更快,也更加灵活实用。 - OpenResty内置了强大的共享内存功能,不仅支持简单的数据存取,还支持原子计数和队列操作,用起来就像是一个微型的Redis数据库,极大地便利了worker进程间的通信和协作。
- OpenResty 共享内存里存储的数据只能是布尔、数字、字符串这三种类型。
- 使用时需要在nginx配置文件的http块里进行定义。lua_shared_dict dict size; #定义1个名为dict的共享内存,大小为size
1 | --共享内存提供对象读写删除操作 |
定时器
- 定时器可以在任意处理阶段发起任意多个定时器,执行任意的功能。
- 使用lua_max_pending_timers num来限制排队的任务数量。使用lua_max_running_timers num来限制最多可同时运行的定时任务数量。
1 | -- ok,err=ngx.timer.at(delay,handler,...) --启动单次任务定时器,delay秒后开始 |
进程管理
- OpenResty的进程模型基于nginx,以master/worker多进程方式提供服务。新增了一个拥有root权限的特权进程。
- 进程管理位于ngx.process库,它是lua-resty-core库的一部分。
- OpenResty进程有六种类型:single单一进程,master监控进程,signaller信号进程,worker工作进程,helper辅助进程,privileged agent特权进程。
1 | --进程类型 |
轻量级线程
- OpenResty本质是多进程单线程的,每个worker里只有一个主线程,通过I/O多路复用机制(epoll/kqueue)实现服务。
- 基于Lua的协程提出了轻量级线程概念,类似于操作系统的线程,可并发运行,但不是通过系统内核来调度。
- 轻量级线程只能在rewrite_by_lua、access_by_lua、content_by_lua、ssl_certificate_by_lua和ngx.timer里使用。
- OpenResty使用ngx.semaphore提供信号量操作,能实现高级的线程同步功能。信号量是线程同步的经典手段,但只能在本进程的线程之间同步,不能跨进程生效。不同进程的线程同步必须使用共享内存。
- 信号量有4个操作方法,new新建一个信号量,wait等待信号量,post增加信号量,count获取当前信号量的数量。
1 | --启动线程 |
HTTPS服务
- OpenResty为HTTPS服务增加了关键指令,”ssl_certificate_by_lua”,能在SSL/TLS握手阶段执行Lua代码,实现各种优化。
- 常用的手段有利用ngx.ssl动态加载整数,利用ngx.ocsp动态查验证书,以及Session ID和Session Ticket会话复用。
- 会话复用的原理是,由于https有安全成本,当第一次握手时认证身份,获取了通信的密钥,可以把这个密钥保存起来供下次通信时直接使用。
- 搭建HTTPS服务的常见配置如下。
1 | server { |
HTTP2服务
HTTP2协议脱胎于SPDY协议,是HTTP 1.0/1.1的升级和优化,主要解决网络性能问题。HTTP2的改进包括:
- 二进制格式,非明文协议,将数据分为数据帧,更利于组织和传输
- 多路复用,允许使用单个连接同时发起多个请求,不受数 的限制
- 请求优先级,高优先级的请求可以更快地获得响应
- 流量控制,类似TCP的流量控制机制,使用窗口避免拥塞
- 头部压缩,使用专用的HPACK算法压缩冗余的头部信息
- 服务端推送,服务器可以主动向客户端发送可能需要的资源
- 安全性增强,禁用了数百种不再安全的算法,减少了被攻破的可能
- 不强制加密,允许用户在安全与性能间做出自己的选择
如需要支持HTTP2,需要编译时configure使用选项”–with-http_v2_module”开启。
1 | server{ |
可以让curl发送HTTP2请求
1 | curl --http2 -k 'https://127.0.0.1:443/' #请求HTTP2服务,-k为不验证证书 |
websocket服务
- WebSocket是为了解决现有HTTP协议的缺陷,即实现双方向的实时通信,避免通过HTTP协议轮询。
- WebSocket使用HTTP协议通过握手动作建立连接,之前基于TCP的全双工通信协议。在建立连接的初始阶段完全兼容HTTP协议,因此服务的配置文件中和传统http配置相同。
- OpenResty内置lua-resty-websocket库来支持WebSocket功能,调用resty.websocket.server提供的接口来实现服务端功能。
TCP/UDP服务
- Nginx 1.9.0引入steam子系统后,可以处理TCP/UDP协议。OpenResty也实现了运行在stream块里的stream_lua模块。
- OpenResty也会对每个TCP/UDP请求使用流水线顺序进行处理,处理阶段和http有差异,如access阶段发生在ssl之前,没有rewrite阶段等。
- OpenResty主要聚焦在HTTP开发,目前还无法做到ngx_lua的完善程序。
安全防护
安全防护主要应用场景:
- 基本算法
- 防止SQL注入
- 访问权限控制
- 策略限速限连
- WAF
使用lua-resty-limit-traffic,实现服务限制,10 req/s。
1 | lua_shared_dict lim_req_store lOm; #定义多进程间使用的共享内存 |
六、Tengine
『Tengine』是淘宝团队在nginx基础上,针对大访问量网站的需求,添加了很多高级功能和特性。
特性包括:
- 继承Nginx-1.18.0的所有特性,兼容Nginx的配置;
- 支持HTTP的CONNECT方法,可用于正向代理场景;
- 增强相关运维、监控能力,比如异步打印日志及回滚,本地DNS缓存,内存监控等;
- Stream模块支持server_name指令;
- 更加强大的负载均衡能力,包括一致性hash模块、会话保持模块,还可以对后端的服务器进行主动健康检查,根据服务器状态自动上线下线,以及动态解析upstream中出现的域名;
- 输入过滤器机制支持。通过使用这种机制Web应用防火墙的编写更为方便;
- 支持设置proxy、memcached、fastcgi、scgi、uwsgi在后端失败时的重试次数;
- 动态脚本语言Lua支持。扩展功能非常高效简单;
- 支持按指定关键字(域名,url等)收集Tengine运行状态;
- 组合多个CSS、JavaScript文件的访问请求变成一个请求;
- 自动去除空白字符和注释从而减小页面的体积