openresty程序开发(Nginx+Lua)

单纯的说openresty开发的话,网上已经有了相当成熟的教程。因此笔者就不多此一举,本篇就写一些关于初学者才到的一些坑。

1、项目结构介绍

当openresty安装完成之后,目录如下:

这些目录目前笔者主要介绍两个lualib和nginx。lualib为openresty依赖的第三方库。在后面的开发当中,如果需要引用拓展的第三方库,则一般情况下都是放在lualib下面。

对于nginx目录,里面就是nginx软件本身。目录如下:

在这里,*_temp的目录就不多说了,这个是nginx运行时产生的用于数据处理的临时目录。其他几个目录,熟悉nginx的都应该比较清楚。conf这里保存了nginx的配置信息,主要用到nginx.conf;html目录主要用于存放html、css、js等静态数据;logs用于存储访问日志和错误日志等;sbin目录存放了nginx的启动、停用的相关命令。

在这里笔者多加了一个lua目录,这个用于存放lua写的业务代码。对于其他的文件目录在这里就不多介绍了,这里主要介绍lua下面的目录结构。因为笔者是java开发出身,因此本项目的项目结构还是类似于Java项目。如下所示:

common主要存放一些通用的工具包,如统一返回对象result等;controller主要存放用于接收前端请求的入口;libs主要用于存放一些自己写的通用工具,类似于java中的DateUtils等;service则用于处理业务逻辑数据,这其中也包含了连库的操作(因为如果选择了openresty作为开发架构,一般来说并不会将项目做的很重,大型系统的话主要还要依赖后端其他语言写的系统。openresty更为轻量级,因此项目分层的粒度可以大一些。)。

看到这里读者应该还会留意到,还有一个dispatch目录,这个是用于分发HTTP请求的逻辑。一般来说,nginx本身就有了这种请求分发的功能。但是当接口变多的时候,就会造成nginx.conf的配置变得很多,难以维护。此时我们可以将前端所有的接口请求分发dispatch.lua上面去,然后再dispatch中再根据URI规则进行pcall调用controller中的代码。

该项目的下载地址为:https://github.com/Fouy/openresty-blog

2、开发过程中踩过的一些坑

lua_package_path配置问题:初次为openresty增加lua代码的时候,老是报出找不到.lua文件。当时比较郁闷的是,openresty堆栈中打出的日志的path中有响应的lua模块,如下所示:

后来查到因为lua_package_path配置的问题,修改配置为以下之后,确实可以访问了

lua_package_path "/Users/xuefeihu/software/openresty/nginx/lua/?.lua;/Users/xuefeihu/software/openresty/lualib/?.lua;;";

其中两个分别为openresty重lualib中的模块和用户自己写的逻辑模块。但是从上述日志可以看出,openresty已经找到了路径,却还报出了不存在,甚是疑惑。

使用ngx.header设置响应头问题:当在controller中使用ngx.say()向前端输出字节流的时候,openresty的Content-Type的值是:application/octet-stream。这个指的是无类型,字节流。

这个对于普通的ajax接口交互并没有什么问题,当使用lua-resty-template 进行模板渲染时,被浏览器识别为数据,从而触发了下载的动作。通过实验发现如下:

    # 业务代码
    local list = article_service:list(args)
	local typeList = article_type_service:list()
	local context = {list = list, pageNo = tonumber(args["pageNo"])+1, typeList = typeList }
	
	ngx.header["Content-Type"] = 'text/html;charset=UTF-8'
	template.render("blog/index.html", context)

ngx.header的设置需要在template.render之前才有效。

openresty接收大文本造成数据丢失的问题:对于HTTP来说POST本身并没有提交数据的长度限制,具体大小都是在服务器端设置的。

这个限制不是openresty限制,是Nginx本身就有请求体的大小限制,从而以保持其高效性。需要在nginx.conf的http中设置如下:

    client_max_body_size 10M;
    client_body_buffer_size 10M;