Linux下Nginx环境搭建OpenResty(Nginx+Lua)

一.简介

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

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

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

总结和拓展:

  • OpenResty 是 Nginx 与 Lua 的结合;
  • OpenResty 是多进程模式,会有一个 master 进程和多个 worker 进程。Master 进程管理 worker 进程,向各 worker 进程发送信号,监控 work 进程状态;
  • OpenResty 是异步非阻塞 ;怎样理解阻塞非阻塞与同步异步的区别?知乎
  • 子查询:OpenResty 中有三种方式发起子请求:capture、exec、redirect;
  • OpenResty 缓存机制。

Nginx+Lua架构思维导图:

window 环境开发nginx 插件_nginx

二.yum安装

对于一些常见的 Linux 发行版本,OpenResty® 提供 官方预编译包。确保你首先用这种方式来安装。

你可以在你的 CentOS 系统中添加 openresty 仓库,这样就可以便于未来安装或更新我们的软件包(通过 yum update 命令)。运行下面的命令就可以添加我们的仓库:

yum install yum-utils -y
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo

然后就可以像下面这样安装软件包,比如 openresty:

yum install openresty -y

如果你想安装命令行工具 resty,那么可以像下面这样安装 openresty-resty 包:

yum install openresty-resty -y

命令行工具 opm 在 openresty-opm 包里,而 restydoc 工具在 openresty-doc 包里头。

列出所有 openresty 仓库里头的软件包:

yum --disablerepo="*" --enablerepo="openresty" list available

参考 OpenResty RPM 包页面获取这些包更多的细节。

三.源码包编译安装

下载
从下载页 Download下载最新的 OpenResty 源码包,并且像下面的示例一样将其解压:

wget https://openresty.org/download/openresty-1.13.6.2.tar.gz

安装前的准备

必须将这些库 perl 5.6.1+, libpcre, libssl安装在您的电脑之中。 对于 Linux来说, 您需要确认使用 ldconfig 命令,让其在您的系统环境路径中能找到它们。

推荐您使用yum安装以下的开发库:

yum install pcre-devel openssl-devel gcc curl -y

安装

tar -zxvf openresty-1.13.6.2.tar.gz
cd openresty-1.13.6.2
./configure
make
make install

如果您的电脑支持多核 make 工作的特性, 您可以这样编译:

make -j2

默认, --prefix=/usr/local/openresty 程序会被安装到/usr/local/openresty目录。您可以指定各种选项,比如:

./configure --prefix=/opt/openresty \
            --with-luajit \
            --without-http_redis2_module \
            --with-http_iconv_module \
            --with-http_postgres_module

试着使用 ./configure --help 查看更多的选项。

四.配置


第一种常规配置方案
修改nginx.conf配置文件

cd /usr/local/openresty/nginx/conf
mv nginx.conf nginx.conf.$(date +%Y%m%d)
vim nginx.conf
worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}
http {
    server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>hello, world</p>")
            ';
        }
    }
}

添加环境变量

echo "export PATH=$PATH:/usr/local/openresty/nginx/sbin" >> /etc/profile
source /etc/profile

然后启动openresty,启动命令和nginx一致。

nginx -c /usr/local/openresty/nginx/conf/nginx.conf

启动后查看一下服务

ps -ef | grep  nginx

访问 Web 服务

curl http://localhost:8080/

如果一切正常,我们应该得到输出

<p>hello, world</p>

重启 Web 服务

nginx -s reload

第二种lua配置方案

添加lua.conf配置文件

server {
        listen 8080;
        location / {
            default_type text/html;
            content_by_lua '
                ngx.say("<p>hello, world Lua!</p>")
            ';
        }
    }

修改nginx.conf配置文件

cd /usr/local/openresty/nginx/conf
mv nginx.conf nginx.conf.$(date +%Y%m%d)
vim nginx.conf

worker_processes  1;
error_log logs/error.log;
events {
    worker_connections 1024;
}

http {
    #lua模块路径,多个之间”;”分隔,其中”;;”表示默认搜索路径,默认到/usr/servers/nginx下找  
    lua_package_path "/usr/local/openresty/lualib/?.lua;;";  #lua模块
    lua_package_cpath "/usr/local/openresty/lualib/?.so;;";  #c模块 
    include lua.conf; #lua.conf和nginx.conf在同一目录下
}

添加环境变量

echo "export PATH=$PATH:/usr/local/openresty/nginx/sbin" >> /etc/profile
source /etc/profile

然后启动openresty,启动命令和nginx一致。

nginx -c /usr/local/openresty/nginx/conf/nginx.conf

访问 Web 服务

curl http://localhost:8080/

如果一切正常,我们应该得到输出

<p>hello, world Lua!</p>

配置lua代码文件

我们把lua代码放在nginx配置中会随着lua的代码的增加导致配置文件太长不好维护,因此我们应该把lua代码移到外部文件中存储。

在conf文件夹下创建lua文件夹,专门用来存放lua文件

mkdir /usr/local/openresty/nginx/conf/lua

创建test.lua文件

cd /usr/local/openresty/nginx/conf/lua
vim test.lua
ngx.say("test lua");

修改conf/lua.conf文件

vim /usr/local/openresty/nginx/conf/lua.conf
server {
        listen 8080;
        location / {
            default_type text/html;
            lua_code_cache off; #关闭lua代码缓存,调试时关闭,正式环境开启
            content_by_lua_file conf/lua/test.lua; #相对于nginx安装目录
        }
    }

关闭缓存后会看到如下报警(忽略不管)

nginx: [alert] lua_code_cache is off; this will hurt performance in /usr/local/openresty/nginx/conf/lua.conf:5

明天继续

lua连接redis集群

连接redis集群需要用到llua-resty-redis-cluster模块

github地址:https://github.com/taohuadeng/resty-redis-cluster

下载完成后,只需要用到包中2个文件rediscluster.lua和redis_slot.c

.c文件无法在nginx配置文件中引入,需要编译成.so文件,编译命令: gcc SOURCE_FILES -fPIC -shared -o TARGET

# 根据实际文件引用命名即可,存放路径需要和使用处一致
yum install lua-dev
gcc redis_slot.c -fPIC -shared -o libredis_slot.so
gcc redis_slot.c -fPIC -shared -o librestyredisslot.so

如果报错:

[root@eln167 lualib]# gcc redis_slot.c -fPIC -shared -o libredis_slot.so
redis_slot.c:1:17: fatal error: lua.h: No such file or directory
#include <lua.h>
^
compilation terminated.
修改redis_slot.c文件头文件指定路径
#include “/usr/local/openresty/luajit/include/luajit-2.1/lua.h”
#include “/usr/local/openresty/luajit/include/luajit-2.1/lualib.h”
#include “/usr/local/openresty/luajit/include/luajit-2.1/lauxlib.h”
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

将文件libredis_slot.so放到/usr/local/openresty/lualib目录

将文件rediscluster.lua放到/usr/local/openresty/lualib/resty目录下

使用示例:
nginx.conf添加:
lua_shared_dict redis_cluster_slot_locks 100k;

#keepalive_timeout 0;
keepalive_timeout 65;
#添加项,必须
lua_shared_dict redis_cluster_slot_locks 100k;

redirectClusteTest.lua

local config = {
    name = "TaoFadeng",                   --rediscluster name
    serv_list = {                           --redis cluster node list(host and port),
        { ip = "192.168.0.250", port = 9991 },
        { ip = "192.168.0.250", port = 9992 },
        { ip = "192.168.0.250", port = 9993 },
        { ip = "192.168.0.66", port = 9991 },
        { ip = "192.168.0.66", port = 9992 },
        { ip = "192.168.0.66", port = 9993 }
    },
    keepalive_timeout = 60000,              --redis connection pool idle timeout
    keepalive_cons = 1000,                  --redis connection pool size
    connection_timout = 1000,               --timeout while connecting
    max_redirection = 5                     --maximum retry attempts for redirection,
    --auth = "password"                       --set password while setting auth, Notice no auth no set!
}

local redis_cluster = require "rediscluster"
local cache = redis_cluster:new(config)

local path = 'http://veln.qgutech.com/veln';
if not cache then
    ngx.redirect(path);
end

local m = string.len(ngx.var.request_uri)
local code = string.sub(ngx.var.request_uri, 5, m)

local res, err = cache:hget('SHORT_LINK',code)
if not res then
    ngx.redirect(path);
end

if res == ngx.null then
    ngx.redirect(path);
end

ngx.redirect(res);