「造個(gè)輪子」——cicada(輕量級(jí) WEB 框架)

image

前言

俗話說 「不要重復(fù)造輪子」,關(guān)于是否有必要不再本次討論范圍击吱。

創(chuàng)建這個(gè)項(xiàng)目的主要目的還是提升自己虑椎,看看和知名類開源項(xiàng)目的差距以及學(xué)習(xí)優(yōu)秀的開源方式。

好了纲爸,現(xiàn)在著重來談?wù)?cicada 這個(gè)項(xiàng)目的核心功能亥鸠。

我把他定義為一個(gè)快速、輕量級(jí) WEB 框架识啦;沒有過多的依賴负蚊,核心 jar 包僅 30KB。

也僅需要一行代碼即可啟動(dòng)一個(gè) HTTP 服務(wù)颓哮。

image

image

特性

現(xiàn)在來談?wù)勚匾膸讉€(gè)特性家妆。

image

當(dāng)前版本主要實(shí)現(xiàn)了基本的請(qǐng)求、響應(yīng)冕茅、自定義參數(shù)以及攔截器功能伤极。

功能雖少,但五臟俱全姨伤。

在今后的迭代過程中會(huì)逐漸完善上圖功能哨坪,有好的想法也歡迎提 https://github.com/crossoverJie/cicada/issues

快速啟動(dòng)

下面來看看如何快速啟動(dòng)一個(gè) HTTP 服務(wù)乍楚。

只需要?jiǎng)?chuàng)建一個(gè) Maven 項(xiàng)目当编,并引入核心包。

<dependency>
    <groupId>top.crossoverjie.opensource</groupId>
    <artifactId>cicada-core</artifactId>
    <version>1.0.0</version>
</dependency>

如上圖所示徒溪,再配置一個(gè)啟動(dòng)類即可忿偷。

public class MainStart {

    public static void main(String[] args) throws InterruptedException {
        CicadaServer.start(MainStart.class,"/cicada-example") ;
    }
}

配置業(yè)務(wù) Action

當(dāng)然我們還需要一個(gè)實(shí)現(xiàn)業(yè)務(wù)邏輯的地方。cicada 提供了一個(gè)接口臊泌,只需要實(shí)現(xiàn)該接口即可實(shí)現(xiàn)具體邏輯鲤桥。

創(chuàng)建業(yè)務(wù) Action 實(shí)現(xiàn) top.crossoverjie.cicada.server.action.WorkAction 接口。

@CicadaAction(value = "demoAction")
public class DemoAction implements WorkAction {


    private static final Logger LOGGER = LoggerBuilder.getLogger(DemoAction.class) ;

    private static AtomicLong index = new AtomicLong() ;

    @Override
    public WorkRes<DemoResVO> execute(Param paramMap) throws Exception {
        String name = paramMap.getString("name");
        Integer id = paramMap.getInteger("id");
        LOGGER.info("name=[{}],id=[{}]" , name,id);

        DemoResVO demoResVO = new DemoResVO() ;
        demoResVO.setIndex(index.incrementAndGet());
        WorkRes<DemoResVO> res = new WorkRes();
        res.setCode(StatusEnum.SUCCESS.getCode());
        res.setMessage(StatusEnum.SUCCESS.getMessage());
        res.setDataBody(demoResVO) ;
        return res;
    }

}

同時(shí)需要再自定義類中加上 @CicadaAction 注解缺虐,并需要指定一個(gè) value芜壁,該 value 主要是為了在請(qǐng)求路由時(shí)能找到業(yè)務(wù)類。

這樣啟動(dòng)應(yīng)用并訪問

http://127.0.0.1:7317/cicada-example/demoAction?name=12345&id=10

便能執(zhí)行業(yè)務(wù)邏輯同時(shí)得到服務(wù)端的返回高氮。

image

目前默認(rèn)支持的是 json 響應(yīng)慧妄,后期也會(huì)加上模板解析。

服務(wù)中也會(huì)打印相關(guān)日志剪芍。

image

靈活的參數(shù)配置

這里所有的請(qǐng)求參數(shù)都封裝在 Param 中塞淹,可以利用其中的各種 API 獲取請(qǐng)求數(shù)據(jù)。

之所以是靈活的:我們甚至可以這樣請(qǐng)求:

http://127.0.0.1:7317/cicada-example/demoAction?jsonData="info": {
    "age": 22,
    "name": "zhangsan"
  }

這樣就可以傳遞任意結(jié)構(gòu)的數(shù)據(jù)罪裹,只要業(yè)務(wù)處理時(shí)進(jìn)行解析即可饱普。

自定義攔截器

攔截器是一個(gè)框架的基本功能运挫,可以利用攔截器實(shí)現(xiàn)日志記錄、事務(wù)提交等通用工作套耕。

為此 cicada 提供一個(gè)接口: top.crossoverjie.cicada.server.intercept.CicadaInterceptor谁帕。

我們只需要實(shí)現(xiàn)該接口即可編寫攔截功能:

@Interceptor(value = "executeTimeInterceptor")
public class ExecuteTimeInterceptor implements CicadaInterceptor {

    private static final Logger LOGGER = LoggerBuilder.getLogger(ExecuteTimeInterceptor.class);

    private Long start;

    private Long end;

    @Override
    public void before(Param param) {
        start = System.currentTimeMillis();
    }

    @Override
    public void after(Param param) {
        end = System.currentTimeMillis();

        LOGGER.info("cast [{}] times", end - start);
    }
}

這里演示的是記錄所有 action 的執(zhí)行時(shí)間。

目前默認(rèn)只實(shí)現(xiàn)了 action 的攔截冯袍,后期也會(huì)加入自定義攔截器匈挖。

攔截適配器

雖說在攔截器中提供了 before/after 兩個(gè)方法,但也不是所有的方法都需要實(shí)現(xiàn)康愤。

因此 cicada 提供了一個(gè)適配器:

top.crossoverjie.cicada.server.intercept.AbstractCicadaInterceptorAdapter

我們需要繼承他便可按需實(shí)現(xiàn)其中的某個(gè)方法儡循,如下所示:

@Interceptor(value = "loggerInterceptor")
public class LoggerInterceptorAbstract extends AbstractCicadaInterceptorAdapter {

    private static final Logger LOGGER = LoggerBuilder.getLogger(LoggerInterceptorAbstract.class) ;

    @Override
    public void before(Param param) {
        LOGGER.info("logger param=[{}]",param.toString());
    }

}

性能測(cè)試

既然是一個(gè) HTTP 服務(wù)框架,那性能自然也得保證征冷。

在測(cè)試條件為:300 并發(fā)連續(xù)壓測(cè)兩輪择膝;1G 內(nèi)存、單核 CPU检激、1Mbps肴捉。用 Jmeter 壓測(cè)情況如下:

image

同樣的服務(wù)器用 Tomcat 來壓測(cè)看看結(jié)果。

Tomcat 的線程池配置:

<Executor name="tomcatThreadPool" namePrefix="consumer-exec-"
        maxThreads="510" minSpareThreads="10"/>
image

我這里請(qǐng)求的是 Tomcat 的一個(gè) doc 目錄呵扛,雖說結(jié)果看似 cicada 的性能比 Tomcat 還強(qiáng)每庆。

但其實(shí)這個(gè)對(duì)比過程中的變量并沒有完全控制好,Tomcat 所返回的是 HTML今穿,而 cicada 僅僅返回了 json缤灵,當(dāng)然問題也不止這些。

但還是能說明 cicada 目前的性能還是不錯(cuò)的蓝晒。

總結(jié)

本文沒有過多討論 cicada 實(shí)現(xiàn)原理腮出,感興趣的可以看看源碼,都比較簡(jiǎn)單芝薇。

在后續(xù)的更新中會(huì)仔細(xì)探討這塊內(nèi)容胚嘲。

同時(shí)不出意外 cicada 會(huì)持續(xù)更新,未來也會(huì)加入更多實(shí)用的功能洛二。

甚至我會(huì)在適當(dāng)?shù)臅r(shí)機(jī)將它應(yīng)用于我的生產(chǎn)項(xiàng)目馋劈,也希望更多朋友能參與進(jìn)來一起把這個(gè)「輪子」做的更好。

項(xiàng)目地址:https://github.com/crossoverJie/cicada

你的點(diǎn)贊與轉(zhuǎn)發(fā)是最大的支持晾嘶。

image
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末妓雾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子垒迂,更是在濱河造成了極大的恐慌械姻,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件机断,死亡現(xiàn)場(chǎng)離奇詭異楷拳,居然都是意外死亡绣夺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門欢揖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來陶耍,“玉大人,你說我怎么就攤上這事浸颓∥锉郏” “怎么了旺拉?”我有些...
    開封第一講書人閱讀 169,461評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵产上,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我蛾狗,道長(zhǎng)晋涣,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,135評(píng)論 1 300
  • 正文 為了忘掉前任沉桌,我火速辦了婚禮谢鹊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘留凭。我一直安慰自己佃扼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評(píng)論 6 398
  • 文/花漫 我一把揭開白布蔼夜。 她就那樣靜靜地躺著兼耀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪求冷。 梳的紋絲不亂的頭發(fā)上瘤运,一...
    開封第一講書人閱讀 52,736評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音匠题,去河邊找鬼拯坟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛韭山,可吹牛的內(nèi)容都是我干的郁季。 我是一名探鬼主播,決...
    沈念sama閱讀 41,179評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼钱磅,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼梦裂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起续搀,我...
    開封第一講書人閱讀 40,124評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤塞琼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后禁舷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體彪杉,經(jīng)...
    沈念sama閱讀 46,657評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毅往,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了派近。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片攀唯。...
    茶點(diǎn)故事閱讀 40,872評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖渴丸,靈堂內(nèi)的尸體忽然破棺而出侯嘀,到底是詐尸還是另有隱情,我是刑警寧澤谱轨,帶...
    沈念sama閱讀 36,533評(píng)論 5 351
  • 正文 年R本政府宣布戒幔,位于F島的核電站,受9級(jí)特大地震影響土童,放射性物質(zhì)發(fā)生泄漏诗茎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評(píng)論 3 336
  • 文/蒙蒙 一献汗、第九天 我趴在偏房一處隱蔽的房頂上張望敢订。 院中可真熱鬧,春花似錦罢吃、人聲如沸楚午。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽矾柜。三九已至,卻和暖如春泊业,著一層夾襖步出監(jiān)牢的瞬間把沼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評(píng)論 1 274
  • 我被黑心中介騙來泰國(guó)打工吁伺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饮睬,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,304評(píng)論 3 379
  • 正文 我出身青樓篮奄,卻偏偏與公主長(zhǎng)得像捆愁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子窟却,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理昼丑,服務(wù)發(fā)現(xiàn),斷路器夸赫,智...
    卡卡羅2017閱讀 134,716評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,332評(píng)論 25 707
  • Java是一種可以撰寫跨平臺(tái)應(yīng)用軟件的面向?qū)ο蟮某绦蛟O(shè)計(jì)語言菩帝。Java 技術(shù)具有卓越的通用性、高效性、平臺(tái)移植性和...
    Java小辰閱讀 1,088評(píng)論 0 14
  • ? 好久沒追劇,沖著師太周末一口氣看了10集《我的前半生》握础。幾千字的小說被拍成幾十集辐董,加入了不少斗小三、搶孩子的狗...
    財(cái)女蘇小妹閱讀 541評(píng)論 4 6
  • 今天體測(cè) 而我悲催的來了大姨媽 于是乎成了后援一樣 跟著大家進(jìn)操場(chǎng) 幫拿衣服幫拿卡 幫人壓坐仰臥起 原本是想跟大家...
    sunpanda閱讀 211評(píng)論 0 1