2019-01-02網(wǎng)站基礎(chǔ)架構(gòu)的思考

大部分人認同開發(fā)微信小程序或SPA(WEB單頁應(yīng)用)是實現(xiàn)“前后端分離”的臀栈。所有業(yè)務(wù)數(shù)據(jù)都是“后端應(yīng)用”通過HTTP接口提供給“前端應(yīng)用”。一個“完整的應(yīng)用”被物理隔離為兩個獨立的應(yīng)用挠乳,并由擅長的開發(fā)者負責(zé)权薯,從而實現(xiàn)職責(zé)分離

前端開發(fā)者:負責(zé) View 和 Controller 層。

后端開發(fā)者:只負責(zé) Model 層睡扬,業(yè)務(wù)處理/數(shù)據(jù)等盟蚣。

“前后端分離”是強調(diào)“職責(zé)分離”,上面應(yīng)用分離的例子是為了方便理解接受卖怜,可以不應(yīng)用分離屎开。通常應(yīng)用分離能大量減少不小心的越界行為。

分離前:前端開發(fā)者提供靜態(tài)頁面马靠,后端開發(fā)者完成 Controller 和 View 層代碼奄抽。但前端開發(fā)者經(jīng)常會插一腳修改 Controller 和 View 層代碼。

分離后:面向用戶的 Controller 和 View 層都由前端開發(fā)者做虑粥;后端開發(fā)者只需復(fù)雜 Model 層如孝,提供業(yè)務(wù)數(shù)據(jù)接口。

在自己服務(wù)器測試兩種場景娩贷。

服務(wù)器配置:

騰訊云服務(wù)器(Ubuntu 16.04.1 LTS)

CPU: 2核

內(nèi)存:4GB

帶寬:2M

Node.js環(huán)境:

Node.js版本:v8.12.0(Alinode v3.12.0)

框架:Egg.js

worker進程數(shù):2

PHP環(huán)境:

PHP版本:7.2.10

框架:Lumen

php-fpm最大子進程數(shù):5

兩種場景測試代碼:

場景一第晰,直接輸出字符串,不做任何IO和計算。

PHP效率比Node.js高

Node.js:

// egg-4asyncfunctiontest(ctx){? ctx.body ='<h1>goddess.daifee.com</h1><p>Egg程序</p>';}

egg-4.png

PHP:

// php-4$router->get('/test',function()use($router){return'<h1>goddess-php.daifee.com</h1><p>這是PHP服務(wù)</p>';});

php-4.png

場景二茁瘦,模擬200ms的網(wǎng)絡(luò)請求品抽。

Node.js效率比PHP高。相對“場景一”PHP效率下降明顯甜熔,Node.js不明顯圆恤。

Node.js:

// egg-4—test2asyncfunctiontest2(ctx){conststart =Date.now();awaitnewPromise(resolve=>{? ? setTimeout(()=>{? ? ? resolve(true);? ? },200);? });constoffset =Date.now() - start;? ctx.body =`

goddess.daifee.com

Egg程序${offset}

`;}

egg-4-test2.png

PHP:

// ./WeTest_[php-4—test2]_20181014172129.pdf$router->get('/test2',function()use($router){? ? $start = microtime(true);? ? usleep(200000);? ? $offset = microtime(true) - $start;return"<h1>goddess-php.daifee.com</h1><p>這是PHP服務(wù) {$offset}</p>";});

php-4-test2.png

3.2 基于Egg.js框架開發(fā)(編碼)

下面用Egg.js框架開發(fā)一個頁面為例(瀏覽器端開發(fā)模式不需要改變)。

開發(fā)一個新頁面(用戶主頁頁)腔稀,只需要下面4個步驟:

模板:創(chuàng)建模板文件盆昙。

<!-- app/views/user.ejs -->這里是 ejs 模板

數(shù)據(jù)接口:幾行代碼封裝數(shù)據(jù)接口。

// app/service/user.jsconst{ Service } =require('egg');module.exports =classUserServiceextendsService{asyncget(userId) {consturl =`https://api.gateway.com/xxx/${userId}`;// http請求/ajaxconstresponse =awaitthis.app.curl(url);returnresponse;? }}

控制器:過濾/驗證用戶輸入焊虏、驗證權(quán)限淡喜、調(diào)用數(shù)據(jù)接口、渲染模板诵闭。

// app/controller/user.jsconstBaseController =require('./base-controller');module.exports =classUserControllerextendsBaseController{asyncprofile() {const{ params, service } =this.ctx;// 只有自己才能訪問自己主頁炼团。不是自己就拋出 403 異常this.assertUser(params.userId);? ? user =awaitservice.user.get(params.userId);awaitthis.render('user', {user: user});? }}

路由:一行代碼聲明路由。

// app/router.jsmodule.exports =app=>{const{ router, controller, middleware } = app;const{ authorize } = middleware;const{ user } = controller;// 已登錄用戶才能訪問router.get('/users/:userId', authorize.user, user.profile);}

只負責(zé) Controller 和 View 層的Node.js服務(wù)端開發(fā)非常簡單疏尿。一個企業(yè)應(yīng)用除了開發(fā)瘟芝,還有其他環(huán)節(jié)需要做好。

3.3 我們還缺什么褥琐?

前端開發(fā)者可以在服務(wù)端寫 Controller 和 View 層代碼锌俱,但整個生產(chǎn)環(huán)節(jié)還缺什么?

3.3.1 前端開發(fā)者

既然前端開發(fā)者需要做更多踩衩,能做更多嚼鹉,所以工作量增加。所以缺前端開發(fā)者驱富。

同一個項目锚赤,編碼的工作量增加了。

前端同事需要關(guān)注褐鸥、分析线脚、協(xié)助維護Node.js服務(wù)器。

肯定會有更多的xxx小程序需求叫榕。

3.3.2 適合我們的框架和項目腳手架

確定了web網(wǎng)站應(yīng)用使用Egg框架浑侥,還需為不同業(yè)務(wù)場景的項目創(chuàng)建拿來即用的腳手架。

未確定React Isomorphic應(yīng)用的框架晰绎。我體驗過next.js寓落,是一個不錯的選擇。

3.3.3 構(gòu)建/部署服務(wù)

目前還沒有Node.js項目的構(gòu)建/部署服務(wù)荞下。

基本需求:

構(gòu)建:開發(fā)者只需關(guān)注源碼伶选,“構(gòu)建服務(wù)”自動構(gòu)建項目史飞。

發(fā)布:支持選擇git tag構(gòu)建,部署到“生產(chǎn)環(huán)境”仰税。

發(fā)布:支持選擇git branch構(gòu)建构资,部署到“測試環(huán)境”。

回滾:支持指定版本回滾陨簇。

重啟:支持重啟Node.js服務(wù)器吐绵。

發(fā)布:允許測試人員發(fā)布“測試版本”。

3.3.4 嚴謹?shù)膅it工作流

需要依據(jù)“構(gòu)建/部署服務(wù)”定制嚴謹?shù)膅it工作流河绽。

3.3.5 風(fēng)險監(jiān)控和日志采集

風(fēng)險監(jiān)控可以考慮Alinode己单。

完全免費

支持性能監(jiān)控、安全提醒葵姥、故障排查荷鼠、性能優(yōu)化等

支持手動下載性能數(shù)據(jù)

日志采集接入大數(shù)據(jù)團隊的服務(wù)?

關(guān)于React Isomrophic

當時用React全家桶做了一個SPA Demo項目榔幸,然后用next.js框架再做一個React Isomorphic版。發(fā)現(xiàn)可以復(fù)用(copy)98%的代碼矮嫉,然后花一點時間將 React Router 替換為 next.js 自帶的 Router 即可

基于 next.js 框架 React Isomorphic 應(yīng)用與 SPA 的開發(fā)體驗差不多削咆。

畢竟一套代碼運行于兩個不同環(huán)境,React Isomorphic 還是帶來了一些坑:

需要意識到哪些代碼在2個環(huán)境都執(zhí)行蠢笋,哪些代碼只在其中一個環(huán)境執(zhí)行拨齐。

立即執(zhí)行的代碼在2個環(huán)境都執(zhí)行。

React組件生命周期的代碼只在Browser環(huán)境執(zhí)行昨寞。

Component.getInitialProps()方法在2個環(huán)境都執(zhí)行瞻惋。

小心使用運行環(huán)境的“接口”

next.js自帶Router,與“其他Router”肯定存在差異援岩。

某些組件需要用唯一自增ID或隨機數(shù)歼狼,這種做法會使服務(wù)端于客戶端存在差異。

“服務(wù)端”與“客戶端”基本只能用cookie共享“狀態(tài)”享怀,要珍惜cookie資源羽峰。

作者:daifee

鏈接:http://www.reibang.com/p/1f3f3f70be33

來源:簡書

簡書著作權(quán)歸作者所有,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處添瓷。

個人倒是覺得梅屉。如果有條件的話,架構(gòu)上可以考慮底層接口采用java來提供基層的共性接口鳞贷,可以保證高并發(fā)和穩(wěn)定性坯汤。然后在業(yè)務(wù)邏輯處理上,采用php進行處理搀愧,為前端提供接口服務(wù)惰聂,而在前端則采用vue來模塊化界面卖毁。



所以我們就需要有發(fā)布系統(tǒng)票堵,發(fā)布系統(tǒng)定義了統(tǒng)一的回退操作,所有服務(wù)必須遵循發(fā)布系統(tǒng)的定義回退操作。 在餓了么對接發(fā)布系統(tǒng)是對所有人的強制要求歹苦,所有的系統(tǒng)必須全部接入發(fā)布系統(tǒng)。發(fā)布系統(tǒng)的框架很重要立倍,這個東西其實對于公司是很重要的一件事情澜薄,需要放到第一優(yōu)先級的隊列里面去考慮。

四叉钥、服務(wù)框架

緊接著就是餓了么的服務(wù)框架罢缸,把一個大的Repo拆分成一個小的Repo,把一個大的服務(wù)拆成一個小的服務(wù)投队,讓我們的服務(wù)盡量獨立出去枫疆,這需要一套分布式服務(wù)框架來支撐。 分布式服務(wù)框架包含的服務(wù)注冊敷鸦、發(fā)現(xiàn)息楔、負載均衡、路由扒披、流控值依、熔斷、降級等功能碟案,這里就不一一展開了愿险。前面已經(jīng)提及,餓了么是多語言的生態(tài)价说,有 Python的辆亏,也有Java的,我們的服務(wù)化框架對應(yīng)也是多語言的鳖目。這對我們后來一些中間件的選型是有影響的扮叨,比如說DAL層。

五疑苔、DAL數(shù)據(jù)訪問層

當業(yè)務(wù)量越來越大的時候甫匹,數(shù)據(jù)庫會變成一個瓶頸。 前期可以通過提升硬件的方式來提升數(shù)據(jù)庫的性能惦费。比如:

升級到一個有更多CPU的機器兵迅;

把硬盤改成 SSD 的或者更高級一點的。

但硬件提升終歸是有一個容量限制的薪贫。而且很多做業(yè)務(wù)的小伙伴恍箭,寫代碼的時候都直接操作數(shù)據(jù)庫,發(fā)生過很多次服務(wù)一上線數(shù)據(jù)庫就被打爆的情形瞧省。數(shù)據(jù)庫被打爆掉了之后扯夭,除非等待數(shù)據(jù)庫恢復(fù)鳍贾,沒有任何其它機會可以恢復(fù)業(yè)務(wù)。 如果數(shù)據(jù)庫里面數(shù)據(jù)是正常的交洗,業(yè)務(wù)其實都可以補償出來骑科。所以我們做DAL服務(wù)層的時候,第一件事情是限流构拳,其它的東西可以放一放咆爽。然后做連接復(fù)用,我們Python框架用的多進程單線程加協(xié)程的模型置森。 多進程之間其實是不可以共享一個連接的斗埂。比如:一臺機器上部署了10個 Python進程,每個進程10個數(shù)據(jù)庫連接凫海。再擴展到10臺機器上呛凶,就有1000個數(shù)據(jù)庫連接。對數(shù)據(jù)庫來說行贪,連接是一個很昂貴的東西漾稀,我們DAL層要做一個連接復(fù)用。 這個連接復(fù)用講的不是服務(wù)本身的連接復(fù)用建瘫,而是說DAL層上的連接復(fù)用县好,就是服務(wù)有1000個連接到DAL層,經(jīng)過連接復(fù)用后對數(shù)據(jù)庫可能只是保持著十幾個連接暖混。一旦發(fā)現(xiàn)某個數(shù)據(jù)庫請求是一個事務(wù)的話,那么DAL就幫你保留這個連接的對應(yīng)關(guān)系翁授。當這個事務(wù)結(jié)束之后拣播,就把數(shù)據(jù)庫的連接,放回到共用池里面去收擦,供其他人使用贮配。 然后做冒煙和熔斷。數(shù)據(jù)庫也可以熔斷的塞赂。當數(shù)據(jù)庫發(fā)生冒煙時泪勒,我們會殺掉一些數(shù)據(jù)庫的請求,保證數(shù)據(jù)庫不至于崩潰宴猾。六圆存、服務(wù)治理服務(wù)框架之后,涉及服務(wù)治理的問題仇哆。服務(wù)治理其實是一個很大的概念沦辙。首先是埋點,你要埋很多的監(jiān)控點讹剔。 比如有一個請求油讯,請求成功了或者失敗了详民,請求的響應(yīng)時間是多少,把所有的監(jiān)控指標放到監(jiān)控系統(tǒng)上面去陌兑。我們有一個很大的監(jiān)控屏幕沈跨,上面有很多的監(jiān)控指標。有專門小組72小時去盯著這個屏幕兔综,如果有任何曲線波動了饿凛,就找人去解決。另外是報警系統(tǒng)邻奠,一個監(jiān)控屏幕展示的東西總是有限的笤喳,只能放那些很重要的關(guān)鍵指標。這個時候就需要有報警系統(tǒng)碌宴。 羅馬不是一天建成的杀狡,基礎(chǔ)架構(gòu)更是一個演進的過程。我們的資源和時間總是有限的贰镣,作為架構(gòu)師和 CTO 來說呜象,如何在這種有限的資源下,產(chǎn)出更重要的東西碑隆? 我們做了很多系統(tǒng)恭陡,覺得自己做得很不錯了,但實則不是上煤,我感覺我們又回到了石器時代休玩,因為問題越來越多,需求也越來越多劫狠,總感覺你的系統(tǒng)里還缺點什么東西拴疤,想做的功能也一大堆。 比如對于流控系統(tǒng)独泞,現(xiàn)在我們還是需要用戶去配一個并發(fā)數(shù)呐矾,那么這個并發(fā)數(shù),是不是根本不需要用戶去配懦砂?是不是可以基于我們服務(wù)本身的一個狀態(tài)自動去控制并發(fā)數(shù)蜒犯? 然后是升級方式,SDK升級是個很痛苦的事情荞膘。比如說我們服務(wù)框架2.0發(fā)布的時候是去年12月份罚随,到現(xiàn)在還有人用的是1.0。是不是可以做到SDK的無損感升級衫画,我們自己來控制升級的時間和節(jié)奏毫炉。 還有,我們現(xiàn)在的監(jiān)控只支持同一個服務(wù)上的匯聚削罩,是不分集群瞄勾、不分機器的费奸,那是不是以后的指標可以分集群、分機器进陡?舉一個最簡單的例子愿阐,比如一個服務(wù)上有10臺機器,那么可能只是某一個機器上出了問題趾疚,但它所有的指標都會平均分攤到其它的9臺機器上去缨历。你只是看到了整個服務(wù)延時增加了,但有可能只是某一臺機器拖慢了整個服務(wù)集群糙麦。但我們現(xiàn)在還做不到更多維度的監(jiān)控辛孵。 還有智能化的報警,這個報警赡磅,就是要快魄缚、全、準焚廊,我們現(xiàn)在做到更快了冶匹,做到更全了,怎么才能做到更準咆瘟?每天的報警量高峰時間一分鐘一千多個報警發(fā)出去嚼隘。所有的一千報警都是有用的嗎?報警多了之后袒餐,就相當于沒有報警飞蛹。大家都疲勞了,就不去看了灸眼。我怎么能夠把這個報警更準確地區(qū)分出來桩皿?還有更智能化的鏈路分析?以后是不是我們的監(jiān)控不要放監(jiān)控指標幢炸,而是放鏈路分析,這樣就能夠很清晰地知道拒贱,這個問題對應(yīng)的是哪一個結(jié)點上出了問題宛徊。 這些問題涉及我們做事的一個原則:東西夠用就好,但是要能夠未雨綢繆逻澳,做一定的超前規(guī)劃闸天。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市斜做,隨后出現(xiàn)的幾起案子苞氮,更是在濱河造成了極大的恐慌,老刑警劉巖瓤逼,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件笼吟,死亡現(xiàn)場離奇詭異库物,居然都是意外死亡,警方通過查閱死者的電腦和手機贷帮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門戚揭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人撵枢,你說我怎么就攤上這事民晒。” “怎么了锄禽?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵潜必,是天一觀的道長。 經(jīng)常有香客問我沃但,道長磁滚,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任绽慈,我火速辦了婚禮恨旱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坝疼。我一直安慰自己搜贤,他們只是感情好,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布钝凶。 她就那樣靜靜地躺著仪芒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪耕陷。 梳的紋絲不亂的頭發(fā)上掂名,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音哟沫,去河邊找鬼饺蔑。 笑死,一個胖子當著我的面吹牛嗜诀,可吹牛的內(nèi)容都是我干的猾警。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼隆敢,長吁一口氣:“原來是場噩夢啊……” “哼发皿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起拂蝎,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤穴墅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體玄货,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡皇钞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了誉结。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片鹅士。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖惩坑,靈堂內(nèi)的尸體忽然破棺而出掉盅,到底是詐尸還是另有隱情,我是刑警寧澤以舒,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布趾痘,位于F島的核電站,受9級特大地震影響蔓钟,放射性物質(zhì)發(fā)生泄漏永票。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一滥沫、第九天 我趴在偏房一處隱蔽的房頂上張望侣集。 院中可真熱鬧,春花似錦兰绣、人聲如沸世分。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽臭埋。三九已至,卻和暖如春臀玄,著一層夾襖步出監(jiān)牢的瞬間瓢阴,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工健无, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留荣恐,地道東北人。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓累贤,卻偏偏與公主長得像募胃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子畦浓,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

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

  • 目錄: 一、什么是前后端分離检疫? 二讶请、為什么要前后端分離?2.1 清晰前后端職責(zé)2.2 提高開發(fā)效率2.3 前端能做...
    daifee閱讀 5,069評論 2 144
  • 我昨天騎自行車去上班,騎到一個路口的時候,突然一個抱小孩的女的竄了出來,我趕緊剎車啊,結(jié)果沒剎住,然后我撞到這個抱...
    佛系怪獸君閱讀 7,639評論 73 221
  • 這就是我了,顏控的可以略過啦夺溢! 安徽人论巍,現(xiàn)在在江蘇工作 95年生 獨生子女,未婚未育 個子不高只有173风响,看過一些...
    墨道非攻閱讀 619評論 6 2
  • 五臺山真容禪寺有當代高僧上夢下參長老駐錫修建嘉汰。丁酉年四月初八本寺方丈隆明大和尚將主法浴佛法會。歡迎諸善信...
    真容寺義工閱讀 2,338評論 0 0