全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Nginx+lua 实现调用.so文件

最近在和智能硬件部门一起,做一个室内定位的服务,该服务根据手机端传过来的beacon设备列表,根据一定的算法计算出具体的商场,并将商场ID和beason设备列表作为参数,调用.so文件中的计算方法,得出位置数据(坐标:x、y、z),返回给手机端。

因为服务对QPS要求比较高,并且都是纯查询操作,于是决定使用Nginx+lua+Redis的架构(该架构在公司内部已成主流,比较成熟)。下面我将对lua调用.so文件的方式,做一下介绍。

lua调用.so文件,主要有两种方式:

1.Lua直接调用动态链接库,具体可参考 技术分享 。
2.使用C写一个Wrapper。

鉴于第一种方式需要引入第三方工具包,并且效率不高,所以我们采用第二种方式来实现。具体实现过程如下:

1.编写业务代码,其中包括业务方法的封装器。

  static int lua_Locate( lua_State* L )
  {
    long handle = lua_tonumber( L, 1 );
    const char* beacon_rssi_json = lua_tostring( L, 2 );

    vector<RSSI_INFO> rssi_info_vec;

    FingerprintLocationServer* p = (FingerprintLocationServer*)handle;

    ConvertJson2CppRSSI( beacon_rssi_json, rssi_info_vec );

    double x;
    double y;
    float floor;

    p->UpdateBeaconSignalGetResult( rssi_info_vec, x, y, floor );

    lua_pushnumber(L,x);
    lua_pushnumber(L,y);
    lua_pushnumber(L,floor);

    return 3;
  }

  static const struct luaL_Reg myLib[] =  
  { 
    {"lua_Locate", lua_Locate}, 
    {NULL, NULL}    //数组中最后一对必须是{NULL, NULL},用来表示结束   
  }; 

  int luaopen_mLualib(lua_State *L) 
  { 
    luaL_register(L, "FPCalc", myLib); 
    return 1;    // 把myLib表压入了栈中,所以就需要返回1 
  }

其中,wapper函数的函数名有个命名规则,前缀为luaopen,后面就是lua中require的字符串,否则将会报类似于下面的异常:

lua entry thread aborted: runtime error: error loading module 'mLualib' from file '/var/wdd/wrs/webroot/intelligent_lua/mLualib.so':
  /var/wdd/wrs/webroot/intelligent_lua/mLualib.so: undefined symbol: _Z13lua_tolstringP9lua_StateiPm
stack traceback:
coroutine 0:
  [C]: in function 'require'
  /var/wdd/wrs/webroot/intelligent_lua/location.lua:18: in function...

另外,如果是.cpp文件,在luaopen_mylib一定要加 extern "C", 否则导出的函数会被重命名,切记切记! 关于extern "C",请参考 extern "C" 用法解析。

2.Nginx配置文件中指定so包所在的文件夹。

lua_package_cpath '/var/wdd/wrs/webroot/intelligent_lua/?.so;;';

注意,这里有很多种配置方式,只要让lua能找到so文件即可,比如可以通过lua代码package.cpath来引入(参阅下面代码段)或者直接把so文件复制lua环境变量指定的目录里等。
package.cpath = '/usr/local/lib/lua/5.1/?.so;'        --搜索so模块

如果未指定cpath或者cpath中找不到so文件,系统会报如下异常:

no file './mLualib.lua'
  no file '/usr/local/openresty/luajit/share/luajit-2.1.0-beta1/mLualib.lua'
  no file '/usr/local/share/lua/5.1/mLualib.lua'
  no file '/usr/local/share/lua/5.1/mLualib/init.lua'
  no file '/usr/local/openresty/luajit/share/lua/5.1/mLualib.lua'
  no file '/usr/local/openresty/luajit/share/lua/5.1/mLualib/init.lua'
  no file '/usr/local/openresty/lualib/mLualib.so'
  no file './mLualib.so'
  no file '/usr/local/lib/lua/5.1/mLualib.so'
  no file '/usr/local/openresty/luajit/lib/lua/5.1/mLualib.so'
  no file '/usr/local/lib/lua/5.1/loadall.so'
  no file '/var/wdd/wrs/webroot/intelligent_lua/mLualib.so'

3.lua代码中引入so包,并执行调用。

local FPCalc = require "mLualib"

local x, y, floor = FPCalc.lua_Locate(c_addr, umm_json)

ngx.log(ngx.ERR, "lua_Locate:end:返回结果:", "x=" .. x, " y=" .. y, " floor=" .. floor)

以上就是lua调用.so包全部过程了。

实际压测过程中,还发现了几个问题:

1.so包需要在运行环境上编译,不同的环境编译的so包不一定通用。比如我在mac上编译的so包,直接复制到生产环境(centos系统)就不能使用,需要在生产环境重新编译才可以。

2.编译so包单进程可以正常执行,但是多进程访问时异常,错误信息如下(目前这个问题还没有解决)。

2017/05/03 16:52:41 [notice] 14355#0: signal 17 (SIGCHLD) received
2017/05/03 16:52:41 [alert] 14355#0: worker process 14361 exited on signal 11
2017/05/03 16:52:41 [notice] 14355#0: start worker process 14427
2017/05/03 16:52:41 [notice] 14355#0: signal 29 (SIGIO) received
2017/05/03 16:52:41 [notice] 14427#0: sched_setaffinity(0x00000008)

2017-05-04 终于找到原因:

问题原因:进程在访问.so文件时,需要调用.so中一个初始化方法。这个方法负责初始内存等相关操作,每个进程需要单独调用(初始化)一次,而我所有进程只调用(初始化)了一次,导致部分未初始化的进程执行代码时异常。

解决方式:查到原因了,问题就好解决了,每个进程初始一次就好了。


# nginx调用lua脚本  # nginx  # 调用lua  # 调用so  # nginx源码分析configure脚本详解  # nginx服务器通过配置来解决API的跨域问题  # 详解nginx服务器http重定向到https的正确写法  # 详解Linux中Nginx反向代理下的tomcat集群  # CentOS 7中利用yum安装Nginx的方法教程  # nginx超时设置详细介绍  # Nginx 实现灰度发布的三种方法总结  # 会报  # 都是  # 运行环境  # 还没有  # 我在  # 有个  # 就好  # 这个问题  # 较高  # 工具包  # 可以通过  # 并将  # 而我  # 才可以  # 不高  # 做一个  # 就不能  # 将对  # 要让  # 已成 


相关文章: 如何在Golang中实现微服务服务拆分_Golang微服务拆分与接口管理方法  建站10G流量真的够用吗?如何应对访问高峰?  专业企业网站设计制作公司,如何理解商贸企业的统一配送和分销网络建设?  阿里云网站制作公司,阿里云快速搭建网站好用吗?  智能起名网站制作软件有哪些,制作logo的软件?  广州网站建站公司选择指南:建站流程与SEO优化关键词解析  保定网站制作方案定制,保定招聘的渠道有哪些?找工作的人一般都去哪里看招聘信息?  如何用西部建站助手快速创建专业网站?  代购小票制作网站有哪些,购物小票的简要说明?  简历在线制作网站免费,免费下载个人简历的网站是哪些?  如何登录建站主机?访问步骤全解析  头像制作网站在线制作软件,dw网页背景图像怎么设置?  如何通过网站建站时间优化SEO与用户体验?  如何生成腾讯云建站专用兑换码?  c# F# 的 MailboxProcessor 和 C# 的 Actor 模型  网站制作企业,网站的banner和导航栏是指什么?  建站VPS配置与SEO优化指南:关键词排名提升策略  手机怎么制作网站教程步骤,手机怎么做自己的网页链接?  如何快速搭建高效可靠的建站解决方案?  官网自助建站平台指南:在线制作、快速建站与模板选择全解析  大连网站制作公司哪家好一点,大连买房网站哪个好?  常州自助建站工具推荐:低成本搭建与模板选择技巧  股票网站制作软件,网上股票怎么开户?  家庭服务器如何搭建个人网站?  建站之星24小时客服电话如何获取?  建站之星好吗?新手能否轻松上手建站?  IOS倒计时设置UIButton标题title的抖动问题  制作充值网站的软件,做人力招聘为什么要自己交端口钱?  制作网站建设的公司有哪些,网站建设比较好的公司都有哪些?  江苏网站制作公司有哪些,江苏书法考级官方网站?  建站之星CMS建站配置指南:模板选择与SEO优化技巧  建站之星安装后界面空白如何解决?  长沙企业网站制作哪家好,长沙水业集团官方网站?  油猴 教程,油猴搜脚本为什么会网页无法显示?  c++怎么用jemalloc c++替换默认内存分配器【性能】  网站设计制作公司地址,网站建设比较好的公司都有哪些?  如何挑选最适合建站的高性能VPS主机?  黑客入侵网站服务器的常见手法有哪些?  如何在万网ECS上快速搭建专属网站?  如何做静态网页,sublimetext3.0制作静态网页?  如何通过虚拟主机快速搭建个人网站?  交易网站制作流程,我想开通一个网站,注册一个交易网址,需要那些手续?  广州美橙建站如何快速搭建多端合一网站?  建站之星在线版空间:自助建站+智能模板一键生成方案  网站按钮制作软件,如何实现网页中按钮的自动点击?  如何快速查询网址的建站时间与历史轨迹?  免费视频制作网站,更新又快又好的免费电影网站?  高防服务器租用如何选择配置与防御等级?  昆明高端网站制作公司,昆明公租房申请网上登录入口?  零服务器AI建站解决方案:快速部署与云端平台低成本实践 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。