溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

core_framework —— 基于libev的輕量級lua網(wǎng)絡(luò)開發(fā)框架

發(fā)布時間:2020-07-07 17:59:10 來源:網(wǎng)絡(luò) 閱讀:226 作者:CandyMi 欄目:軟件技術(shù)

大道至簡, 返璞歸真.

前言

在發(fā)表這篇博文的前夕, 還有一些小伙伴在提問一些以下相關(guān)的問題:

  1. 性能怎么樣?

  2. 是否容易上手?

  3. 開發(fā)目標(biāo)在哪?

  4. 如何反饋問題?

  5. 對比行業(yè)內(nèi)的lua開源項目有何優(yōu)勢?

等等, 以上問題會在本文中一一介紹.


CF的起因

首先來聊聊情懷這個東西! 相信每一個行業(yè)內(nèi)的從業(yè)者都或多或少有過一個夢, 這個夢叫做: "我到時候要開發(fā)一個XXX"!其實(shí)作者當(dāng)初也是一樣.

每當(dāng)半夜(凌晨)在加班、看文檔、調(diào)試的時候, 總會搜索到一些幾年前或十幾年前的框架或入門demo。例如: tinyhttp, 鏈接的源碼是一些同學(xué)fork的鏡像站。

每次看到這些內(nèi)容或多或少都會激起心中那一絲絲快熄滅的熱情, 也許這就是最后對技術(shù)的渴望?

就是在動手創(chuàng)建項目之前還反復(fù)問過自己是否要做? 能堅持下去么?也許被噴都是一種奢望?

在心里一一回答了這些問題后, 在2018年末創(chuàng)建了本項目.

說句實(shí)話! 一個網(wǎng)絡(luò)開發(fā)框架最難的不是實(shí)現(xiàn)某個功能, 而是從零開始一步一步添磚加瓦的造輪子!

作為一個網(wǎng)絡(luò)開發(fā)框架, 最重要的兩個功能肯定是需要的! 定時器庫、事件驅(qū)動庫. 如何抉擇?選項有2個: libev / libuv .

libev 成熟穩(wěn)定、輕量級、unix like支持、容易嵌入;

libuv 比libev更加優(yōu)秀,增加了許多功能(線程池、信號、同步、鎖等等),封裝更加完善, 并且增加了windows支持;

從cf框架開發(fā)之初選型來看, libuv絕對是目前最優(yōu)解. 但是作者偏偏選擇了libev. 也從此開始, 艱辛的底層開發(fā)之路就此展開.

首先, 作者不讓使用者C/C++進(jìn)行實(shí)際業(yè)務(wù)開發(fā)! 這樣做會讓使用者有較高的開發(fā)成本與學(xué)習(xí)成本, 而選擇一門較好的腳本語言就顯得尤為重要.

作者對Lua還算是稍微熟悉一點(diǎn), 所以就選了Lua作為業(yè)務(wù)腳本語言。至于Lua語言的優(yōu)勢這里就不說了, 網(wǎng)上大把文章夸它的.

現(xiàn)在既然腳本語言已經(jīng)選定, 那么就開始寫代碼吧!Let's Lua.


CF的編寫之路

1. 網(wǎng)絡(luò)層

首先, 我們來看一段C封裝給Lua調(diào)用的API代碼:

LUAMOD_API int
luaopen_tcp(lua_State *L){
    luaL_checkversion(L);
    /* 添加SSL支持 */
    SSL_library_init();
    SSL_load_error_strings();
    // CRYPTO_set_mem_functions(xmalloc, xrealloc, xfree);
    // OpenSSL_add_ssl_algorithms();
    /* 添加SSL支持 */
    luaL_newmetatable(L, "__TCP__");
    lua_pushstring (L, "__index");
    lua_pushvalue(L, -2);
    lua_rawset(L, -3);
    lua_pushliteral(L, "__mode");
    lua_pushliteral(L, "kv");
    lua_rawset(L, -3);
    luaL_Reg tcp_libs[] = {
        {"read", tcp_read},
        {"write", tcp_write},
        {"ssl_read", tcp_sslread},
        {"ssl_write", tcp_sslwrite},
        {"stop", tcp_stop},
        {"start", tcp_start},
        {"close", tcp_close},
        {"listen", tcp_listen},
        {"connect", tcp_connect},
        {"ssl_connect", tcp_sslconnect},
        {"new", tcp_new},
        {"new_ssl", ssl_new},
        {"free_ssl", ssl_free},
        {"new_server_fd", new_server_fd},
        {"new_client_fd", new_client_fd},
        {NULL, NULL}
    };
    luaL_setfuncs(L, tcp_libs, 0);
    luaL_newlib(L, tcp_libs);
    return 1;
}

以上是TCP實(shí)現(xiàn)的C代碼的片段, 有興趣閱讀源碼的小伙伴請點(diǎn)擊這里;

眾所周知Lua沒有原生的Socket. 那么就需要框架編寫者自己抽象底層邏輯重新實(shí)現(xiàn)一套API.

簡單的封裝Lua C庫誰都會, 而且也算不上是什么難事. 但是我們的目的是將底層同步阻塞Socket hook為非阻塞, 這時候難點(diǎn)就來了!

大家都知道libev是基于react模型的事件驅(qū)動網(wǎng)絡(luò)庫, 所有注冊事件后的業(yè)務(wù)邏輯都是以回調(diào)的形式觸發(fā). 那不就變成node-lua代碼了嗎?(笑)

這時候, 作者想了個點(diǎn)子來解決這個問題! 執(zhí)行流程如下:

  1. 每次需要做一些同步操作的時候, 就調(diào)用C API注冊回調(diào)事件.

  2. 為當(dāng)前注冊的所有事件創(chuàng)建一個Lua協(xié)程保存上下文并讓出當(dāng)前協(xié)程執(zhí)行權(quán).

  3. 等到注冊事件被觸發(fā)后, 調(diào)用C API恢復(fù)協(xié)程繼續(xù)執(zhí)行.

簡單來說就是將C層次的異步回調(diào)邏輯封裝為Lua層的同步非阻塞, 保證不因?yàn)镮O問題阻塞線程.

下面提供一段socket同步非阻塞的偽代碼, 經(jīng)供參考:

function TCP:recv(bytes)
    local current_co = co_self()
    self.read_co = read_ev(function()
    -- do action
    -- stop timer_ev
    -- wakeup(current_co) 恢復(fù)執(zhí)行權(quán)
    end)
   self.timer_co =  self.timer_ev(function()
    -- do action
    -- stop read_ev
    -- wakeup(current_co) 恢復(fù)執(zhí)行權(quán)
    end)
    tcp_start(io, EV_READ, self.read_co)
    timer_start(timer, 3秒超時, self.timer_co)
    return co_yield() -- 讓出執(zhí)行權(quán)
end

一個Lua版的Socket EV_READ偽代碼大致的處理流程如上, 想看實(shí)際處理邏輯請看這里。

同理, Socket write/connect/listen等等API直接照抄就行(UDP也大同小異). (其實(shí)這里有個小插曲就是SSL SOCKET的坑, 但是由于篇幅問題就不說了.)

細(xì)心的小伙伴可能發(fā)現(xiàn)代碼同時注冊了Socket與Timer事件, Socket非阻塞操作不能解決read與connect超時的問題. 所以cf框架干脆就封裝徹底一點(diǎn).

至此, Socket算是已經(jīng)算是基本hook與封裝完成了. 接下來就可以開始寫應(yīng)用層協(xié)議了.

2. 應(yīng)用層協(xié)議

現(xiàn)在Socket終于能正常使用了, 那么面臨的新問題就又來了。

libev沒有自帶異步dns

dns都還需要使用者自己封裝, 這個坑真是填的無比難受! 好在網(wǎng)絡(luò)上有前輩實(shí)現(xiàn)了Lua版的異步dns, 作者稍微看明白之后就借用了過來封裝內(nèi)部使用.

這樣cf也算是有了深度定制的異步dns庫了吧!(雖然并不完善, 但是足夠使用)

一個網(wǎng)絡(luò)庫是否流行, 基本上就得看生態(tài). 那么協(xié)議層的輪子又得造起來:

  1. httpd與httpc
  2. mail
  3. mysql
  4. redis
  5. mqtt
  6. websocket

其中一些協(xié)議為各位前輩那邊借過來適配后定制的, 簡單的協(xié)議則是直接花1-2小時直接手寫出來的。

3. 封裝與易用性

為了不讓API那么封閉與提升cf的可用性, 作者決定將mysql與redis進(jìn)行初步封裝.

封裝包括大家常用的功能, 連接池、面向?qū)ο蟛僮?、無需手動管理session生命周期等等. 簡化編程思想包袱來提升開發(fā)效率.

至于內(nèi)部Socket更是讓框架來解決釋放問題確保文件描述數(shù)量限制的情況下也是可以正常使用. (其實(shí)是不喜歡依賴gc被動close fd與free內(nèi)存)


CF是啥?

如果你耐心看完了第一部分介紹, 那么你就應(yīng)該對cf有了一個大概的了解.

cf全稱為: CoreFramework, 是一個基于libev的Lua網(wǎng)絡(luò)開發(fā)框架. 在其內(nèi)部實(shí)現(xiàn)了多種網(wǎng)絡(luò)協(xié)議與第三方庫用來幫助使用者進(jìn)行項目原型的快速開發(fā).

cf 在httpd使用上尊崇前、后端分離的解決方案, 僅實(shí)現(xiàn)了基本的view路由并且不支持rest風(fēng)格的API路由. 雖然這樣可能會引來宇多人的詬病.

cf 的httpd內(nèi)嵌websocket支持, 方便使用者在復(fù)用端口的同時也可以享受長連接編寫的樂趣.

更多的介紹, 請大家項目地址的Wiki


CF能做什么?

  • 基于容器技術(shù)的微服務(wù)場景(swarm/kubernetes); —— 推薦

  • 游戲服務(wù)器的前端代理層; —— 推薦

  • 內(nèi)存/CPU資源較為緊缺的云服務(wù)器; —— 推薦

  • 對性能要求較高的無狀態(tài)集群; —— 推薦

  • 海量長連接(websocket)Agent集群; —— 推薦

CF使用到的技術(shù)棧?

傳輸層: TCP/UDP

會話層: SSL Client支持

協(xié)議層: dns/webocket/http/mqtt/redis/mysql/smtp

工具庫: Timer/TASK

第三方庫: Libev、openssl/libressl、lua-5.3、jemalloc/tcmalloc(可選)


CF如何安裝?

cf 目前支持絕大部分Unix like操作系統(tǒng), 作者是在Mac上進(jìn)行開發(fā), 所以Mac支持是必須的.

cf測試的Linux為Centos, 所以基本上基于Linux內(nèi)核的操作系統(tǒng)編譯后的運(yùn)行也沒什么問題(export 增加/usr/local/lib)

同時,作者還貼心的為大家做了一個簡單Dockerfile. 文件在項目根目錄下, 大家下載直接使用即可。

當(dāng)然, 如果你不想制作Dockerfile,也可以使用Docker命令直接拉去作者制作好放在docker hub的鏡像. candymi/cfweb

使用詳情與使用方法請參考Docker安裝和編譯安裝


CF 如何運(yùn)行呢?

測試運(yùn)行

bash#: ./cfadmin

后臺運(yùn)行

bash#: ./cfadmin

退出

killall cfadmin

ctrl + c


文檔在哪?

作者為大家貼心的寫了一篇詳細(xì)到不能再詳細(xì)的文檔, 以此來獲取大家的點(diǎn)贊與關(guān)注.

作者還為喜歡閱讀源碼的同學(xué)準(zhǔn)備了充足的中文注釋與英文注釋, 結(jié)合起來方便大家快速了解CF工作方式(中/英注釋結(jié)合易于理解一些專屬詞匯).


回答之前的問題:

Q. 性能怎么樣?

A. 性能還不錯, 但是具體數(shù)值請自行測試.

Q. 是否容易上手?

A. 學(xué)習(xí)lua 一小時入門 -> cf 一小時入門

Q. 開這個項目的初衷是什么?

A. 其實(shí)在前面已經(jīng)回答過了.

Q. 開發(fā)目標(biāo)在哪?

A. Wiki 里有TODO項

Q. 如何反饋問題?

A. Wiki 里有Q & A項

Q. 對比行業(yè)內(nèi)的lua開源項目有何優(yōu)勢?

A. CF對比其它lua開發(fā)項目更深入改變用戶使用習(xí)慣! 簡化框架上手難度, 將框架都黑盒子透明化. 無需學(xué)習(xí)復(fù)雜的設(shè)計模式與理念.

Q. CF的開發(fā)理念是什么?

A. CF項目的目標(biāo)不是競爭, 而是明白明白簡單為美. 當(dāng)你習(xí)慣了它, 也許你就會上癮.


使用示例

  • 容器部署

    • Dockerfile快速構(gòu)建開發(fā)環(huán)境

    • cf k8s中的應(yīng)用示例
  • cf web的初始化與使用

  • cf web Websocket應(yīng)用指南

  • cf web 中間件開發(fā)指南

精彩截圖

core_framework —— 基于libev的輕量級lua網(wǎng)絡(luò)開發(fā)框架

core_framework —— 基于libev的輕量級lua網(wǎng)絡(luò)開發(fā)框架

core_framework —— 基于libev的輕量級lua網(wǎng)絡(luò)開發(fā)框架

希望

也許你正在使用其它開發(fā)框架, 但是這不妨礙你對cf的督促.

也許你正在試用它, 這不妨礙你與作者溝通你的想法.

也許你正在吐槽它的缺點(diǎn),請來issue盡情吐槽.

文檔與地址

項目文檔

項目地址

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI