咱们在作Asterisk功能开发的时候,除了直接用C写模块以前,更经常使用的方法是用本身熟悉的语言来开发本身的业务逻辑,这个时候就须要用到AGI的功能。通常比较多的选择是:PHP,Perl,JAVA 来实现。JAVA由于是FASTAGI的方式,故效果会比PHP,Perl好点,由于PHP,Perl是脚本语音,须要进行编译操做,故这个CPU消耗仍是比较大的。 另一种方式是asterisk 的dialplan 是能够直接支持lua 脚原本编写,这个就很方便来用lua 来作扩展。通过实测使用Lua方式来作嵌入式来扩展业务,这个性能确实有质的飞跃。 故本次将介绍使用Lua来写dialPlan。 官方文档指引,请参考: https://wiki.asterisk.org/wiki/display/AST/Lua+Dialplan+Configuration 经过官方文档的介绍,其实extensions.lua 其实就是一个lua 脚本,直接在上面写代码便可。 关于数据存储的选择技巧: 若是要快速响应呼叫请求,能够利用redis 来作缓存,使用redis 的列表功能进行消息推送。把话单和通话状态经过外部的监控服务来推送到MySQL。 通过上面的改造后,Asterisk的性能获得了很大的提高,下面是具体的测试效果: CPU型号: Intel(R) Core(TM) i3-4020Y CPU @ 1.50GHz CPU个数:4 内存:4G Asterisk版本:Asterisk 13.21.0 上面安装了2套Asterisk,一套作接入转码,一套作模拟正常的30%的接通率。 稳定并发:150线并发 一台微型小机器,便可知足大部分公司的业务需求。 下面附上lua dialplan 的使用例子:
function hangup() app.Hangup() end function verbose(msg) app.Verbose('"' .. msg .. '"') end function noop(msg) app.Noop('"' .. msg .. '"') end function dial(dialstr) app.Dial(dialstr) end function getChannelItem(item) return channel.CHANNEL('"' .. item .. '"'):get() end function getCallerIdItem(item) return channel.CALLERID('"' .. item .. '"'):get() end function getVar(key) -- key : CALLERID(num) ,EXTEN , CHANNEL return channel[key]:get(); end function setVar(key,val) channel[key] = val; end e = {}; e.default = {}; e.default["_X."] = function(context,exten) app.Noop("incoming call to default") app.Hangup() end; e.TO_EXT_UserName = {}; e.TO_EXT_UserName["_X."] = function(context,exten) local peerIp = channel.CHANNEL('peerip'):get() local userAgent = channel.CHANNEL('useragent'):get() local uriHeader = channel.CHANNEL('ruri'):get() local from = channel.CHANNEL('from'):get() local concat = getChannelItem('uri') local caller = getCallerIdItem('num'); local callerName = getCallerIdItem('name') local uniqueid = getVar('UNIQUEID'); local channelName = getVar('CHANNEL'); setVar('CALLERID(num)','+8615875329063') local msg = 'incoming call: ' .. peerIp .. ',useragent: '.. userAgent .. ',request uri: ' .. uriHeader ..',from header: ' .. from .. ',concat header: ' .. concat ; verbose(msg); msg = "caller: " .. caller ..",callerName: " .. callerName ..',uniqueid: ' .. uniqueid .. ',channel name: ' .. channelName; noop(msg); caller = getVar('CALLERID(num)'); noop("Your new callerid is: " .. caller) local res = dial("SIP/IMS_PROXY/" .. exten .. ',45,geU(sub_record_ims^s)') hangup() end; e.TO_EXT_UserName["h"] = function(context,exten) local msg = ''; local caller = getCallerIdItem('num'); local callerName = getCallerIdItem('name') local uniqueid = getVar('UNIQUEID'); local duration = getVar('DIALEDTIME'); if duration == nil or duration == '' then duration = 0; end local billsec = getVar('ANSWEREDTIME'); if billsec == nil or billsec == '' then billsec = 0; end local dialresult = getVar('DIALSTATUS'); if dialresult == nil then dialresult = '' end -- 获取挂断通道名称 local hangupCauseString = getVar('HANGUPCAUSE_KEYS()'); msg = "hangup==> caller: " .. caller .. ',is hangup,uniqueid='.. uniqueid .. ',duration='.. duration .. ',billsec='.. billsec .. ',result: ' .. dialresult; noop(msg) -- 获取挂断缘由SIP代码 local hangupCause = getVar('HANGUPCAUSE("' .. hangupCauseString ..'",tech)'); msg = "hangup by: " .. hangupCauseString .. ',hangupCause: ' .. hangupCause; noop(msg) end; e.sub_record_ims = {}; e.sub_record_ims['s'] = function(context,exten) -- 当被叫接通主叫前执行 local msg = ""; local caller = getCallerIdItem('num'); local callerName = getCallerIdItem('name') local uniqueId = getVar('UNIQUEID'); msg = "caller: " .. caller .. ',callerName: ' .. callerName .. ',uniqueId: ' .. uniqueId .. ' is answered ...'; noop(msg); app['Return'](); end extensions = e;