在 OpenResty 中,连接池在使用上如果不加以注意,容易产生数据写错地方,或者得到的应答数据异常以及类似的问题,当然使用短连接可以规避这样的问题,但是在一些企业用户环境下,短连接 + 高并发对企业内部的防火墙是一个巨大的考验,因此,长连接自有其用武之地,使用它的时候要记住,长连接一定要保持其连接池中所有连接的正确性。
===========执行阶段和主要函数请参考HttpLuaModule#ngx.shared.DICT非队列性质ngx.shared.DICT 的实现是采用红黑树实现,当申请的缓存被占用完后如果有新数据需要存储则采用 LRU 算法淘汰掉“多余”数据。
在应用开发中,经常会有对请求进行限速的需求。通常意义上的限速,其实可以分为以下三种:limit_rate 限制响应速度limit_conn 限制连接数limit_req 限制请求数接下来让我们看看,这三种限速在 OpenResty 中分别怎么实现。限制响应速度Nginx 有一个 $limit_rate,这个变量反映的是当前请求每秒能响应的字节数。该字节数默认为配置文件中 limit_rate 指令的设值。
本章内容来自openresty讨论组 这里先看两段代码:-- index.lualocal uri_args = ngx.req.get_uri_args()local mo = require('mo')mo.args = uri_args-- mo.lualocal showJs = function(callback, data) local cjson = require('cjson') ngx.say(callback .. '(' .. cjson.encode(data) .. ')')endlocal self.jsonp = self.args.
Lua 的解析器有官方的 standard Lua 和 LuaJIT,需要明确一点的是目前大量的优化文章都比较陈旧,而且都是针对 standard Lua 解析器的,standard Lua 解析器在性能上需要书写者自己规避,才能写出高性能来。需要各位看官注意的是,OpenResty 最新版默认已经绑定 LuaJIT,优化手段和方法已经略有不同。
调试是一个程序猿非常重要的能力,人写的程序总会有 bug,所以需要 debug。如何方便和快速的定位 bug,是我们讨论的重点,只要 bug 能定位,解决就不是问题。对于熟悉用 Visual Studio 和 Eclipse 这些强大的集成开发环境的来做 C++ 和 Java 的同学来说,OpenResty 的 debug 要原始很多,但是对于习惯 Python 开发的同学来说,又是那么的熟悉。
在一些请求中,我们会做一些日志的推送、用户数据的统计等和返回给终端数据无关的操作。而这些操作,即使你用异步非阻塞的方式,在终端看来,也是会影响速度的。这个和我们的原则:终端请求,需要用最快的速度返回给终端,是冲突的。这时候,最理想的是,获取完给终端返回的数据后,就断开连接,后面的日志和统计等动作,在断开连接后,后台继续完成即可。怎么做到呢?
不同的业务应用场景,会有完全不同的非法终端控制策略,常见的限制策略有终端 IP 、访问域名端口,这些可以通过防火墙等很多成熟手段完成。可也有一些特定限制策略,例如特定 cookie、url、location,甚至请求 body 包含有特殊内容,这种情况下普通防火墙就比较难限制。
在请求返回后继续执行章节中,我们介绍了一种实现的方法,这里我们介绍一种更优雅更通用的方法:ngx.timer.at()。ngx.timer.at 会创建一个 Nginx timer。在事件循环中,Nginx 会找出到期的 timer,并在一个独立的协程中执行对应的 Lua 回调函数。有了这种机制,ngx_lua 的功能得到了非常大的扩展,我们有机会做一些更有想象力的功能出来。比如批量提交和 cron 任务。
这是一个比较常见的功能,你会怎么做呢?Google 一下,你会找到Lua 的官方指南,里面介绍了 10 种 sleep 不同的方法(操作系统不一样,方法还有区别),选择一个用,然后你就杯具了:( 你会发现 Nginx 高并发的特性不见了!在 OpenResty 里面选择使用库的时候,有一个基本的原则:尽量使用 OpenResty 的库函数,尽量不用 Lua 的库函数,因为 Lua 的库都是同步阻塞的。
缓存的原则缓存是一个大型系统中非常重要的一个组成部分。在硬件层面,大部分的计算机硬件都会用缓存来提高速度,比如 CPU 会有多级缓存、RAID 卡也有读写缓存。
OpenResty 的诞生,一直对外宣传是同步非阻塞(100% non-blocking)的。基于事件通知的 Nginx 给我们带来了足够强悍的高并发支持,但是也对我们的编码有特殊要求。这个特殊要求就是我们的代码,也必须是非阻塞的。如果你的服务端编程生涯一开始就是从异步框架开始的,恭喜你了。但如果你的编程生涯是从同步框架过来的,而且又是刚刚开始深入了解异步框架,那你就要小心了。
在 OpenResty 中,提及热加载代码,估计大家的第一反应是 lua_code_cache 这个开关。但 lua_code_cache off 的工作原理,是给每个请求创建一个独立的 Lua VM。即使抛去性能因素不谈,考虑到程序的正确性,也不应该在生产环境中关闭 lua_code_cache。那么我们是否可以在生产环境中完成热加载呢?代码有变动时,自动加载最新 Lua 代码,但是 Nginx 本身,不做任何 reload。
看过本章第一节的同学应该还记得,log_by_lua* 是一个请求经历的最后阶段。由于记日志跟应答内容无关,Nginx 通常在结束请求之后才更新访问日志。由此可见,如果我们有日志输出的情况,最好统一到 log_by_lua* 阶段。如果我们把记日志的操作放在 content_by_lua* 阶段,那么将线性的增加请求处理时间。
OpenResty 处理一个请求,它的处理流程请参考下图(从 Request start 开始):我们在这里做个测试,示例代码如下:location /mixed { set_by_lua_block $a { ngx.log(ngx.ERR, "set_by_lua*") } rewrite_by_lua_block { ngx.log(ngx.ERR, "rewrite_by_lua*") } access_by_lua_block { ngx.log(ngx.
有使用 SQL 语句操作数据库的经验朋友,应该都知道使用 SQL 过程中有一个安全问题叫 SQL 注入。所谓 SQL 注入,就是通过把 SQL 命令插入到 Web 表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的 SQL 命令。为了防止 SQL 注入,在生产环境中使用 OpenResty 的时候就要注意添加防范代码。
当我们所有数据库的 SQL 语句是通过子查询方式完成,对于超时的控制往往很容易被大家忽略。因为大家在代码里看不到任何调用 set_timeout 的地方。实际上 PostgreSQL 已经为我们预留好了两个设置。请参考下面这段配置:location /postgres { internal; default_type text/html; set_by_lua_block $query_sql {return ngx.unescape_uri(ngx.var.
关注时代Java