App網(wǎng)絡(luò)實(shí)時(shí)數(shù)據(jù)模擬方案

背景

客戶端同學(xué)與服務(wù)端同學(xué)進(jìn)行聯(lián)調(diào)時(shí),總是會(huì)遇到各種各樣的問題蚕冬。其中免猾,以服務(wù)端的線下環(huán)境不穩(wěn)定是最為頭疼,聯(lián)調(diào)過程中囤热,一會(huì)應(yīng)用要重啟了猎提,一會(huì)某個(gè)依賴的公共線下環(huán)境掛了,或者為了讓服務(wù)端增加某個(gè)字段需要等半天才行旁蔼。

這些直接導(dǎo)致的結(jié)果就是锨苏,聯(lián)調(diào)開發(fā)效率非常低下!陷入了各種相互等的循環(huán)造成了各種碎片的垃圾時(shí)間棺聊。

于是就想想辦法讓客戶端同學(xué)開發(fā)的時(shí)候盡量少依賴伞租,甚至不依賴服務(wù)端的運(yùn)行環(huán)境,這樣就可以完美高效開發(fā)了限佩。

原始方案

最開始的做法也是相當(dāng)普通的做法葵诈,就是把服務(wù)端的內(nèi)容結(jié)果json字符串以json文件的形式加入app安裝包中,app啟動(dòng)后會(huì)根據(jù)app當(dāng)前的網(wǎng)絡(luò)情況判斷是獲取本地的json文件中的內(nèi)容還是直接獲取真實(shí)接口內(nèi)容祟同。

這種做法其實(shí)已經(jīng)很大程度的解決了最核心問題作喘,如果是這個(gè)方案我不需要專門寫一篇文章來介紹。

有人吐槽

產(chǎn)品的不斷迭代其實(shí)就是一直被吐槽晕城,被吐槽說明被需要泞坦,有人用,只是覺得不爽砖顷。

有了原始方案后贰锁,客戶端同學(xué)們已經(jīng)大量從服務(wù)端依賴中解救出來主之,陷入了新的煩惱,原因是只要需要對(duì)返回結(jié)果做一些哪怕是一點(diǎn)點(diǎn)改動(dòng)李根,都需要重新編譯壓包槽奕,這是很惱火的事情。

我自己開發(fā)過程中也深刻體會(huì)到了這一點(diǎn)房轿,并也開始思考粤攒,怎么樣不重新編譯壓包就可以修改mock數(shù)據(jù)。

思考了幾個(gè)方案:

  1. 代理:使用Charles囱持,通過map功能將請(qǐng)求返回結(jié)果通過map到的本地文本文件返回夯接,就可以完美實(shí)現(xiàn)實(shí)時(shí)修改mock結(jié)果。但需要查看電腦ip纷妆,還要手機(jī)設(shè)置代理盔几,還要配置ssl證書等一堆破事,作為程序員總覺的還是要操作很多步驟非常不爽掩幢。
  2. 遠(yuǎn)程修改安裝包中的mock文件內(nèi)容:通過本機(jī)命令行操作模擬器和真機(jī)逊拍,讀寫app安裝包中的mock文件內(nèi)容來達(dá)到目的,這條路探索了一陣子沒有找到落地的方案际邻。

新的思路

那天的一件事突然激發(fā)了靈感芯丧,想出了目前最完美的方案。那天具體目的是啥忘了世曾,總之想要在本機(jī)開啟一個(gè)http靜態(tài)服務(wù)器缨恒,設(shè)置到任意一個(gè)本地目錄為root,把里面的內(nèi)容可以被別人下載訪問轮听,看了下mac自帶的Apache骗露,需要設(shè)置虛擬機(jī)等配置,并不是很方便血巍,沒法達(dá)到我最簡(jiǎn)單最純粹的目的萧锉。

最終還是探索出了一行命令在任意目錄開啟http服務(wù)的途徑,后面會(huì)詳細(xì)介紹藻茂。

由此突然想到驹暑,如果我把靜態(tài)服務(wù)器root置為項(xiàng)目目錄下的mock文件夾,再將本機(jī)ip讓app感知到辨赐,那在運(yùn)行的時(shí)候就可以將請(qǐng)求轉(zhuǎn)發(fā)給ip指向的機(jī)器优俘,來做到實(shí)時(shí)mock數(shù)據(jù)的功能!

全新設(shè)計(jì)方案

由此設(shè)計(jì)出一套不需要任何輔助app支援掀序,不需要手機(jī)設(shè)置代理帆焕,而且可以不用重新編譯就可以實(shí)時(shí)修改mock數(shù)據(jù)的網(wǎng)絡(luò)數(shù)據(jù)模擬方案。

我本身是開發(fā)iOS所以下面實(shí)施方案都以iOS為例,安卓上思路可以參考叶雹。

1. 讓app知道哪臺(tái)機(jī)器開啟了mock數(shù)據(jù)的http服務(wù)

說的明白一點(diǎn)就是讓編譯的app知道當(dāng)前壓包的機(jī)器是什么ip财饥,這個(gè)思路就很多了,我也是采用了最普通的做法,通過在編譯過程中插入腳本,讀取本機(jī)ip蒲跨,寫入當(dāng)前app的Info.plist文件。

ifconfig | grep "inet " | grep -Fv 127.0.0.1 | awk '{print $2}'

將獲得ip寫入Info.plist

plist="${PROJECT_DIR}/${INFOPLIST_FILE}"
key="XM_MOCK_IP"
value="192.168.2.101"
/usr/libexec/Plistbuddy -c "Delete :${key}" "${plist}"
/usr/libexec/Plistbuddy -c "Add :${key} string ${value}" "${plist}"

2. 在編譯機(jī)上工程項(xiàng)目Mock目錄下啟動(dòng)http靜態(tài)服務(wù)

腳本cd到Mock目錄下谦炒,執(zhí)行下面命令就可以。

lsof -ti:7777 | xargs kill
SCREEN -d -m python -m SimpleHTTPServer 7777

第一行命令清理一下占用7777端口的應(yīng)用风喇。
第二行命令可以以當(dāng)前執(zhí)行命令的目錄為root開啟一個(gè)7777端口的靜態(tài)服務(wù)器宁改,這句話試了目前主流的macOS版本都支持這樣啟動(dòng)。

ps. 解釋下Mock目錄魂莫,Mock目錄我的設(shè)計(jì)是目錄中存放的是所有以apiname.json為文件名的請(qǐng)求結(jié)果字符串文本文件还蹲。
這個(gè)目錄存放在項(xiàng)目的Resource目錄下,直接以物理目錄在Xcode下可見耙考。
目的是為了在開發(fā)過程中方便隨時(shí)新增和修改內(nèi)容谜喊,不需要再切換其他編輯器來修改。

3. 讓app發(fā)起網(wǎng)絡(luò)請(qǐng)求時(shí)轉(zhuǎn)發(fā)到mock服務(wù)器

這里沒什么代碼可以提供琳骡,大體就是app上得有個(gè)開關(guān)锅论,可以隨時(shí)開關(guān)app的mock和非mock狀態(tài),根據(jù)這個(gè)標(biāo)志位楣号,網(wǎng)絡(luò)請(qǐng)求生成的請(qǐng)求URL會(huì)有所不同:

  • 在mock模式下
    生成的請(qǐng)求url會(huì)變成http://192.168.2.101:7777/xmmock/xxx.json
    網(wǎng)絡(luò)請(qǐng)求正常發(fā)出,或得到的內(nèi)容就是mock內(nèi)容怒坯,此時(shí)修改macOS里Xcode項(xiàng)目中mock文件夾下的json文件內(nèi)容就可以實(shí)時(shí)生效修改炫狱。
    這里的xmmock/xxx.json就是root目錄下的mock文件結(jié)構(gòu),可根據(jù)規(guī)則動(dòng)態(tài)生成剔猿。

  • 在非mock模式下
    正常生成url請(qǐng)求

4. 局部數(shù)據(jù)模擬

這里還可以做一下容錯(cuò)视译,大體是如果mock模式下,請(qǐng)求http://192.168.2.101:7777/xmmock/xxx.json后如果是非200归敬,說明這個(gè)mock文件不存在酷含,則繼續(xù)發(fā)送正常請(qǐng)求,以確保沒有在mock范圍內(nèi)的接口在app中還是可以正常訪問汪茧。

這樣就做到了app接口整體可用椅亚,只有在mock模式下,在mock范圍內(nèi)的接口會(huì)被mock舱污。

5. 清理尾巴

這里有點(diǎn)小尾巴呀舔,比如之前生成的在plist文件中加入了一個(gè)鍵值標(biāo)明當(dāng)前壓包的機(jī)器ip,這個(gè)鍵值在git中顯示是一個(gè)修改扩灯,這樣每個(gè)人修改這個(gè)代碼很容易沖突媚赖。

這個(gè)也很好辦霜瘪,在寫入編譯包后,編譯完成的環(huán)節(jié)再把這個(gè)鍵值從plist中自動(dòng)移除即可

plist="${PROJECT_DIR}/${INFOPLIST_FILE}"
/usr/libexec/Plistbuddy -c "Delete :XM_MOCK_IP" "${plist}"

全新的聯(lián)調(diào)流程

做到這樣以后惧磺,可以想象一下颖对,在項(xiàng)目進(jìn)入開發(fā)后,客戶端和服務(wù)端同學(xué)只要事先約定好接口各種情況數(shù)據(jù)返回的格式磨隘,客戶端就可以利用這套方案直接當(dāng)做服務(wù)端已經(jīng)提供接口那樣進(jìn)行開發(fā)缤底,當(dāng)客戶端通過本mock方案聯(lián)調(diào)自測(cè)各種情況通過后,再與服務(wù)端真實(shí)接口對(duì)接琳拭,成本可以說是非常的小训堆,完全消除的之前的相互等待的垃圾碎片時(shí)間。

目前我們團(tuán)隊(duì)的iOS組內(nèi)已經(jīng)使用這套方案成熟運(yùn)行了好幾個(gè)版本白嘁,開發(fā)效率提升明顯坑鱼。

附上完整腳本

將以下deploy腳本插入到"Build Phases"里盡可能前面的環(huán)節(jié),實(shí)際操作總我放在"Copy Bundle Resources"的前面絮缅。

#!/bin/sh
## 給plist賦值函數(shù)
setValueToPlist() {
    plist="${PROJECT_DIR}/${INFOPLIST_FILE}"
    
    key="$1"
    value="$2"
    /usr/libexec/Plistbuddy -c "Delete :${key}" "${plist}"
    /usr/libexec/Plistbuddy -c "Add :${key} string ${value}" "${plist}"
    echo "XMNetworkMock::在PLIST設(shè)定${key}值為${value}"
}

echo "XMNetworkMock::CONFIGURATION:${CONFIGURATION}"
echo "XMNetworkMock::PROJECT_DIR:${PROJECT_DIR}"

if [[ $CONFIGURATION == "Debug" ]]; then

## 獲取主機(jī)IP地址
ASB_HOST_IP=`ifconfig | grep "inet " | grep -Fv 127.0.0.1 | awk '{print $2}'`
setValueToPlist "XM_MOCK_IP" $ASB_HOST_IP
echo "XMNetworkMock::主機(jī)IP地址${ASB_HOST_IP}"

## 清理端口進(jìn)程
lsof -ti:7777 | xargs kill
echo "XMNetworkMock::端口占用清理完畢"

## 進(jìn)入目錄 
ASB_DIR_MOCK_API="${PROJECT_DIR}/Resources/xmmock"
mkdir -p $ASB_DIR_MOCK_API
echo "XMNetworkMock::打開目錄${ASB_MOCK_API}"

## 開啟網(wǎng)絡(luò)服務(wù)
cd $ASB_DIR_MOCK_API
SCREEN -d -m python -m SimpleHTTPServer 7777
echo "XMNetworkMock::啟動(dòng)網(wǎng)絡(luò)服務(wù) ${ASB_DIR_MOCK_API}:7777"

else
echo "XMNetworkMock::檢測(cè)到非開發(fā)模式鲁沥,已清理調(diào)試選項(xiàng)ASC_HOST_IP的值"
fi

以下clean腳本放置在"Build Phases"的最后一個(gè)流程即可

#!/bin/sh
deleteValue() {
plist="${PROJECT_DIR}/${INFOPLIST_FILE}"
key="$1"
/usr/libexec/Plistbuddy -c "Delete :${key}" "${plist}"
}
if [[ $CONFIGURATION == "Debug" ]]; then
deleteValue "XM_MOCK_IP"
fi

ps. 注意腳本中相關(guān)目錄。

原文 - App網(wǎng)絡(luò)實(shí)時(shí)數(shù)據(jù)模擬方案

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末耕魄,一起剝皮案震驚了整個(gè)濱河市画恰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌吸奴,老刑警劉巖允扇,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異则奥,居然都是意外死亡考润,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門读处,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糊治,“玉大人,你說我怎么就攤上這事罚舱【迹” “怎么了?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵管闷,是天一觀的道長(zhǎng)粥脚。 經(jīng)常有香客問我,道長(zhǎng)渐北,這世上最難降的妖魔是什么阿逃? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上恃锉,老公的妹妹穿的比我還像新娘搀菩。我一直安慰自己,他們只是感情好破托,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布肪跋。 她就那樣靜靜地躺著,像睡著了一般土砂。 火紅的嫁衣襯著肌膚如雪州既。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天萝映,我揣著相機(jī)與錄音吴叶,去河邊找鬼。 笑死序臂,一個(gè)胖子當(dāng)著我的面吹牛蚌卤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奥秆,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逊彭,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了构订?” 一聲冷哼從身側(cè)響起侮叮,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悼瘾,沒想到半個(gè)月后囊榜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡亥宿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年锦聊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片箩绍。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖尺上,靈堂內(nèi)的尸體忽然破棺而出材蛛,到底是詐尸還是另有隱情,我是刑警寧澤怎抛,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布卑吭,位于F島的核電站,受9級(jí)特大地震影響马绝,放射性物質(zhì)發(fā)生泄漏豆赏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望掷邦。 院中可真熱鬧白胀,春花似錦、人聲如沸抚岗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宣蔚。三九已至向抢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胚委,已是汗流浹背挟鸠。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留亩冬,地道東北人艘希。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像鉴未,于是被迫代替她去往敵國(guó)和親枢冤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理铜秆,服務(wù)發(fā)現(xiàn)淹真,斷路器,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,116評(píng)論 25 707
  • (冬季清晨连茧,天蒙蒙亮核蘸,霧氣仍在。一禪在門口張望著啸驯,穿著圓鼓鼓的客扎,很可愛) 師傅:一空,你在看什么? 一空:師傅罚斗,我...
    小七與咩閱讀 431評(píng)論 2 1
  • 1.微積分 導(dǎo)數(shù):一個(gè)函數(shù)在某一點(diǎn)的導(dǎo)數(shù)描述了這個(gè)函數(shù)在這一點(diǎn)附近的變化率徙鱼。$$f'(a) = \lim_{h \...
    Vinicer閱讀 877評(píng)論 0 2