Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
有門(mén)店的餐飲商家來(lái)說(shuō),只要味道能說(shuō)的過(guò)去,能夠滿足時(shí)間、空間需求,那么訂餐就會(huì)很平常,對(duì)中型或酒店等單位更是趨于平常,同時(shí)還有訂桌、菜品預(yù)約、咨詢等需求,那么對(duì)餐飲商家來(lái)說(shuō),基于餐品展示訂餐小程序能夠?qū)崿F(xiàn)什么效果呢?
通過(guò)雨科網(wǎng)小程序平臺(tái)制作餐品預(yù)約小程序,可以將所有菜品多規(guī)格展示到線上,用戶可以填寫(xiě)信息預(yù)約或咨詢,商家后臺(tái)響應(yīng)整理訂單操作,文章/視頻/音頻/圖文等形式滿足多種信息承載。
制作餐飲小程序覆蓋微信、百度、頭條、抖音、快手、支付寶平臺(tái),讓商家在線上平臺(tái)可以高效獲客及經(jīng)營(yíng),案例、環(huán)境、服務(wù)、價(jià)格等信息統(tǒng)統(tǒng)透明可查,便于商家分享也利于用戶搜索、直接觸達(dá)。
基于訂餐訂座小程序服務(wù)/餐品分類式呈現(xiàn),用戶可快速找到所需服務(wù),現(xiàn)成的餐飲小程序模板,替換修改內(nèi)容快速完成制作,訪客信息查看及表單、留言、投票、優(yōu)惠券、新人有禮等功能持續(xù)提升服務(wù)效率、促進(jìn)客戶預(yù)約及線上發(fā)展。
現(xiàn)在就通過(guò)雨科網(wǎng)平臺(tái)制作餐飲訂餐訂座預(yù)約小程序吧。
原文:https://www.zcdly.com/cydcdzxcx.html
公眾號(hào):雨科網(wǎng)
的架構(gòu)要不斷演變,進(jìn)而去適應(yīng)業(yè)務(wù)的發(fā)展。美團(tuán)在移動(dòng)端上的架構(gòu),也經(jīng)歷了組件化、平臺(tái)化、RN混合化,到現(xiàn)在開(kāi)始向容器化變遷。容器化架構(gòu)充分地利用了現(xiàn)在的跨端技術(shù),將動(dòng)態(tài)化的能力最大化地賦予了業(yè)務(wù)。
作為美團(tuán)最為重要的業(yè)務(wù)之一,美團(tuán)外賣(mài)移動(dòng)端的架構(gòu)演進(jìn)是怎樣的呢?本文將為你揭開(kāi)背后的思考、技術(shù)細(xì)節(jié)以及實(shí)踐。
中秋國(guó)慶雙節(jié)喜臨,美團(tuán)技術(shù)團(tuán)隊(duì)祝大家節(jié)日快樂(lè)~~
1.1 移動(dòng)端跨平臺(tái)技術(shù)的介紹
移動(dòng)端的跨平臺(tái)技術(shù)不是一個(gè)新話題,早在幾年前,WebView容器、React Native、Weex、Flutter、小程序等移動(dòng)端跨平臺(tái)框架就風(fēng)起云涌。為什么跨平臺(tái)這么有吸引力呢?我們?cè)O(shè)想一下如果可以做到一次開(kāi)發(fā),多端復(fù)用,那么對(duì)于公司來(lái)說(shuō),就可以降低用人成本。對(duì)于開(kāi)發(fā)來(lái)說(shuō),只需要學(xué)習(xí)一個(gè)框架,就可以在Android和iOS雙平臺(tái)上開(kāi)發(fā)。節(jié)約下來(lái)的成本,可以投入到產(chǎn)品快速驗(yàn)證、快速上線。這對(duì)所有人來(lái)說(shuō)都有著極大的吸引力。本節(jié)先針對(duì)部分移動(dòng)端跨平臺(tái)技術(shù)進(jìn)行一些簡(jiǎn)要的介紹,以便讀者能夠更好地理解后面的內(nèi)容。
1.1.1 WebView容器
WebView容器的工作原理是基于Web技術(shù)來(lái)實(shí)現(xiàn)界面和功能,通過(guò)將原生的接口封裝、暴露給JavaScript調(diào)用,JavaScript編寫(xiě)的頁(yè)面可以運(yùn)行在系統(tǒng)自帶的WebView中。這樣做的優(yōu)勢(shì)是,對(duì)于前端開(kāi)發(fā)者比較友好,可以很快地實(shí)現(xiàn)頁(yè)面跨端,同時(shí)保留調(diào)用原生的能力,通過(guò)搭建橋接層和原生能力打通。但這種設(shè)計(jì),跨端的能力受限于橋接層,當(dāng)調(diào)用之前沒(méi)有的原生能力時(shí),就需要增加橋。另外,瀏覽器內(nèi)核的渲染獨(dú)立于系統(tǒng)組件,無(wú)法保證原生體驗(yàn),渲染的效果會(huì)差不少。
1.1.2 React Native
2015年,F(xiàn)acebook推出了React Native,一經(jīng)推出就備受關(guān)注。它的思路是最大化地復(fù)用前端的生態(tài)和Native的生態(tài),和WebView容器的最大區(qū)別在于View的渲染體系。React Native拋棄了低效的瀏覽器內(nèi)核渲染,轉(zhuǎn)而使用自己的DSL生成中間格式,然后映射到對(duì)應(yīng)的平臺(tái),渲染成平臺(tái)的組件。相對(duì)WebView容器,體驗(yàn)會(huì)有一定的提升。不過(guò),渲染時(shí)需要JavaScript和原生之間通信,在有些場(chǎng)景可能會(huì)導(dǎo)致卡頓。另外就是,渲染還是在Native層,要求開(kāi)發(fā)人員對(duì)Native有一定的熟悉度。
1.1.3 Flutter
2018年Google推出Flutter,通過(guò)Dart語(yǔ)言構(gòu)建一套跨平臺(tái)的開(kāi)發(fā)組件,所有組件基于Skia引擎自繪,在性能上可以和Native平臺(tái)的View相媲美。Flutter站在前人的肩膀上,參考了React的狀態(tài)管理、Web的自繪制UI、React Native的HotReload等特點(diǎn),同時(shí)考慮了與Native通信的Channel機(jī)制、自渲染、完備的開(kāi)發(fā)工具鏈。Flutter與上述Recat Native、WebView容器本質(zhì)上都是不同的,它沒(méi)有使用WebView、JavaScript解釋器或者系統(tǒng)平臺(tái)自帶的原生控件,而是有一套自己專屬的Widget,底層渲染使用自身的高性能C/C++ 引擎自繪。但大部分移動(dòng)端發(fā)展到今天,都已經(jīng)形成了自己的架構(gòu),在現(xiàn)有基礎(chǔ)上加上Flutter,會(huì)形成原有架構(gòu)和Flutter雙平臺(tái)共存的問(wèn)題。目前,對(duì)新的App來(lái)說(shuō),是最被看好的跨端方案。
1.2 美團(tuán)外賣(mài)業(yè)務(wù)介紹
作為中國(guó)領(lǐng)先的生活服務(wù)電子商務(wù)平臺(tái),美團(tuán)致力于用科技連接消費(fèi)者和商家,提供服務(wù)以滿足人們?nèi)粘!俺浴钡男枨螅⑦M(jìn)一步擴(kuò)展至多種生活和旅游服務(wù)。而作為公司最為重要的業(yè)務(wù)之一,美團(tuán)外賣(mài)從2013年創(chuàng)建以來(lái),已經(jīng)從單一的品類擴(kuò)展到附近美食、水果、蔬菜、超市、鮮花、蛋糕等多品類,從早午晚餐,發(fā)展到下午茶、宵夜,中餐、西餐、家常菜、小吃、快餐、海鮮、火鍋、川菜、蛋糕、烤肉、水果、飲料、甜點(diǎn)等多種類餐飲。美團(tuán)外賣(mài)可以說(shuō)是當(dāng)前電商領(lǐng)域,最為復(fù)雜的業(yè)務(wù)之一。
業(yè)務(wù)的復(fù)雜,給系統(tǒng)架構(gòu)也帶來(lái)了不小的挑戰(zhàn)。美團(tuán)外賣(mài)業(yè)務(wù)之所以說(shuō)是當(dāng)前電商領(lǐng)域最為復(fù)雜的業(yè)務(wù),主要源于以下幾點(diǎn)特征:
綜上所述,可以發(fā)現(xiàn)美團(tuán)外賣(mài)不僅僅自身業(yè)務(wù)比較復(fù)雜,而且對(duì)外的角色也很復(fù)雜。在美團(tuán)內(nèi)部,外賣(mài)不僅僅是美團(tuán)平臺(tái)的一個(gè)頻道業(yè)務(wù),而且自己本身也是一個(gè)平臺(tái)業(yè)務(wù),同時(shí)美團(tuán)外賣(mài)還承擔(dān)著新業(yè)務(wù)發(fā)展的平臺(tái)角色。這意味著想要支持好美團(tuán)外賣(mài)業(yè)務(wù)的發(fā)展是一件非常有挑戰(zhàn)的事情。
1.3 美團(tuán)外賣(mài)移動(dòng)端歷史架構(gòu)概述
好的架構(gòu)源于不停地衍變而非設(shè)計(jì)。美團(tuán)外賣(mài)的架構(gòu),歷史上也是經(jīng)歷了很多次迭代。由于外賣(mài)業(yè)務(wù)形態(tài)不斷地發(fā)生變化,原有的設(shè)計(jì)也需要不斷地跟隨業(yè)務(wù)形態(tài)進(jìn)行演進(jìn)。在不斷探索和實(shí)踐過(guò)程中,我們經(jīng)歷了若干個(gè)大的架構(gòu)變遷。從考慮如何高效地復(fù)用代碼支持外賣(mài)App,逐漸地衍變成如何去解決多端代碼復(fù)用問(wèn)題,再?gòu)亩喽说拇a復(fù)用到支持其他頻道業(yè)務(wù)的平臺(tái)架構(gòu)上。在平臺(tái)化架構(gòu)建設(shè)完成后,我們又開(kāi)始嘗試?yán)脛?dòng)態(tài)化技術(shù)去支持業(yè)務(wù)快速上線的訴求。如今,我們面臨著多端復(fù)用、平臺(tái)能力、平臺(tái)支撐、單頁(yè)面多業(yè)務(wù)團(tuán)隊(duì)、業(yè)務(wù)動(dòng)態(tài)訴求強(qiáng)等多個(gè)業(yè)務(wù)場(chǎng)景問(wèn)題。下文我們針對(duì)美團(tuán)外賣(mài)移動(dòng)端架構(gòu)的變遷史,做一些簡(jiǎn)單的概述,以便讀者閱讀本文時(shí)能有更好的延續(xù)性。
1.3.1 組件化架構(gòu)
早期階段,美團(tuán)外賣(mài)作為公司的一個(gè)孵化業(yè)務(wù),在2013年底完成了美團(tuán)外賣(mài)App的1.0版本。隨著外賣(mài)業(yè)務(wù)的驗(yàn)證成功和跑通,訂單量也快速增長(zhǎng),在2014年底突破了日訂單量100萬(wàn)。
隨后在2015年2月,外賣(mài)以Native的形式接入美團(tuán)App,成為美團(tuán)App的一個(gè)業(yè)務(wù)頻道。在接入過(guò)程中,我們從美團(tuán)外賣(mài)App拷貝了大量的代碼到美團(tuán)App的外賣(mài)頻道,兩個(gè)App上的外賣(mài)業(yè)務(wù)代碼也分別由兩個(gè)獨(dú)立的團(tuán)隊(duì)維護(hù)。早期外賣(mài)業(yè)務(wù)變化快,App迭代頻繁,寫(xiě)代碼的方式也比較粗放,同時(shí)美團(tuán)App也處在一個(gè)平臺(tái)化轉(zhuǎn)變的時(shí)期,代碼的穩(wěn)定性和質(zhì)量都在變化和提升當(dāng)中。這些因素導(dǎo)致了外賣(mài)代碼內(nèi)各子系統(tǒng)之間耦合嚴(yán)重,邊界模糊,“你中有我,我中有你”的情況隨處可見(jiàn)。這對(duì)代碼質(zhì)量、功能擴(kuò)展以及開(kāi)發(fā)效率都造成很大的影響。
此時(shí),我們架構(gòu)重構(gòu)的目的,就是希望將各個(gè)子系統(tǒng)劃分為相對(duì)獨(dú)立的組件,建設(shè)組件可以直接復(fù)用,架構(gòu)如下圖所示:
1.3.2 平臺(tái)化架構(gòu)
如上文所述,大家可以知道美團(tuán)外賣(mài)和美團(tuán)外賣(mài)頻道是由不同的團(tuán)隊(duì)在維護(hù)發(fā)展。2015年,公司考慮到業(yè)務(wù)發(fā)展的一致性,將美團(tuán)外賣(mài)頻道團(tuán)隊(duì)正式歸于美團(tuán)外賣(mài)。從組織架構(gòu)上來(lái)說(shuō),美團(tuán)外賣(mài)和美團(tuán)外賣(mài)頻道,逐漸融合成一個(gè)團(tuán)隊(duì),但是兩端的差異性,導(dǎo)致我們不得不仍然階段性地維持原有的兩班人馬,各自去維護(hù)獨(dú)立外賣(mài)App和美團(tuán)外賣(mài)頻道。如何解決這個(gè)問(wèn)題??jī)啥舜a復(fù)用看起來(lái)是唯一的途徑。另外,隨著業(yè)務(wù)的快速發(fā)展,外賣(mài)App所承載的業(yè)務(wù)模塊越來(lái)越多,產(chǎn)品功能越來(lái)越復(fù)雜,團(tuán)隊(duì)規(guī)模也越來(lái)越大,如閃購(gòu)、跑腿等業(yè)務(wù)想以獨(dú)立的Native包的形態(tài)接入外賣(mài)App,還有外賣(mài)的異地研發(fā)團(tuán)隊(duì)的建立,都帶來(lái)了挑戰(zhàn)。這使得我們?cè)?017年開(kāi)始了第二次架構(gòu)重構(gòu)——平臺(tái)化架構(gòu),目標(biāo)是希望能夠支持多端復(fù)用和支持不同團(tuán)隊(duì)的業(yè)務(wù)發(fā)展。通過(guò)抽象出平臺(tái)能力層、業(yè)務(wù)解耦、建立殼容器,最終實(shí)現(xiàn)了平臺(tái)化架構(gòu),架構(gòu)如下圖所示:
1.3.3 RN混合架構(gòu)
在平臺(tái)化架構(gòu)之后,美團(tuán)外賣(mài)功能持續(xù)增加,美團(tuán)外賣(mài)客戶端安裝包的體積也在持續(xù)增加。回顧2017年和2018年,每年幾乎都增長(zhǎng)100%。如果沒(méi)有一個(gè)有效的手段,安裝包將變得越發(fā)臃腫。另外,由于原生應(yīng)用需要依托于應(yīng)用市場(chǎng)進(jìn)行更新,每次產(chǎn)品的更新,必須依賴用戶的主動(dòng)更新,使得版本的迭代周期很長(zhǎng)。業(yè)務(wù)上的這些痛點(diǎn),不斷地督促我們?nèi)シ此嫉降子袥](méi)有一種框架可以解決這些問(wèn)題。
在2015年的時(shí)候,F(xiàn)acebook發(fā)布了非常具有顛覆性的React Native框架,簡(jiǎn)稱RN。從名字上看,就可以清楚的明白,這是混合式開(kāi)發(fā)模式,RN使用Native來(lái)渲染,JS來(lái)編碼,從而實(shí)現(xiàn)了跨平臺(tái)開(kāi)發(fā)、快速編譯、快速發(fā)布、高效渲染和布局。RN作為一種跨平臺(tái)的移動(dòng)應(yīng)用開(kāi)發(fā)框架,它的特性非常符合我們的訴求。美團(tuán)也積極地探索RN技術(shù)。在RN的基礎(chǔ)上,美團(tuán)在腳手架、組件庫(kù)、預(yù)加載、分包構(gòu)建、發(fā)布運(yùn)維等方面進(jìn)行了全面的定制及優(yōu)化,大幅提升RN的開(kāi)發(fā)及發(fā)布運(yùn)維效率,形成了MRN(Meituan React Native)技術(shù)體系。
從2018年開(kāi)始,美團(tuán)外賣(mài)客戶端團(tuán)隊(duì)開(kāi)始嘗試使用MRN框架來(lái)解決業(yè)務(wù)上的問(wèn)題。使用RN的另一方面的好處是,能逐漸的抹平Android和iOS開(kāi)發(fā)技術(shù)棧帶來(lái)的問(wèn)題,使用一套代碼,兩個(gè)平臺(tái)上線,理論上人效可以提升一倍,支持的業(yè)務(wù)需求也可以提升一倍,架構(gòu)如下圖所示:
2.1 什么是容器化架構(gòu)
上文說(shuō)到,外賣(mài)業(yè)務(wù)已經(jīng)發(fā)展到多App復(fù)用、單頁(yè)面多業(yè)務(wù)團(tuán)隊(duì)開(kāi)發(fā)的業(yè)務(wù)階段。要滿足這樣的業(yè)務(wù)場(chǎng)景下,尋求一個(gè)可持續(xù)發(fā)展的業(yè)務(wù)架構(gòu)是件不容易的事情。經(jīng)過(guò)我們之前架構(gòu)演進(jìn),我們獲得了寶貴的經(jīng)驗(yàn):在平臺(tái)化架構(gòu)的時(shí)候,我們將App和業(yè)務(wù)進(jìn)行解耦,將App做成殼容器,業(yè)務(wù)形成獨(dú)立的業(yè)務(wù)庫(kù),集成到殼容器里面,從而屏蔽了多App的問(wèn)題,提高了業(yè)務(wù)的復(fù)用度。在RN混合式架構(gòu)里面,我們引入了RN容器,通過(guò)這個(gè)容器,使得業(yè)務(wù)屏蔽了Android和iOS的平臺(tái)差異。借助這些成功的經(jīng)驗(yàn),我們進(jìn)一步思考,如果我們嘗試進(jìn)一步的細(xì)分外賣(mài)的業(yè)務(wù)場(chǎng)景,將不同場(chǎng)景下的基礎(chǔ)能力建設(shè)成殼容器,業(yè)務(wù)集成到容器內(nèi),是否可以更好的支撐我們多App復(fù)用、單頁(yè)面多業(yè)務(wù)團(tuán)隊(duì)的當(dāng)前現(xiàn)狀呢?
容器化架構(gòu)的愿景是:
2.2 容器化架構(gòu)的優(yōu)勢(shì)
當(dāng)我們把承載外賣(mài)業(yè)務(wù)的環(huán)境進(jìn)行了抽象和標(biāo)準(zhǔn)化后,就可以獲得以下若干點(diǎn)好處。首先動(dòng)態(tài)化屬性提升,我們可以把原有必須在客戶端上寫(xiě)的業(yè)務(wù)放到了遠(yuǎn)端,業(yè)務(wù)的動(dòng)態(tài)性得到很大的提升,具備隨時(shí)上線業(yè)務(wù)的可能。對(duì)于開(kāi)發(fā)過(guò)程而言,編譯部署的速度也得到了極大提升。如果涉及到客戶端的代碼改動(dòng),那客戶端的編譯打包,即使是增量的編譯,也至少是秒級(jí)的編譯速度。而容器化后,我們只打包必要的業(yè)務(wù),把業(yè)務(wù)動(dòng)態(tài)下發(fā)到容器呈現(xiàn),客戶端代碼本身不會(huì)有變化,這樣就可以從秒級(jí)的編譯減少到毫秒級(jí)的編譯。同樣,業(yè)務(wù)動(dòng)態(tài)下發(fā),對(duì)減少客戶端的包大小也有很大的幫助。
然后,容器位于應(yīng)用之內(nèi),我們向應(yīng)用中引入相同的容器SDK,容器屏蔽了應(yīng)用之間的差異,對(duì)于Android和iOS平臺(tái),在設(shè)計(jì)上,通過(guò)容器這一層去盡可能屏蔽平臺(tái)之間的差異,使業(yè)務(wù)開(kāi)發(fā)人員只需要認(rèn)識(shí)容器,不需要花費(fèi)大量的精力去關(guān)注應(yīng)用和平臺(tái)之間的差異,從而使得開(kāi)發(fā)效率得到了極大的提升。
其次,容器化后,容器對(duì)承載的內(nèi)容是有接口協(xié)議要求的,承載的內(nèi)容只有滿足容器定義的協(xié)議才能得到容器帶來(lái)的好處,這促使業(yè)務(wù)得到了更細(xì)粒度的細(xì)分,業(yè)務(wù)開(kāi)發(fā)時(shí)候,對(duì)模塊化的意識(shí)得到了保障。另外,容器這一層提供的接口在Android和iOS上是標(biāo)準(zhǔn)化的,業(yè)務(wù)的開(kāi)發(fā)也因?yàn)橐蕾嚨臉?biāo)準(zhǔn)化,而趨向標(biāo)準(zhǔn)化,雙端的業(yè)務(wù)一致性得到了提升。這些潛在的架構(gòu)好處,對(duì)未來(lái)的業(yè)務(wù)維護(hù)和擴(kuò)展都打下了比較好的地基。
2.3 外賣(mài)容器化架構(gòu)全景圖
整個(gè)外賣(mài)容器化架構(gòu)可以按照從下到上,從左到右的視角進(jìn)行解讀:
最底層是系統(tǒng)服務(wù),因?yàn)槲覀儾捎昧薍5和RN這樣跨端的技術(shù)棧,使得iOS系統(tǒng)和Android系統(tǒng)成為了最底層。
系統(tǒng)服務(wù)之上是集團(tuán)基于Native建設(shè)的基建,全公司通用,覆蓋了研發(fā)工程中方方面面的基礎(chǔ)服務(wù)。
在基建之上是我們定義的容器層。我們嘗試用單一技術(shù)棧解決所有問(wèn)題。但經(jīng)過(guò)我們的探索,覺(jué)得不太可能實(shí)現(xiàn)。好的架構(gòu)要匹配業(yè)務(wù)形態(tài),業(yè)務(wù)的訴求決定了我們不能選擇唯一的技術(shù)棧去解決所有問(wèn)題,細(xì)分外賣(mài)的業(yè)務(wù)場(chǎng)景可得到以下3個(gè)方向的頁(yè)面分類:
再往上,就是垂直的業(yè)務(wù),外賣(mài)目前有流量業(yè)務(wù)、交易業(yè)務(wù)、商家業(yè)務(wù)、商品業(yè)務(wù)、廣告業(yè)務(wù)、營(yíng)銷(xiāo)業(yè)務(wù)、閃購(gòu)業(yè)務(wù)等。業(yè)務(wù)都是垂直向下依賴,直接可見(jiàn)容器,可見(jiàn)基建,能夠很好地獲取到各種已經(jīng)建設(shè)的能力去完成業(yè)務(wù)的需求。
最上面是承載的App端,目前有四端,包括外賣(mài)、點(diǎn)評(píng)、美團(tuán)、閃購(gòu)等等。
右側(cè)是測(cè)試發(fā)布和線上監(jiān)控,相對(duì)于常規(guī)的移動(dòng)端App架構(gòu)而言,容器化架構(gòu)的測(cè)試發(fā)布和監(jiān)控是更為精細(xì)化的。不僅僅要關(guān)注端本身的可用性,還需要關(guān)注容器、容器承載的模塊、模塊展示的模板,模板里面的樣式這些的可用性。
2.4 容器化的挑戰(zhàn)
容器化架構(gòu)相對(duì)常規(guī)的移動(dòng)端架構(gòu)而言,它從管理移動(dòng)端的代碼轉(zhuǎn)變成管理移動(dòng)端的容器建設(shè)代碼和業(yè)務(wù)遠(yuǎn)端開(kāi)發(fā)代碼,多出了容器和業(yè)務(wù)遠(yuǎn)端下發(fā)。這不僅僅是對(duì)技術(shù)上的挑戰(zhàn),對(duì)長(zhǎng)期做客戶端開(kāi)發(fā)同學(xué),也需要一個(gè)思維轉(zhuǎn)變的跳轉(zhuǎn)。
一致性的挑戰(zhàn):容器需要在多個(gè)宿主應(yīng)用之中運(yùn)行,宿主應(yīng)用的環(huán)境一致性直接影響了容器的一致性。我們的策略是兩手準(zhǔn)備,一方面利用外賣(mài)業(yè)務(wù)的優(yōu)勢(shì)推動(dòng)宿主應(yīng)用的環(huán)境對(duì)齊;另一方面將容器建設(shè)成SDK,通過(guò)SDK將長(zhǎng)期保持容器的一致性,也通過(guò)SDK內(nèi)部的設(shè)計(jì)屏蔽應(yīng)用之間的差異;對(duì)于Android和iOS平臺(tái),我們通過(guò)分層的設(shè)計(jì),盡可能屏蔽平臺(tái)的差異。綜上所述,一致性的挑戰(zhàn)在于(1)容器運(yùn)行的宿主應(yīng)用的環(huán)境一致性;(2)不同應(yīng)用不同版本容器的一致性;(3)Android和iOS平臺(tái)容器的對(duì)業(yè)務(wù)的一致性。
動(dòng)態(tài)發(fā)布的挑戰(zhàn):長(zhǎng)期以來(lái),客戶端同學(xué)的開(kāi)發(fā)概念里面只有App版本的概念,而當(dāng)我們逐漸把業(yè)務(wù)代碼做成遠(yuǎn)端下發(fā)時(shí),將會(huì)新增一個(gè)線上動(dòng)態(tài)發(fā)版的概念。當(dāng)我們?cè)诎l(fā)布業(yè)務(wù)的時(shí)候,相對(duì)以往的工作,多出需要去考慮這個(gè)業(yè)務(wù)的版本,可以運(yùn)行的容器對(duì)應(yīng)的App上下界版本。另外,發(fā)版的周期也會(huì)新增業(yè)務(wù)的發(fā)版周期,不僅僅是App的發(fā)版周期。這兩者在一起將會(huì)產(chǎn)生新的火花,業(yè)務(wù)的版本和App的版本如何適配的問(wèn)題,業(yè)務(wù)動(dòng)態(tài)發(fā)版的周期和App的發(fā)版周期如何適配的問(wèn)題。外賣(mài)這邊的解決方式是建設(shè)主版本迭代+周迭代的模型。
監(jiān)控運(yùn)維的挑戰(zhàn):以往的移動(dòng)端架構(gòu),我們更加關(guān)注的是端本身的可用性,然而當(dāng)我們演進(jìn)到容器化架構(gòu)的時(shí)候,僅僅關(guān)注端的可用性已經(jīng)遠(yuǎn)遠(yuǎn)不能確定業(yè)務(wù)是可用的了。我們需要從端的可用性延伸出下載鏈路、加載鏈路,使用鏈路上的可用性,針對(duì)每個(gè)重要的環(huán)境,都做好監(jiān)控運(yùn)維。
3.1 MRN容器
3.1.1 MRN容器簡(jiǎn)介
React Native框架本身只是一個(gè)運(yùn)行時(shí)環(huán)境中的渲染引擎,可以將同一套JS代碼分別在Android和iOS系統(tǒng)上最終以Native的方式渲染頁(yè)面,從而為App提供了基礎(chǔ)的跨端能力。但從工程化的角度來(lái)看,如果想在App中大規(guī)模地應(yīng)用RN技術(shù),除了RN框架本身外,還需要在開(kāi)發(fā)、構(gòu)建、測(cè)試、部署、運(yùn)維等諸多方面的配合。
MRN(Meituan React Native)是美團(tuán)基于React Native框架改造并完善而成的一套動(dòng)態(tài)化方案,在RN的基礎(chǔ)上提供了容器化能力、動(dòng)態(tài)化能力、多端復(fù)用能力和工程化保障。MRN在開(kāi)發(fā)效率、穩(wěn)定性、性能體驗(yàn)、動(dòng)態(tài)化和監(jiān)控運(yùn)維等多方面進(jìn)行了能力升級(jí)和擴(kuò)展,滿足了美團(tuán)RN開(kāi)發(fā)工程化的需要。目前,MRN已接入美團(tuán)40多個(gè)App,核心框架及生態(tài)工具有超過(guò)100位內(nèi)部代碼貢獻(xiàn)者,總PV超過(guò)4億。
3.1.2 Roo組件庫(kù)
下面再介紹一下外賣(mài)建設(shè)的兩個(gè)UI相關(guān)的技術(shù)項(xiàng)目,Roo組件庫(kù)和組件樣式動(dòng)態(tài)配置。
外賣(mài)在2018年底開(kāi)始試驗(yàn)MRN容器在外賣(mài)業(yè)務(wù)上的應(yīng)用,并在2019年上半年進(jìn)行了大面積的頁(yè)面落地。目前,外賣(mài)已有近60個(gè)RN頁(yè)面上線,占外賣(mài)頁(yè)面比例超80%,其中包括Tab頁(yè)面“我的”、提單選擇紅包頁(yè)、訂單評(píng)價(jià)頁(yè)等高PV頁(yè)面。MRN容器的接入,給外賣(mài)App的容器化、動(dòng)態(tài)化、人效提升、包大小瘦身等方面都做出了不小的貢獻(xiàn)。
3.2 Titans容器
3.2.1 Titans容器簡(jiǎn)介
Titans容器是美團(tuán)系A(chǔ)pp統(tǒng)一的Web容器組件,基于蘋(píng)果提供的WebView組件,將WebView容器化,統(tǒng)一了WebView的UI展示和交互方式,規(guī)范了橋協(xié)議的使用范式,同時(shí)預(yù)置了諸多基礎(chǔ)能力和業(yè)務(wù)能力。Titans容器大大提高了Web頁(yè)面的開(kāi)發(fā)效率和用戶體驗(yàn)上的一致性。
Titans容器在外賣(mài)業(yè)務(wù)中的使用場(chǎng)景非常豐富,其中最重要的使用場(chǎng)景是各種運(yùn)營(yíng)頁(yè)和活動(dòng)頁(yè),例如點(diǎn)擊首頁(yè)頂部Banner的廣告落地頁(yè)、為你優(yōu)選、限時(shí)秒殺等活動(dòng)運(yùn)營(yíng)頁(yè)等;還有客服頁(yè)、幫助反饋?lái)?yè)、商家入駐頁(yè)、美團(tuán)公益頁(yè)等功能性頁(yè)面;作為一級(jí)入口頁(yè)面的美團(tuán)會(huì)員頁(yè)面,也是一個(gè)基于Enlight的Titans容器。
外賣(mài)容器化建設(shè),首先需要要區(qū)分的是核心頁(yè)面和非核心頁(yè)面。外賣(mài)業(yè)務(wù)中對(duì)核心頁(yè)面的定義是頁(yè)面DAU>美團(tuán)DAU的5%或者是下單關(guān)鍵路徑。為什么要先按照是否為核心頁(yè)面進(jìn)行拆分呢?重點(diǎn)就在于改造的成本。核心頁(yè)面的業(yè)務(wù)復(fù)雜度決定了它不容易做全頁(yè)面的動(dòng)態(tài)化,它比較適合做局部的動(dòng)態(tài)化方案。核心頁(yè)面的復(fù)雜度在于業(yè)務(wù)本身復(fù)雜,最重要的是核心頁(yè)面往往會(huì)有多個(gè)垂直業(yè)務(wù)團(tuán)隊(duì)共同的開(kāi)發(fā)維護(hù),大家各自有重點(diǎn)關(guān)注的模塊,做全頁(yè)面的動(dòng)態(tài)化,無(wú)法做到有效的物理隔離。
而對(duì)于非核心頁(yè)面,業(yè)務(wù)功能和交互相對(duì)簡(jiǎn)單,組織關(guān)系也較為確定,更適合做標(biāo)準(zhǔn)的MRN和Titans容器化。所以我們的策略是核心頁(yè)面做到支撐頁(yè)面模塊級(jí)別的業(yè)務(wù)動(dòng)態(tài)和復(fù)用,非核心頁(yè)面可以做到頁(yè)面級(jí)別的動(dòng)態(tài)化和復(fù)用。頁(yè)面容器化的核心含義就是把一個(gè)頁(yè)面劃分為若干個(gè)模塊,每個(gè)模塊成為一個(gè)業(yè)務(wù)容器,每個(gè)容器的填充既可以用Native的方式實(shí)現(xiàn),也可以用Mach實(shí)現(xiàn)(Mach是外賣(mài)自研的頁(yè)面局部動(dòng)態(tài)化技術(shù)),可以支持iOS/Android/小程序三端跨平臺(tái)運(yùn)行。頁(yè)面本身則化身為容器的管理者,負(fù)責(zé)子容器的編排和布局,并支持其動(dòng)態(tài)化。
4.1 頁(yè)面容器化設(shè)計(jì)思路
頁(yè)面容器化設(shè)計(jì)中主要分為三個(gè)階段,模塊有序化、模塊編排化、漸進(jìn)式業(yè)務(wù)落地。
4.2 業(yè)務(wù)構(gòu)建模塊標(biāo)準(zhǔn)化
從App頁(yè)面開(kāi)發(fā)的角度看,一個(gè)完整的頁(yè)面可以按照不同的功能及不同業(yè)務(wù)屬性劃分出多個(gè)不同的模塊。
業(yè)務(wù)構(gòu)建泛指由多個(gè)業(yè)務(wù)模塊組合拼裝為一個(gè)業(yè)務(wù)頁(yè)面的過(guò)程,涉及頁(yè)面本身(UIViewController/Activity)以及各個(gè)業(yè)務(wù)模塊的構(gòu)造過(guò)程,前后端業(yè)務(wù)數(shù)據(jù)以及頁(yè)面和業(yè)務(wù)模塊之間的數(shù)據(jù)交互過(guò)程,業(yè)務(wù)模塊內(nèi)部的數(shù)據(jù)處理以及視圖刷新流程。
模塊標(biāo)準(zhǔn)化指的將業(yè)務(wù)構(gòu)建涉及到的多個(gè)過(guò)程通過(guò)規(guī)范化的方式確定下來(lái),形成唯一的標(biāo)準(zhǔn)。模塊標(biāo)準(zhǔn)化一方面能夠在解決業(yè)務(wù)共性問(wèn)題的基礎(chǔ)上提供業(yè)務(wù)難點(diǎn)專項(xiàng)解決方案,另一方面能夠在框架基礎(chǔ)上形成能力約束,減少重復(fù)建設(shè)、低質(zhì)量建設(shè)的問(wèn)題。
業(yè)務(wù)構(gòu)建模塊標(biāo)準(zhǔn)化中我們抽象了四層,下面將分別進(jìn)行解讀。
通過(guò)業(yè)務(wù)構(gòu)建模塊標(biāo)準(zhǔn)化的建設(shè),業(yè)務(wù)模塊已經(jīng)是標(biāo)準(zhǔn)化的了,可以在跨頁(yè)面間自由組合,這為頁(yè)面容器化打下了基礎(chǔ)。
在頁(yè)面容器化中最基礎(chǔ)的能力有以下幾點(diǎn):頁(yè)面中業(yè)務(wù)模塊可編排能力,動(dòng)態(tài)上線前端AB實(shí)驗(yàn)的能力,增量上線動(dòng)態(tài)模塊的能力。實(shí)現(xiàn)這些能力最重要的就是進(jìn)行前后端數(shù)據(jù)協(xié)議標(biāo)準(zhǔn)化建設(shè)。客戶端根據(jù)數(shù)據(jù)協(xié)議中的模塊唯一標(biāo)識(shí)匹配并構(gòu)造業(yè)務(wù)模塊,在完成模塊數(shù)據(jù)的填充后會(huì)根據(jù)數(shù)據(jù)協(xié)議中的模塊布局信息完成模塊的布局。針對(duì)Mach動(dòng)態(tài)模塊,我們創(chuàng)建了基于模板ID的模塊匹配和數(shù)據(jù)填充流程,可以支持Mach動(dòng)態(tài)模板的增量上線。在數(shù)據(jù)協(xié)議中針對(duì)前端AB實(shí)驗(yàn)我們預(yù)留了AB實(shí)驗(yàn)和通參字段,在數(shù)據(jù)填充階段通過(guò)容器化接口傳入動(dòng)態(tài)模塊中,用于支持AB實(shí)驗(yàn)的動(dòng)態(tài)上線。
在容器化上線的過(guò)程中屬于接口的大版本升級(jí),為了保證容器的高可用性,客戶端從模塊級(jí)別和API級(jí)別實(shí)現(xiàn)了兩套降級(jí)容災(zāi)方案。
模塊級(jí)別的降級(jí)方案主要針對(duì)Mach動(dòng)態(tài)模塊,與Native模塊不同,Mach動(dòng)態(tài)模塊需要預(yù)先下載動(dòng)態(tài)模板才能正常地完成模塊的載入和渲染。為了保證動(dòng)態(tài)模塊的加載成功率,我們一方面在接口上線前利用Eva(美團(tuán)內(nèi)部系統(tǒng))對(duì)Mach模板的下載進(jìn)行預(yù)熱。另一方面,我們?cè)O(shè)計(jì)了動(dòng)態(tài)模塊的主動(dòng)降級(jí)方案,針對(duì)動(dòng)態(tài)模塊的動(dòng)態(tài)上線使用Native模塊進(jìn)行兜底降級(jí),對(duì)于跟版動(dòng)態(tài)模塊使用App內(nèi)置模板的方案進(jìn)行兜底降級(jí)。
API級(jí)別的容災(zāi)方案主要為了保障客戶端在新接口不穩(wěn)定的情況下可以自行降級(jí)到舊接口。針對(duì)這個(gè)問(wèn)題,我們對(duì)線上老接口設(shè)計(jì)了數(shù)據(jù)結(jié)構(gòu)映射方案,在客戶端通過(guò)配置化的方式可以把老接口的數(shù)據(jù)結(jié)構(gòu)映射為新接口的數(shù)據(jù)結(jié)構(gòu)。這樣在上層業(yè)務(wù)無(wú)感知的情況下,可以做到容災(zāi)方案的上下線。
4.3 小結(jié)
通過(guò)頁(yè)面容器化,使得頁(yè)面只需要關(guān)心頁(yè)面級(jí)的構(gòu)造方式,而無(wú)需關(guān)心某一模塊內(nèi)部如何實(shí)現(xiàn)動(dòng)態(tài)化的。把頁(yè)面與頁(yè)面的模塊分離,也符合目前外賣(mài)客戶端的組織結(jié)構(gòu),有利于業(yè)務(wù)組間的協(xié)作。同時(shí),頁(yè)面容器化使得外賣(mài)核心頁(yè)面具備了符合外賣(mài)業(yè)務(wù)場(chǎng)景下的動(dòng)態(tài)能力,漸進(jìn)式把Native靜態(tài)模塊過(guò)渡到具備動(dòng)態(tài)能力的模塊,從模塊的維度使整個(gè)頁(yè)面具備了動(dòng)態(tài)能力。這種漸進(jìn)式的遷移方案把容器遷移跟業(yè)務(wù)模塊的遷移分隔開(kāi),大大降低了頁(yè)面容器化改造的風(fēng)險(xiǎn)。
5.1 容器化架構(gòu)衡量指標(biāo)的特點(diǎn)
質(zhì)量和性能指標(biāo)是衡量我們App開(kāi)發(fā)質(zhì)量和用戶體驗(yàn)的重要依據(jù),是我們一直都非常關(guān)注的重點(diǎn)數(shù)據(jù)。在非容器化時(shí)代,我們大多數(shù)的指標(biāo)都和App的使用環(huán)節(jié)緊密相關(guān),因?yàn)樵诜侨萜骰瘯r(shí)代,邏輯鏈路相對(duì)簡(jiǎn)單,例如我們打開(kāi)一個(gè)新頁(yè)面時(shí),我們首先創(chuàng)建頁(yè)面實(shí)例,然后發(fā)起網(wǎng)絡(luò)請(qǐng)求,同時(shí)頁(yè)面會(huì)經(jīng)歷一系列生命周期方法,最后渲染。這時(shí)我們可能會(huì)關(guān)注網(wǎng)絡(luò)請(qǐng)求的成功率和請(qǐng)求時(shí)間,頁(yè)面的渲染時(shí)間,和過(guò)成功是否發(fā)生Crash,這個(gè)過(guò)程相對(duì)更短暫,指標(biāo)更少,所以監(jiān)控起來(lái)也更容易。
外賣(mài)的容器化大大提升了外賣(mài)業(yè)務(wù)的復(fù)用能力、動(dòng)態(tài)能力、模塊化和開(kāi)發(fā)效率,但同時(shí)也帶來(lái)了更長(zhǎng)的邏輯鏈路,鏈路從時(shí)間維度上劃分是:下載鏈路、加載鏈路、使用鏈路。例如我們?cè)谑褂肕RN容器的時(shí)候,會(huì)涉及到bundle的啟動(dòng)下載或預(yù)熱下載,bundle解壓縮,MRN容器引擎初始化,bundle加載,JS的加載、執(zhí)行,頁(yè)面渲染等步驟,其中的每個(gè)步驟都可能存在性能問(wèn)題和質(zhì)量風(fēng)險(xiǎn)。因此,我們需要升級(jí)我們的衡量指標(biāo)系統(tǒng)來(lái)應(yīng)對(duì)容器化帶來(lái)的新的挑戰(zhàn)。
5.2 鏈路指標(biāo)
5.3 關(guān)鍵指標(biāo)
因?yàn)槿萜骰氖褂眯纬闪艘粋€(gè)串行的鏈路,所以如果某個(gè)關(guān)鍵節(jié)點(diǎn)失敗,會(huì)導(dǎo)致容器功能不可使用,關(guān)鍵指標(biāo)的任務(wù)就是從上述眾多的指標(biāo)當(dāng)中篩選出這些關(guān)鍵節(jié)點(diǎn)。例如在下載鏈路中bundle下載的成功率和API的成功率,加載鏈路中bundle加載的成功率和模塊匹配的成功率,下載或加載失敗都無(wú)法再進(jìn)行鏈路中的后續(xù)步驟,針對(duì)上面的成功率指標(biāo),我們會(huì)添加分鐘級(jí)別的實(shí)時(shí)監(jiān)控告警,做到及時(shí)發(fā)現(xiàn),快速響應(yīng)和緊急修復(fù)。
在使用鏈路中模塊渲染的成功率、Native Crash率、JS錯(cuò)誤率也屬于關(guān)鍵指標(biāo),這些任務(wù)的失敗也會(huì)導(dǎo)致容器的不可用,針對(duì)這些指標(biāo)我們也會(huì)采用實(shí)時(shí)監(jiān)控措施,并且添加降級(jí)手段,例如回滾bundle版本,或者把MRN和Mach容器降級(jí)為Native容器。
上面講到了容器化架構(gòu)的各項(xiàng)衡量指標(biāo),那么把這些指標(biāo)具體落到實(shí)處的工作就是線上的運(yùn)維監(jiān)控工作。工欲善其事,必先利其器,對(duì)于監(jiān)控運(yùn)維工作,一定要有合適的監(jiān)控工具輔助配合才能事半功倍,公司內(nèi)有很多優(yōu)秀的監(jiān)控統(tǒng)計(jì)工具可供使用,這里的難點(diǎn)就是如何根據(jù)監(jiān)控的需要判斷選擇合適的工具。還有就是合理的劃分監(jiān)控維度和數(shù)據(jù)指標(biāo)的優(yōu)先級(jí),例如對(duì)于能夠影響到鏈路穩(wěn)定性的關(guān)鍵指標(biāo),我們需要做到分鐘級(jí)的監(jiān)控,一旦出現(xiàn)問(wèn)題就能及時(shí)收到告警,對(duì)于非關(guān)鍵指標(biāo),則通過(guò)生成日?qǐng)?bào)的方式,方便開(kāi)發(fā)者的統(tǒng)計(jì)和分析。
工具的使用上主要分為大盤(pán)工具、具體異常工具、灰度降級(jí)工具、告警工具等(以下是美團(tuán)內(nèi)部使用的工具)。
業(yè)務(wù)覆蓋維度監(jiān)控可以分為全局監(jiān)控和局部(單業(yè)務(wù))監(jiān)控。
時(shí)間維度監(jiān)控:可以按天、小時(shí)、分鐘的時(shí)間維度。天級(jí)別的監(jiān)控主要是一些非關(guān)鍵路徑指標(biāo),例如一些性能指標(biāo),頁(yè)面加載時(shí)間、頁(yè)面FPS、JS渲染時(shí)間等,我們可以按天維度的生成數(shù)據(jù)報(bào)表,已郵件的數(shù)據(jù)發(fā)送日?qǐng)?bào)。當(dāng)App灰度上線時(shí),我們會(huì)開(kāi)始小時(shí)級(jí)別的監(jiān)控,每過(guò)半小時(shí)通過(guò)IM軟件向廣播一些關(guān)鍵指標(biāo),方便開(kāi)發(fā)者跟蹤線上數(shù)據(jù)的穩(wěn)定性。分鐘級(jí)別的監(jiān)控則是針對(duì)關(guān)鍵指標(biāo),觀察分鐘維度上的變化,如果關(guān)鍵指標(biāo)超過(guò)閾值,或者波動(dòng)過(guò)大,就會(huì)及時(shí)產(chǎn)生告警。
下面我們以一個(gè)開(kāi)發(fā)者的視角去看一下外賣(mài)容器化架構(gòu)的監(jiān)控運(yùn)維系統(tǒng)。從獲取信息的方式上可以分為主動(dòng)查詢和被動(dòng)推送,開(kāi)發(fā)者可以通過(guò)監(jiān)控工具監(jiān)控全局和局部數(shù)據(jù)的變化趨勢(shì),也可以分析具體異常Case;也可以從IM工具,郵件等收到相關(guān)的推送數(shù)據(jù),以便及時(shí)響應(yīng)。在控制運(yùn)維上,開(kāi)發(fā)者可以通過(guò)Eva、Horn等美團(tuán)內(nèi)部的灰度系統(tǒng)進(jìn)行灰度發(fā)布,當(dāng)灰度期發(fā)現(xiàn)問(wèn)題的時(shí)候,可以及時(shí)地通過(guò)停止灰度,版本回滾,關(guān)閉入口的方式進(jìn)行降級(jí)容災(zāi)處理。
7.1 容器化架構(gòu)發(fā)布體系
容器化使外賣(mài)業(yè)務(wù)具備了強(qiáng)大的動(dòng)態(tài)化能力,但動(dòng)態(tài)化能力又和需要相應(yīng)的發(fā)布能力來(lái)支持,發(fā)布能力是我們業(yè)務(wù)開(kāi)發(fā)質(zhì)量和效率的重要保障,也是我們?nèi)萜骰ㄔO(shè)工作過(guò)程中的重點(diǎn)環(huán)節(jié),這一節(jié)主要介紹一下外賣(mài)容器化的發(fā)布能力。
從發(fā)布能力類型的角度看主要可以分為三種類型:(1)容器內(nèi)容的發(fā)布,包括發(fā)布整個(gè)頁(yè)面或者發(fā)布頁(yè)面中的局部模塊;(2)配置下發(fā),通過(guò)API或其他配置平臺(tái),下發(fā)布局協(xié)議、AB測(cè)試、樣式配置、功能配置、模板配置、容器配置等,大大提高了業(yè)務(wù)的靈活度和線上驗(yàn)證能力;(3)灰度、降級(jí)下發(fā),通過(guò)UUID,用戶畫(huà)像等信息做到灰度發(fā)布,降級(jí)回滾等控制能力。
從發(fā)布資源的的角度看主要分為兩種:一種是普通的資源,例如發(fā)布一個(gè)Web頁(yè)面,或者通過(guò)發(fā)布新版API來(lái)控制頁(yè)面局部容器的展示與否和展示的位置,同時(shí)我們也可以進(jìn)行一些AB Test操作;另一種是bundle資源,主要是針對(duì)MRN容器和Mach容器,每個(gè)MRN容器和Mach容器的資源都會(huì)先被打包成一個(gè)bundle,然后通過(guò)發(fā)布系統(tǒng)下發(fā)到終端,然后終端解析bundle中的代碼和資源,最終渲染頁(yè)面。
從發(fā)布階段的角度看,可以分為測(cè)試階段、上線階段、灰度階段和全量階段,其中上線階段是最終的環(huán)節(jié),我們?cè)黾恿撕芏嘈r?yàn)和保護(hù)手段來(lái)盡量保證上線操作的正確性。
7.2 跟版本發(fā)布流程
雖然我們具隨時(shí)備動(dòng)態(tài)發(fā)布能力,但正常的版本迭代還是會(huì)存在中,所以外賣(mài)這邊的節(jié)奏是周動(dòng)態(tài)迭代+雙周版本迭代,這保證了我們的開(kāi)發(fā)工作有個(gè)一清晰的周期。在動(dòng)態(tài)發(fā)布階段中最關(guān)鍵的階段操作上線階段。以MRN為例,目前外賣(mài)業(yè)務(wù)中應(yīng)有70多個(gè)bundle,再算上測(cè)試環(huán)境的bundle就有接近150個(gè)bundle,只是管理這些bundle就是一個(gè)復(fù)雜的工作,況且在進(jìn)行上線操作時(shí)還是涉及發(fā)布的目標(biāo)App、App版本的上下界、MRN版本的上下界等,一不小心就會(huì)造成操作失誤,所以進(jìn)行上線操作時(shí)需要非常謹(jǐn)慎。
我們針對(duì)操作上線階段進(jìn)行了事務(wù)流水線,通過(guò)流水線建立保護(hù)措施,一個(gè)bundle的上線要經(jīng)歷一個(gè)流水線的若干操作。首先,操作人根據(jù)上線SOP手冊(cè)進(jìn)行若干檢查操作,同時(shí)編寫(xiě)標(biāo)準(zhǔn)格式的發(fā)布說(shuō)明,然后周知相關(guān)核心人員后在操作系統(tǒng)上發(fā)起上線申請(qǐng),Leader和QA收到申請(qǐng)后會(huì)進(jìn)行檢查并審批,審批通過(guò)后還要避開(kāi)App使用的高峰期或節(jié)假日上線,上線后通過(guò)灰度發(fā)布觀察各項(xiàng)數(shù)據(jù)指標(biāo),指標(biāo)正常后全量發(fā)布。
7.3 bundle資源發(fā)布
bundle是我們最常發(fā)布的資源類型,這里再結(jié)合發(fā)布工具講解一下bundle的發(fā)布過(guò)程。MRN和Mach都是以bundle的形式下發(fā)到設(shè)備終端的,我們?cè)诎l(fā)布bundle的時(shí)候主要會(huì)用到兩個(gè)工具,打包工具Talos和發(fā)布工具Eva(美團(tuán)內(nèi)部工具)。一個(gè)bundle的工程文件主要由三個(gè)部分組成:配置文件、源代碼和資源文件,其中配置文件用于指導(dǎo)Talos對(duì)工程文件進(jìn)行打包,多個(gè)bundle可以共享一份配置文件。當(dāng)我們準(zhǔn)備發(fā)布一個(gè)bundle時(shí),先找到該bundle在Talos的發(fā)布模板,選擇發(fā)布環(huán)境(測(cè)試或線上),然后進(jìn)行一鍵打包,然后Talos會(huì)進(jìn)行一系列流水線操作,包括Clone代碼、配置環(huán)境、進(jìn)行Lint檢查、構(gòu)建和上傳等。Talos打包完畢后將bundle上傳到Eva系統(tǒng),然后Eva負(fù)責(zé)bundle的分包、上線、下線、灰度等操作,最終下發(fā)到終端設(shè)備上。
未來(lái),我們還將引入美團(tuán)住宿的MRN-DevOps來(lái)進(jìn)一步的屏蔽當(dāng)前多系統(tǒng)的問(wèn)題,降低整個(gè)周期管理的成本,特別是發(fā)布前的人工檢查成本,逐漸實(shí)現(xiàn)RD在一個(gè)平臺(tái)上操作從研發(fā)到發(fā)布運(yùn)維的所有實(shí)現(xiàn)。盡可能地減少人工成本,提升自動(dòng)化。
7.4 多種發(fā)布能力綜合使用
上面介紹的是以bundle資源形式的發(fā)布流程,過(guò)程較為清晰簡(jiǎn)單。下面再結(jié)合外賣(mài)首頁(yè),介紹一下局部容器化的發(fā)布方式。外賣(mài)首頁(yè)是典型的流式列表,在局部容器化的架構(gòu)下,首頁(yè)就是由一個(gè)個(gè)矩形容器以ListView方式布局的,容器分兩種,Native容器和Mach容器,Mach容器是一個(gè)通用容器,我們可以編寫(xiě)不同的樣式模板,下發(fā)到終端后交由通用Mach容器來(lái)渲染,以此達(dá)到只使用通用容器展示不同UI樣式的目的,這里涉及了Mach的發(fā)布系統(tǒng)。
首頁(yè)各子容器相當(dāng)于一塊塊積木,它們的位置排布、展示與否、模板的選擇等最終交由API控制,API具備了控制首頁(yè)布局,樣式展示的能力,而不再是單純的數(shù)據(jù)源。同時(shí),首頁(yè)也涉及了AB能力、灰度降級(jí)策略等其實(shí)配置項(xiàng)下發(fā)系統(tǒng)。可以看到外賣(mài)首頁(yè)的容器化是由多種發(fā)布能力配合支撐的,是外賣(mài)發(fā)布能力體系的“集大成者”。
好的架構(gòu)是要隨著業(yè)務(wù)的發(fā)展,不斷演變?nèi)ミm應(yīng)業(yè)務(wù)的發(fā)展。美團(tuán)外賣(mài)從一個(gè)很小規(guī)模,每日單量只有幾千的業(yè)務(wù),逐漸地走到今天,每日單量峰值超過(guò)4000萬(wàn),組織架構(gòu)也從一個(gè)十幾個(gè)人的團(tuán)隊(duì),逐漸發(fā)展到現(xiàn)在多角色、多垂直業(yè)務(wù)方向,上千人共同協(xié)作的團(tuán)隊(duì)。移動(dòng)端上的架構(gòu),為了適應(yīng)業(yè)務(wù)的發(fā)展要求,也經(jīng)歷了組件化、平臺(tái)化、RN混合化,再到現(xiàn)在向容器化的變遷。
容器化架構(gòu)相對(duì)于傳統(tǒng)的移動(dòng)端架構(gòu)而言,充分地利用了現(xiàn)在的跨端技術(shù),將動(dòng)態(tài)化的能力最大化的賦予業(yè)務(wù)。通過(guò)動(dòng)態(tài)化,帶來(lái)業(yè)務(wù)迭代周期縮短、編譯的加速、開(kāi)發(fā)效率的提升等好處。同時(shí),也解決了我們面臨著的多端復(fù)用、平臺(tái)能力、平臺(tái)支撐、單頁(yè)面多業(yè)務(wù)團(tuán)隊(duì)、業(yè)務(wù)動(dòng)態(tài)訴求強(qiáng)等業(yè)務(wù)問(wèn)題。
當(dāng)然,容器化架構(gòu)帶來(lái)好處的同時(shí),對(duì)線上的可用性、容器的可用性、支撐業(yè)務(wù)的線上發(fā)布上提出了更加嚴(yán)格的要求。我們通過(guò)監(jiān)控下載、加載、使用鏈路上的可用性,來(lái)保障線上動(dòng)態(tài)業(yè)務(wù)的可用性。針對(duì)容器,我們利用成熟的測(cè)試基建,建設(shè)容器的自動(dòng)化測(cè)試來(lái)保障容器的可用性。針對(duì)發(fā)布,我們建設(shè)迭代流程,配合發(fā)布流水線,將線上的發(fā)布變得更為可控。
截止到目前為止,外賣(mài)業(yè)務(wù)經(jīng)過(guò)了幾十個(gè)動(dòng)態(tài)化業(yè)務(wù)上線窗口,累積共發(fā)版百次以上。未來(lái)半年,我們還將進(jìn)一步從業(yè)務(wù)需求入手,將業(yè)務(wù)需求細(xì)分歸類,讓產(chǎn)品側(cè)逐漸建立容器和動(dòng)態(tài)化需求的概念,能夠從源頭上,逐漸的將業(yè)務(wù)進(jìn)行劃分,最終使得每個(gè)業(yè)務(wù)需求,都可以歸類抽象成可以動(dòng)態(tài)下發(fā)的業(yè)務(wù)和容器能力建設(shè),從而進(jìn)一步的完善容器化架構(gòu)的能力和支持更多的的業(yè)務(wù)場(chǎng)景。
郭賽,同同,徐宏,均為美團(tuán)外賣(mài)iOS工程師。
---------- END ----------
招聘信息
美團(tuán)外賣(mài)長(zhǎng)期招聘Android、iOS、FE高級(jí)/資深工程師和技術(shù)專家,感興趣的同學(xué)可投遞簡(jiǎn)歷至:tech@meituan.com(郵件標(biāo)題請(qǐng)注明:美團(tuán)外賣(mài))。
數(shù)字化時(shí)代,外賣(mài)服務(wù)已經(jīng)成為校園生活的重要組成部分。隨著智能手機(jī)的普及和互聯(lián)網(wǎng)技術(shù)的發(fā)展,校園外賣(mài)小程序系統(tǒng)的出現(xiàn)更是改變了傳統(tǒng)外賣(mài)模式的格局。本文將為你詳細(xì)解析如何從零到一構(gòu)建一個(gè)高效的校園外賣(mài)小程序系統(tǒng)。
一、需求分析與規(guī)劃
首先,要明確校園外賣(mài)小程序系統(tǒng)的用戶需求,包括學(xué)生、餐廳和配送員等角色。學(xué)生需要方便的下單、支付和查看訂單進(jìn)程等功能;餐廳需要接單、處理訂單、烹飪、配送等功能;配送員需要接收訂單、配送、確認(rèn)收貨等功能。
二、技術(shù)選型與準(zhǔn)備
基于需求,我們需要選擇合適的技術(shù)棧來(lái)開(kāi)發(fā)校園外賣(mài)小程序系統(tǒng)。推薦使用微信小程序開(kāi)發(fā)框架,結(jié)合JavaScript、CSS和HTML等前端技術(shù)進(jìn)行開(kāi)發(fā)。在后端,可以使用Node.js、Python等語(yǔ)言和框架,實(shí)現(xiàn)數(shù)據(jù)處理、接口服務(wù)等。同時(shí),為了保證系統(tǒng)的穩(wěn)定性和擴(kuò)展性,還需進(jìn)行技術(shù)準(zhǔn)備,如服務(wù)器部署、數(shù)據(jù)庫(kù)設(shè)計(jì)等。
三、界面設(shè)計(jì)
為了滿足用戶需求,界面設(shè)計(jì)應(yīng)簡(jiǎn)潔明了、易于操作。在設(shè)計(jì)過(guò)程中,需要考慮各個(gè)角色的用戶體驗(yàn),如學(xué)生、餐廳和配送員等。此外,還需考慮小程序的響應(yīng)速度和兼容性,確保在不同設(shè)備和網(wǎng)絡(luò)環(huán)境下的良好體驗(yàn)。
四、數(shù)據(jù)庫(kù)設(shè)計(jì)
數(shù)據(jù)庫(kù)是校園外賣(mài)小程序系統(tǒng)的核心,需要合理設(shè)計(jì)數(shù)據(jù)庫(kù)結(jié)構(gòu)以實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)、讀取和更新等操作。針對(duì)不同的業(yè)務(wù)需求,需要建立相應(yīng)的數(shù)據(jù)表,并定義合適的數(shù)據(jù)類型和字段長(zhǎng)度等。同時(shí),為了保證數(shù)據(jù)的完整性,需要進(jìn)行事務(wù)處理和數(shù)據(jù)備份。
五、功能實(shí)現(xiàn)與測(cè)試
根據(jù)需求分析和技術(shù)準(zhǔn)備,可以開(kāi)始實(shí)現(xiàn)校園外賣(mài)小程序系統(tǒng)的各個(gè)功能模塊。在實(shí)現(xiàn)過(guò)程中,要注重代碼的可讀性和可維護(hù)性,同時(shí)要保證系統(tǒng)的性能和安全性。測(cè)試是確保系統(tǒng)質(zhì)量的重要環(huán)節(jié),包括單元測(cè)試、集成測(cè)試和系統(tǒng)測(cè)試等。在測(cè)試過(guò)程中,要發(fā)現(xiàn)和修復(fù)潛在的問(wèn)題和缺陷,確保系統(tǒng)的穩(wěn)定性和可用性。
六、上線與運(yùn)營(yíng)
經(jīng)過(guò)測(cè)試后,可以正式發(fā)布校園外賣(mài)小程序系統(tǒng)。為了吸引用戶和提高使用率,需要進(jìn)行有效的推廣和運(yùn)營(yíng)。可以通過(guò)線上和線下宣傳、推出優(yōu)惠活動(dòng)等方式來(lái)吸引用戶。同時(shí),要持續(xù)關(guān)注用戶反饋和需求變化,及時(shí)進(jìn)行系統(tǒng)更新和維護(hù)。
總結(jié):
本文從需求分析、技術(shù)選型、界面設(shè)計(jì)、數(shù)據(jù)庫(kù)設(shè)計(jì)、功能實(shí)現(xiàn)與測(cè)試等方面詳細(xì)解析了如何從零到一構(gòu)建一個(gè)高效的校園外賣(mài)小程序系統(tǒng)。通過(guò)合理的規(guī)劃和設(shè)計(jì),可以開(kāi)發(fā)出一款滿足用戶需求、性能優(yōu)良、安全可靠的外賣(mài)小程序,為校園生活帶來(lái)便利和便捷。
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。