Openresty 与 Tengine

 

Openresty和Tengine基于 Nginx 的两个衍生版本,某种意义上他们都和淘宝有关系,前者是前淘宝工程师agentzh主导开发的,后者是淘宝的一个开源项目;

Openresty的最大特点是引入了ngx_lua模块,支持使用lua开发插件;

Tengine的特点是融入了因淘宝自身的一些业务带来的新功能;

 

Tengine 简介

tengine官方网站:http://tengine.taobao.org/index_cn.html

在 Nginx官方版本的基础上增加的一些定制模块如下:

1、支持动态加载模块:通过加载so文件实现,不用再重新编译整个项目了,配置如下:

dso {
     load ngx_http_lua_module.so;
     load ngx_http_memcached_module.so;
}

 

2、ngx_proc_daytime_module模块,这个模块允许开一个独立的服务进程,该模块本身并未实现具体的业务逻辑,而是构建了一个TCP Server框架,等待开发者来实现自己的业务;

 

3、ngx_http_concat_module模块,用于合并多个文件的响应;

 

4、ngx_http_upstream_session_sticky_module模块,该模块是一个负载均衡模块,通过cookie实现客户端与后端服务器的会话保持, 在一定条件下可以保证同一个客户端访问的都是同一个后端服务器。

 

5、ngx_http_upstream_check_module模块,用于检查upstream上游服务器的健康状况,如下是一个配置的例子:

upstream cluster1 {
        # simple round-robin
        server 192.168.0.1:80;
        server 192.168.0.2:80;

        check interval=3000 rise=2 fall=5 timeout=1000 type=http;
        check_http_send "HEAD / HTTP/1.0\r\n\r\n";
        check_http_expect_alive http_2xx http_3xx;
    }

 

6、trim filter模块,用于删除 html,内嵌 javascript 和 css 中的注释以及重复的空白符,例如:

location / {
    trim on;
    trim_js on;
    trim_css on;
}

 

7、ngx_http_headers_module模块,支持根据Content-Type来设置过期时间,例如:

expires_by_types       24h text/html;
    expires_by_types       modified +24h text/xml;
    expires_by_types       @15h30m text/xml;
    expires_by_types       0 text/xml;
    expires_by_types       -1 text/xml;
    expires_by_types       epoch text/xml;

 

8、ngx_http_limit_req_module模块,限制访问

9、扩展了ngx_http_log_module模块,支持syslog和pipe;

 

 


 

 

Openresty 简介

 

openresty官方网站:http://openresty.org/cn/index.html

agentzh自己对openresty的介绍:http://blog.zoomquiet.org/pyblosxom/oss/openresty-intro-2012-03-06-01-13.html

 

agentzh(章亦春)的openresty开源项目(基于nginx),通过各种插件、模块,极大的扩展了nginx能干的事情,而lua扩展更是可以用来定制非常复杂的业务逻辑。作者给nginx赋予的这些新的特性,使openresty在业务开发上变得更加简单,对程序员更加友好,开发者可以在不需要对nginx源码熟悉的情况下就直接使用一些高级特性,比如并发subrequest、dns异步解析、对第三方数据库(如mysql、redis、memcached)等的访问。

 

先简单看一下openresty扩展的模块:

  • ArrayVarNginxModule              支持数组变量
  • AuthRequestNginxModule            鉴权模块               
  • CoolkitNginxModule                     一些插件
  • NginxDevelKit                            封装了一些面对开发者的C接口
  • EchoNginxModule                     一堆类似于shell命令的指令,支持(串行/并行)子请求等,这个模块很酷,也很实用
  • EncryptedSessionNginxModule      会话加密
  • FormInputNginxModule                解析POST请求中的参数
  • HeadersMoreNginxModule            http头处理
  • IconvNginxModule                       设置响应编码集
  • MemcNginxModule                      支持对Memcached的访问
  • DrizzleNginxModule                  支持对mysql的访问
  • PostgresNginxModule                   支持对Postgres数据库的访问
  • RdsCsvNginxModule                     filter模块,将Drizzle和Postgres两个模块的响应格式化为csv输出
  • RdsJsonNginxModule                    filter模块,将Drizzle和Postgres两个模块的响应格式化为json输出
  • RedisNginxModule                        支持对redis的访问(只支持select和get命令)
  • Redis2NginxModule                      支持对redis的访问(支持所有redis命令)
  • SetMiscNginxModule                     一堆set命令,用于设置变量
  • SrcacheNginxModule                    通过子请求进行cache
  • XssNginxModule                          防跨站攻击

 

 

  • LuaJIT                                       luaJIT解释器
  • StandardLuaInterpreter               标准lua解释器
  • LuaCjsonLibrary                          json库
  • LuaNginxModule                       lua接口库 (该模块本身用C实现)
  • LuaRdsParserLibrary                   rds格式解析
  • LuaRedisParserLibrary                 redis响应解析库
  • LuaRestyCoreLibrary                   LuaNginxModule模块的lua实现
  • LuaRestyDNSLibrary                   dns解析库
  • LuaRestyLockLibrary                
  • LuaRestyLrucacheLibrary             LRU cache库
  • LuaRestyMemcachedLibrary     memcached访问接口
  • LuaRestyMySQLLibrary                mysql访问接口
  • LuaRestyRedisLibrary                  redis访问接口
  • LuaRestyStringLibrary                 一些hash函数的接口
  • LuaRestyUploadLibrary              
  • LuaRestyUpstreamHealthcheckLibrary
  • LuaRestyWebSocketLibrary           ws协议解析库
  • LuaUpstreamNginxModule             扩展了对upstream的支持    

 

 

浏览一下上述模块,有几个特点:

1、通过upstream机制已经可以支持对mysql、redis、postgreSQL、memcached 等数据库的访问(全都是异步无阻塞的);

2、跟lua扩展有关的模块,提供给lua脚本调用的库,api非常丰富,涉及各种的操作;

 


 

ngx_lua 模块

 ngx_lua模块的原理:

1、每个worker(工作进程)创建一个Lua VM,worker内所有协程共享VM;2、将Nginx I/O原语封装后注入 Lua VM,允许Lua代码直接访问;3、每个外部请求都由一个Lua协程处理,协程之间数据隔离;4、Lua代码调用I/O操作等异步接口时,会挂起当前协程(并保护上下文数据),而不阻塞worker;5、I/O等异步操作完成时还原相关协程上下文数据,并继续运行;

 

ngx_lua 模块提供的指令和API等:

指令名称

说明

lua_use_default_type

是否使用default_type指令定义的Content-Type默认值

lua_code_cache

*_by_lua_file文件是否cache

lua_regex_cache_max_entries

 

lua_regex_match_limit

 

lua_package_path

用Lua写的lua外部库路径(.lua文件)

lua_package_cpath

用C写的lua外部库路径(.so文件)

init_by_lua

master进程启动时挂载的lua代码

init_by_lua_file

 

init_worker_by_lua

worker进程启动时挂载的lua代码,常用来执行一些定时器任务

init_worker_by_lua_file

 

set_by_lua

设置变量

set_by_lua_file

 

content_by_lua

handler模块

content_by_lua_file

 

rewrite_by_lua

 

rewrite_by_lua_file

 

access_by_lua

 

access_by_lua_file

 

header_filter_by_lua

header filter模块

header_filter_by_lua_file

 

body_filter_by_lua

body filter模块,ngx.arg[1]代表输入的chunk,ngx.arg[2]代表当前chunk是否为last

body_filter_by_lua_file

 

log_by_lua

 

log_by_lua_file

 

lua_need_request_body

是否读请求体,跟ngx.req.read_body()函数作用类似

lua_shared_dict

创建全局共享的table(多个worker进程共享)

lua_socket_connect_timeout

TCP/unix 域socket对象connect方法的超时时间

lua_socket_send_timeout

TCP/unix 域socket对象send方法的超时时间

lua_socket_send_lowat

设置cosocket send buffer的low water值

lua_socket_read_timeout

TCP/unix 域socket对象receive方法的超时时间

lua_socket_buffer_size

cosocket读buffer大小

lua_socket_pool_size

cosocket连接池大小

lua_socket_keepalive_timeout

cosocket长连接超时时间

lua_socket_log_errors

是否打开cosocket错误日志

lua_ssl_ciphers

 

lua_ssl_crl

 

lua_ssl_protocols

 

lua_ssl_trusted_certificate

 

lua_ssl_verify_depth

 

lua_http10_buffering

 

rewrite_by_lua_no_postpone

 

lua_transform_underscores_in_response_headers

 

lua_check_client_abort

是否监视client提前关闭请求的事件,如果打开监视,会调用ngx.on_abort()注册的回调

lua_max_pending_timers

 

lua_max_running_timers

 

 

 

 

table

说明

ngx.arg

指令参数,如跟在content_by_lua_file后面的参数

ngx.var

变量,ngx.var.VARIABLE引用某个变量

ngx.ctx

请求的lua上下文

ngx.header

响应头,ngx.header.HEADER引用某个头

ngx.status

响应码

 

 

API

说明

ngx.log

输出到error.log

print

等价于 ngx.log(ngx.NOTICE, ...)

ngx.send_headers

发送响应头

ngx.headers_sent

响应头是否已发送

ngx.resp.get_headers

获取响应头

ngx.timer.at

注册定时器事件

ngx.is_subrequest

当前请求是否是子请求

ngx.location.capture

发布一个子请求

ngx.location.capture_multi

发布多个子请求

ngx.exec

 

ngx.redirect

 

ngx.print

输出响应

ngx.say

输出响应,自动添加'\n'

ngx.flush

刷新响应

ngx.exit

结束请求

ngx.eof

 

ngx.sleep

无阻塞的休眠(使用定时器实现)

ngx.get_phase

 

ngx.on_abort

注册client断开请求时的回调函数

ndk.set_var.DIRECTIVE

 

ngx.req.start_time

请求的开始时间

ngx.req.http_version

请求的HTTP版本号

ngx.req.raw_header

请求头(包括请求行)

ngx.req.get_method

请求方法

ngx.req.set_method

请求方法重载

ngx.req.set_uri

请求URL重写

ngx.req.set_uri_args

 

ngx.req.get_uri_args

获取请求参数

ngx.req.get_post_args

获取请求表单

ngx.req.get_headers

获取请求头

ngx.req.set_header

 

ngx.req.clear_header

 

ngx.req.read_body

读取请求体

ngx.req.discard_body

扔掉请求体

ngx.req.get_body_data

 

ngx.req.get_body_file

 

ngx.req.set_body_data

 

ngx.req.set_body_file

 

ngx.req.init_body

 

ngx.req.append_body

 

ngx.req.finish_body

 

ngx.req.socket

 

ngx.escape_uri

字符串的url编码

ngx.unescape_uri

字符串url解码

ngx.encode_args

将table编码为一个参数字符串

ngx.decode_args

将参数字符串编码为一个table

ngx.encode_base64

字符串的base64编码

ngx.decode_base64

字符串的base64解码

ngx.crc32_short

字符串的crs32_short哈希

ngx.crc32_long

字符串的crs32_long哈希

ngx.hmac_sha1

字符串的hmac_sha1哈希

ngx.md5

返回16进制MD5

ngx.md5_bin

返回2进制MD5

ngx.sha1_bin

返回2进制sha1哈希值

ngx.quote_sql_str

SQL语句转义

ngx.today

返回当前日期

ngx.time

返回UNIX时间戳

ngx.now

返回当前时间

ngx.update_time

刷新时间后再返回

ngx.localtime

 

ngx.utctime

 

ngx.cookie_time

返回的时间可用于cookie值

ngx.http_time

返回的时间可用于HTTP头

ngx.parse_http_time

解析HTTP头的时间

ngx.re.match

 

ngx.re.find

 

ngx.re.gmatch

 

ngx.re.sub

 

ngx.re.gsub

 

ngx.shared.DICT

 

ngx.shared.DICT.get

 

ngx.shared.DICT.get_stale

 

ngx.shared.DICT.set

 

ngx.shared.DICT.safe_set

 

ngx.shared.DICT.add

 

ngx.shared.DICT.safe_add

 

ngx.shared.DICT.replace

 

ngx.shared.DICT.delete

 

ngx.shared.DICT.incr

 

ngx.shared.DICT.flush_all

 

ngx.shared.DICT.flush_expired

 

ngx.shared.DICT.get_keys

 

ngx.socket.udp

 

udpsock:setpeername

 

udpsock:send

 

udpsock:receive

 

udpsock:close

 

udpsock:settimeout

 

ngx.socket.tcp

 

tcpsock:connect

 

tcpsock:sslhandshake

 

tcpsock:send

 

tcpsock:receive

 

tcpsock:receiveuntil

 

tcpsock:close

 

tcpsock:settimeout

 

tcpsock:setoption

 

tcpsock:setkeepalive

 

tcpsock:getreusedtimes

 

ngx.socket.connect

 

ngx.thread.spawn

 

ngx.thread.wait

 

ngx.thread.kill

 

coroutine.create

 

coroutine.resume

 

coroutine.yield

 

coroutine.wrap

 

coroutine.running

 

coroutine.status

 

ngx.config.debug

编译时是否有 --with-debug选项

ngx.config.prefix

编译时的 --prefix选项

ngx.config.nginx_version

返回nginx版本号

ngx.config.nginx_configure

返回编译时 ./configure的命令行选项

ngx.config.ngx_lua_version

返回ngx_lua模块版本号

ngx.worker.exiting

当前worker进程是否正在关闭(如reload、shutdown期间)

ngx.worker.pid

返回当前worker进程的pid

 

 

 

 

 

 

常量

说明

Core constants

ngx.OK (0)

ngx.ERROR (-1)

ngx.AGAIN (-2)

ngx.DONE (-4)

ngx.DECLINED (-5)

ngx.nil

HTTP method constants

ngx.HTTP_GET

ngx.HTTP_HEAD

ngx.HTTP_PUT

ngx.HTTP_POST

ngx.HTTP_DELETE

ngx.HTTP_OPTIONS 

ngx.HTTP_MKCOL   

ngx.HTTP_COPY     

ngx.HTTP_MOVE    

ngx.HTTP_PROPFIND

ngx.HTTP_PROPPATCH

ngx.HTTP_LOCK

ngx.HTTP_UNLOCK   

ngx.HTTP_PATCH  

ngx.HTTP_TRACE  

HTTP status constants

ngx.HTTP_OK (200)

ngx.HTTP_CREATED (201)

ngx.HTTP_SPECIAL_RESPONSE (300)

ngx.HTTP_MOVED_PERMANENTLY (301)

ngx.HTTP_MOVED_TEMPORARILY (302)

ngx.HTTP_SEE_OTHER (303)

ngx.HTTP_NOT_MODIFIED (304)

ngx.HTTP_BAD_REQUEST (400)

ngx.HTTP_UNAUTHORIZED (401)

ngx.HTTP_FORBIDDEN (403)

ngx.HTTP_NOT_FOUND (404)

ngx.HTTP_NOT_ALLOWED (405)

ngx.HTTP_GONE (410)

ngx.HTTP_INTERNAL_SERVER_ERROR (500)

ngx.HTTP_METHOD_NOT_IMPLEMENTED (501)

ngx.HTTP_SERVICE_UNAVAILABLE (503)

ngx.HTTP_GATEWAY_TIMEOUT (504) 

Nginx log level constants

ngx.STDERR

ngx.EMERG

ngx.ALERT

ngx.CRIT

ngx.ERR

ngx.WARN

ngx.NOTICE

ngx.INFO

ngx.DEBUG