openresty中的lua-resty-core和nginx-lua-module 的API 效率对比

2022-07-30 10:48:18

Table of Contents

背景

一、lua-resty-core 是什么?

1、介绍

2、Nginx API for lua 在lua-resty-core中怎么实现的

二、lua-resty-core 和nginx-lua-module API执行效率对比

1、介绍

2、实例对比

三、为什么在openresty中要使用lua-resty-core这个lua模块


背景

    最近在开发高铁CDN项目,由于我们的边缘节点的系统不是标准的centos(而是openwrt),所以在搭建lua-ngx开发环境中就遇到很多问题,最主要的问题是不能直接使用openresty这个平台。为了在nginx 中引入lua,我不得不考虑在ningx中把nginx-lua-module模块编译进来,此外,还需要在openwrt中编译出luajit。关于在openwrt系统中nginx-lua-module,请参考我的另外一篇博文openwrt中编译nginx-lua-module模块

     在openwrt中编译nginx-lua-module模块时,我就在想,nginx-lua-moudle里面已经有的lua API 为什么还要在openresty中的一个核心库lua-resty-core中重新实现一遍。我这里说的lua API 指的就是Nginx API for Lua,下面是一小部分API 截图。

     其实,lua-nginx-module 提供的 API,并不是完全意义上的用 C 实现的。准确来说,是通过 C 实现,并通过 Lua CFunction 暴露出来的。而 lua-resty-core 提供的 API,也不是表面看上去那样用 Lua 实现的。准确来说,是通过在 lua-nginx-module 里面的以*_lua_ffi_* 形式命名的 C 函数实现的,并在 lua-resty-core 里面通过 LuaJIT FFI 暴露出来的。所以其实两者都是 C 实现。两者的比较,就是 Lua CFunction 和 LuaJIT FFI 的比较。后续我会对他们的效率进行对比,好了,咱们直接进入正题:

一、lua-resty-core 是什么?

1、介绍

    lua-resty-core是openresty的一个核心库,看过lua-resty-core 源码的同学,应该知道,lua-resty-core 有两个文件目录,分别是:ngx和core。 resty.core 里面是对nginx-lua-module已有接口的实现;resty.ngx里面是一些新的接口,并且后续新的接口都会放在resty.ngx里面。

2、Nginx API for lua 在lua-resty-core中怎么实现的

    我们以ngx.req.get_headers这个指令为例。

    首先,nginx-lua-module里面已经通过C语言实现了相关接口,接口命名格式为:ngx_http_lua_ffi_**,比如:

   最后,在resty.core.*中通过luaJit FFi把该接口暴露出来,如下图:

  总结一下luajit 中通过ffi 去调用C函数的过程,大概的过程一遍如下:

local ffi = require("ffi")
local C = ffi.C
ffi.cdef[[
  int sum(int a, inb b); 这个就是你c函数名, 你要提前把你的C代码编译成.so
]]
local a=1
local b=4
C.sum(1, 4)

二、lua-resty-core 和nginx-lua-module API执行效率对比

1、介绍

     nginx-lua-module里面已经有的接口为啥还要在lua-resty-core中重新实现一遍呢,难道是吃饱了没事干么,其实,真实原因是lua-resy-core实现的这套接口效率更高,在对比之前,我们下简单说下luajit FFi

     LuaJIT FFI 的实现深深地根植于解释器自身。如果当前 LuaJIT 正处于 JIT 模式,它会在 FFI 调用时优化 Lua 领域和 C 领域间传参和返回的过程,因此采用 FFI 要比直接调用 Lua CFunction 要快。至于能快多少,则取决于调用时两个领域间数据交换频繁情况。

2、实例对比

nginx 的设置:

http {
    include       mime.types;
    lua_code_cache off;
    lua_package_path '/u01/lua_ngcdn/lua_package/lua/?.lua;;';
   
     .............

 
    server {
        listen       81;
        server_name  localhost;
        #access_log  /etc/nginx/logs/access_81.log  main;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location /time {
            content_by_lua_file /u01/lua_ngcdn/lua/test.lua;
        }
    }

1)、关闭luajit 的FFI的调用方式:

  nginx.conf 中注释掉lua_package_path:

http {
    include       mime.types;
    lua_code_cache off;
    #lua_package_path '/u01/lua_ngcdn/lua_package/lua/?.lua;;';

test.lua文件中:

--下面这一行要注释掉
--require "resty.core"
local s = ("test"):rep(256)
local start = ngx.now()
for _ = 1, 1e8 do
    ngx.ctx.test = s
    local r = ngx.ctx.test
end
ngx.update_time()
ngx.say(ngx.now() - start)

耗时如下:

2)、开启luajit 的FFI的调用方式:

http {
    include       mime.types;
    lua_code_cache off;
    lua_package_path '/u01/lua_ngcdn/lua_package/lua/?.lua;;';
require "resty.core"
local s = ("test"):rep(256)
local start = ngx.now()
for _ = 1, 1e8 do
    ngx.ctx.test = s
    local r = ngx.ctx.test
end
ngx.update_time()
ngx.say(ngx.now() - start)

运行结果:

三、为什么在openresty中要使用lua-resty-core这个lua模块

    通过上面的对比实验,相信各个小伙伴已经明白了,lua-resty-core实现的这个接口效率比 nginx-lua-module实现的接口要高出10倍左右。当然,不同平台下数据会不同,但是总的说来,lua-resty-core实现的接口还是要高不少的。

    你可能会觉得,我们的项目不需要什么性能上的优化,所以也无需引入 lua-resty-core。春哥之前说过有计划淘汰掉现有的一套 Lua CFunction 接口。所以迟早你也会用上 lua-resty-core 所暴露的接口。还有,OpenResty 目前新的功能开发,都是放到 lua-resty-core 上的。所以,你迟早都会切到openresty平台上面来。

   题外话: 笔者新增一个开发国外直播服务器的网站,各位直播这块的大神可以找我一起讨论讨论,网站链接:网站

  • 作者:stefan1240
  • 原文链接:https://blog.csdn.net/stefan1240/article/details/105784754
    更新时间:2022-07-30 10:48:18