luanet分布式lua框架


luanet最初只是一個網絡框架,它簡單的封裝了一些網絡相關接口然后暴露到lua中,讓lua可以構建簡單的網絡應用.

隨着我的手游服務器的開發,我發現在C語言中要實現一個簡潔易用的RPC調用接口並不容易,於是開始考慮將整個服務器框架從主C,

輔lua的模式轉變成主lua,輔C的模式.網絡通訊,異步日志等一些在lua中無法實現或cpu消耗大的組件由C語言實現注冊到lua中.由lua

組合這些組件來實現一 個分布式的網絡框架.

進入主題,首先簡單的介紹luanet的特性:

  • 單線程(日志另開一個線程用於往磁盤異步寫)

  • 支持TCP,UDP,UNIX域套接字

  • 提供面向消息和RPC的通訊方式

  • 利用coroutine實現同步的遠程調用接口

  • 談化連接的概念,服務之間通過名字通訊

  • 直接使用lua table作為通訊協議

下面通過一個簡單的實例來介紹luanet的使用:

 

local net = require "lua/net"
local table2str = require "lua/table2str"

local nameservice = net.netaddr_ipv4("127.0.0.1",8010)

local function Plus(arg)
    return nil,arg[1] + arg[2]
end
luanet.RegRPCFunction("Plus",Plus)
luanet.StartLocalService("PlusServer",SOCK_STREAM,net.netaddr_ipv4("127.0.0.1",8012))
luanet.Register2Name(nameservice)

上面的代碼實現了一個簡單的服務器,提供一個叫做Plus的遠程方法. 首先注冊遠程方法,名字就是Plus,之后用服務名PlusServer在8012

端口上啟動一個TCP監聽. 然后向名字服務注冊自己.一個簡單的遠程調用服務就實現了,下面再來看下客戶端.

local net = require "lua/net"
local table2str = require "lua/table2str"
local Sche = require "lua/scheduler"
local nameservice = net.netaddr_ipv4("127.0.0.1",8010)
--啟動本地服務
luanet.StartLocalService("PlusClient",SOCK_STREAM,net.netaddr_ipv4("127.0.0.1",8012))
--注冊到NameService
luanet.Register2Name(nameservice)
--啟動100個lightprocess執行遠程調用
for 1,100 do
    Sche.Spawn(
                function() 
                    while true do
                        local ret,err = luanet.RPCCall("PlusServer","Plus",{1,2})
                        if err then
                            return
                        else
                            print(ret)
                        end
                    end 
                end     
              )
end

client首先用名字PlusClient在8012上啟動一個TCP監聽用於跟其它服務通信.之后向名字服務注冊自己,然后 Spawn個coroutine不斷的執行對

PluServer的Plus遠程方法的調用.對於上面的示例需要說明的一點是,luanet中的所有代碼都運行在coroutine環境下,輸入luanet xxx.lua 的

時候,luanet首先會載入statr.lua文件,然后用xxx.lua作為參數調用start函數.由start函數啟動一個coroutine去執行xxx.lua文件,具體可以

查看luanet.c和start.lua.

下面簡單介紹luanet的公共接口:

StartLocalService(local_name,local_socktype,local_addr,cb_disconnected)

用local_name作為服務的名字,啟動本地服務.這里需要說明的是,當服務A向服務B發送消息或調用遠程方法的時候,A會建立一個到B的連接

(connect B的主監聽),B在這個連接上接收A發過來的所有消息和請求,但不會通過這個連接往A發送消息或遠程方法的響應.如果B要向A發送

消息或遠程回應,則B要建立一條到A的連接(connect A 的主監聽).也就是說A與B之間如果要雙向通信需要建立兩條單向的連接.

Register2Name(nameaddr)

將服務注冊到名字服務.

SendMsg(name,msg)

向name服務發送一條消息

RPCCall(name,funcname,arguments)

調用name服務的funcname方法

RegRPCFunction(name,func)

注冊一個遠程方法

GetRemoteFuncProvider(funcname)

獲取提供遠程方法funcname的服務名字列表

GetMsg()

提取發往本服務的消息,如果消息隊列為空阻塞當前coroutine.建議的使用方式是啟動一組coroutine調用GetMsg,這樣當一個

coroutine阻塞在遠程調用上時還有其它的coroutine可以繼續提取消息並服務.

有興趣的朋友可以關注luanet

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM