后端的一些經(jīng)驗(yàn)與心得

先簡單介紹一下我的經(jīng)歷虱黄,最早在學(xué)校的時候,是在社團(tuán)里寫php和Java赴捞,創(chuàng)業(yè)時期寫js逼裆,oc和Ruby,現(xiàn)在是全職用Rails寫后端了赦政。

項目簡介

我們的主要業(yè)務(wù)有兩塊胜宇,社區(qū)和電商

整體業(yè)務(wù)的峰值qps大概在3000,也算是pv過10億的站點(diǎn)了恢着,后端team有4個人桐愉,除了一個八年老司機(jī),其他人參加工作的年限都不是太久掰派。

我們面對的是一個巨大的基于Rails的歷史遺留系統(tǒng)从诲,最早的開發(fā)成員均已離開,導(dǎo)致我們常常面對遺留代碼一臉蒙逼靡羡,到處是沒有人知道的邏輯系洛,丑陋的實(shí)現(xiàn),以及很多性能跟不上的接口略步。

與巨石應(yīng)用的斗爭

日常工作的重中之重描扯,就是與這個monolith的戰(zhàn)斗!

性能篇

以往每年我們搞活動纳像,服務(wù)器都會掛荆烈,經(jīng)濟(jì)損失不少,所以優(yōu)化性能竟趾,保證活動期間的訪問是第一要務(wù)憔购。

原來的活動整體設(shè)計還是比較科學(xué)的,活動頁面本身是靜態(tài)化托管到cdn的岔帽,從來沒有出現(xiàn)過問題玫鸟,主要瓶頸是商品詳情頁面。我們利用redis做了三層cache犀勒,解決了這個問題屎飘。第一層是數(shù)據(jù)庫的緩存,直接把商品信息緩存到redis里贾费,避免了頻繁的數(shù)據(jù)庫訪問钦购,第二層是單條數(shù)據(jù)的渲染緩存,可以理解成一小段html褂萧,第三層是整個數(shù)據(jù)集的渲染緩存押桃。第二個瓶頸出現(xiàn)在一些靜態(tài)資源上,全面遷移到云存儲解決导犹。做完這兩件事之后唱凯,上上次活動是我們有史以來第一次羡忘,沒有掛。

就在我們覺得磕昼,優(yōu)化做的不錯的時候卷雕,上次活動卻又掛了。

要知道我們特意買了新服務(wù)器票从,美滋滋覺得這下穩(wěn)了漫雕,沒想到...

上次活動掛的原因有以下幾點(diǎn)

  1. redis hmget,我們通過gem提供的API纫骑,緩存了一個巨大的省市區(qū)列表蝎亚,但是沒有注意到緩存是分離的,獲取整個列表先馆,其實(shí)就是一條hmget獲取所有獨(dú)立的緩存片段,這個操作block了redis躺彬,導(dǎo)致訪問極度緩慢煤墙。我們緊急把整個列表轉(zhuǎn)成json,直接貼到代碼里返回hotfix了這個問題
  2. 突然無法通過redis sential進(jìn)行連接宪拥,這套sential系統(tǒng)是由已經(jīng)離職的運(yùn)維搭建的仿野,我們繞開sential直接連接redis,解決了這個問題
  3. fd limit她君, 做完以上兩點(diǎn)脚作,依然時常502, 發(fā)現(xiàn)運(yùn)維修改的是root用戶的fd數(shù)量...坑爹....
  4. 在支付回調(diào)中有一段用于統(tǒng)計的sql缔刹,訂單量大了以后slow query球涛,block了數(shù)據(jù)庫,我們直接注釋了這段可有可無的老代碼校镐,解決亿扁。

總結(jié)一下,對于web應(yīng)用的場景來說鸟廓,大都是讀多寫少从祝,緩存讀請求,異步寫請求引谜,是我們經(jīng)常采用的兩種效果不錯的方式牍陌。在數(shù)據(jù)庫層面,對于遺留代碼中效率低下的查詢進(jìn)行重寫员咽,重點(diǎn)改寫了所有N+1查詢毒涧,對一些逐條插入的語句用batch insert合并寫入操作,也有不錯的提升骏融。

替換篇

做的比較有意思的事链嘀,是寫了我們內(nèi)部用的個推GEM萌狂。原來使用的是github上開源的一個GEM,但是已經(jīng)很久沒更新了怀泊,無法適應(yīng)我們的使用需求茫藏。我基于個推最新的HTTPS的API,寫了一個Ruby的包裝霹琼。

這里要吐槽的是個推的技術(shù)水平务傲。推送服務(wù)是做的不錯,但API怎么做的這么low枣申。他們定義了一個叫authorize的http header用來傳遞身份信息...違背了RFC關(guān)于HTTP頭必須大寫開頭的規(guī)范售葡。一些語言的標(biāo)準(zhǔn)庫(Go、Ruby...)會自動幫你把a(bǔ)uthorize轉(zhuǎn)化成Authorize忠藤,導(dǎo)致個推那邊一直返回auth error...而個推的接口又是HTTPS的挟伙,抓包調(diào)試很困難,浪費(fèi)了我很長時間調(diào)試這個問題模孩。

重構(gòu)篇
重構(gòu)的主要方針就是拆分尖阔,盡可能把功能從巨石應(yīng)用中拆出去。如果一時半會難以拆分的榨咐,代碼上也盡可能讓邏輯高度內(nèi)聚介却,方便以后遷移。

消息系統(tǒng)的重構(gòu)
消息系統(tǒng)是一個块茁,出點(diǎn)問題沒什么齿坷,但做得好會非常出彩的功能。我一直覺得数焊,像知乎這種社區(qū)的成功永淌,除了內(nèi)容,很大一部分要?dú)w功于消息的體驗(yàn)昌跌。目前仰禀,我們幾乎所有頁面,都會展示新消息的數(shù)量蚕愤,導(dǎo)致每次請求都會去主數(shù)據(jù)庫的消息表做count答恶,計算各種消息的數(shù)量返回給前端。我正在著手把整個系統(tǒng)遷移到另一個獨(dú)立的數(shù)據(jù)庫萍诱,以后可以作為單獨(dú)的服務(wù)供內(nèi)部調(diào)用悬嗓,降級限流什么的都很方便。

搜索的重構(gòu)

原來的搜索是基于Solr的java工程裕坊,是一個我們內(nèi)部沒人維護(hù)好多年的爛攤子包竹,雖然各方面表現(xiàn)都不錯。我們還是決定未來要用Elasticsearch換掉它。

新系統(tǒng)
我新寫了內(nèi)部的財務(wù)系統(tǒng)周瞎,過程中遇到很多問題苗缩,寫的也很痛苦,但最終效果還是不錯声诸。因?yàn)樵瓉淼母鞣N報表都是直接基于生產(chǎn)數(shù)據(jù)庫的酱讶,對業(yè)務(wù)會有沖擊,新系統(tǒng)寫了一個同步模塊彼乌,可以增量同步訂單數(shù)據(jù)到財務(wù)系統(tǒng)的專用數(shù)據(jù)庫泻肯,這樣就不會對業(yè)務(wù)帶來影響。

遇到的比較大的坑就是內(nèi)存爆炸慰照。有一些耗時計算我放到了消息對列里灶挟,整個worker進(jìn)程的內(nèi)存占用瘋狂上升。最終發(fā)現(xiàn)是Ruby內(nèi)存模型的問題毒租。

我通過時間換空間的方式稚铣,把之前加載全部數(shù)據(jù)做計算,改成了加載部分?jǐn)?shù)據(jù)做計算蝌衔,然后匯總結(jié)果這樣的方式榛泛,極大降低了內(nèi)存占用,并通過每天重啟worker進(jìn)程噩斟,解決了最主要的內(nèi)存問題。

這個項目讓我真實(shí)感覺到孤个,有些場景真的不是Ruby擅長的領(lǐng)域剃允。Ruby的內(nèi)存模型,就是盡量分配對象齐鲤,從不真正回收斥废,只會重用。Ruby VM啟動就有大量空對象等著被分配给郊,假如我加載了很多數(shù)據(jù)牡肉,空對象不夠用了,VM就向操作系統(tǒng)申請一批內(nèi)存淆九,用完后也不釋放统锤,等著下次重用。而報表計算的最佳場景就是能加載大量數(shù)據(jù)炭庙,算一下結(jié)果饲窿,算完釋放掉內(nèi)存。

監(jiān)控
可以看我之前的文章使用ELK構(gòu)建分布式日志分析系統(tǒng)

代碼篇
在日常編碼焕蹄、重構(gòu)的過程中逾雄,經(jīng)常使用的技術(shù)是

  1. 設(shè)計模式
  2. 元編程

運(yùn)用設(shè)計模式,寫出符合OOP規(guī)范的代碼。分割每個類的職責(zé)鸦泳,盡量讓各個功能的邏輯內(nèi)聚银锻,只提供彼此間調(diào)用的接口,這是我最近才剛領(lǐng)悟的代碼整潔之道做鹰。

元編程抽象代碼击纬,我很早就在使用的奇技淫巧。現(xiàn)在卻用的越來越少了誊垢,因?yàn)樗`背了OOP掉弛,可維護(hù)性比較差,對使用者的水平有很大要求喂走,也容易坑隊友殃饿。

簡單地說,我代碼中的if/else越來越少了芋肠,類越來越多了乎芳,改動起來越來方便了,改動影響的部分越來少了帖池,美滋滋奈惑。

結(jié)語

用一句古老的名言,軟件開發(fā)沒有銀彈睡汹。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末肴甸,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子囚巴,更是在濱河造成了極大的恐慌原在,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彤叉,死亡現(xiàn)場離奇詭異庶柿,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)秽浇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門浮庐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人柬焕,你說我怎么就攤上這事审残。” “怎么了击喂?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵维苔,是天一觀的道長。 經(jīng)常有香客問我懂昂,道長介时,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮沸柔,結(jié)果婚禮上循衰,老公的妹妹穿的比我還像新娘。我一直安慰自己褐澎,他們只是感情好会钝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著工三,像睡著了一般迁酸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上俭正,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天奸鬓,我揣著相機(jī)與錄音,去河邊找鬼掸读。 笑死串远,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的儿惫。 我是一名探鬼主播澡罚,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼肾请!你這毒婦竟也來了留搔?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤铛铁,失蹤者是張志新(化名)和其女友劉穎催式,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體避归,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年管呵,在試婚紗的時候發(fā)現(xiàn)自己被綠了梳毙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡捐下,死狀恐怖账锹,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情坷襟,我是刑警寧澤奸柬,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站婴程,受9級特大地震影響廓奕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一桌粉、第九天 我趴在偏房一處隱蔽的房頂上張望蒸绩。 院中可真熱鬧,春花似錦铃肯、人聲如沸患亿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽步藕。三九已至,卻和暖如春挑格,著一層夾襖步出監(jiān)牢的瞬間咙冗,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工恕齐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留乞娄,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓显歧,卻偏偏與公主長得像仪或,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子士骤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評論 2 354

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