四六級(jí)一鍵查詢項(xiàng)目復(fù)盤
1.背景:
官方將在2月27日公布四六級(jí)成績(jī)躏率。
2月24日凌晨時(shí)和歐陽討論四六級(jí)準(zhǔn)考證號(hào)查詢或進(jìn)一步發(fā)展為四六級(jí)一鍵查詢的可能性及難點(diǎn)逆巍。24日中午正式?jīng)Q定開始開展項(xiàng)目异旧,下午后端主要代碼完成,當(dāng)日晚后端完成準(zhǔn)考證號(hào)的緩存规伐。
25日下午四點(diǎn)左右前端發(fā)現(xiàn)已可查詢成績(jī)茵宪,項(xiàng)目組三人進(jìn)行了深入的交流最冰。25日晚前端完成后將產(chǎn)品鏈接發(fā)入大群,學(xué)長(zhǎng)學(xué)姐介入稀火,并立即決定當(dāng)晚發(fā)布產(chǎn)品暖哨。
26日九點(diǎn)左右成績(jī)又不可提前查詢。
27日九點(diǎn)成績(jī)正式公布凰狞,幾分鐘后端崩潰篇裁,直到一個(gè)半小時(shí)后才恢復(fù)沛慢。27日下午cet官方準(zhǔn)考證號(hào)查詢api不可用。
2.后端程序結(jié)構(gòu) && 目標(biāo)
共有三個(gè)api达布。
查詢準(zhǔn)考證號(hào)的api將先嘗試從緩存取出準(zhǔn)考證號(hào)团甲,如果沒有則用爬蟲獲取準(zhǔn)考證號(hào),然后存入數(shù)據(jù)庫往枣,獲取準(zhǔn)考證號(hào)后再嘗試用準(zhǔn)考證號(hào)和數(shù)據(jù)庫的身份證號(hào)從不需要驗(yàn)證碼的學(xué)信網(wǎng)獲取成績(jī)伐庭,如果成功則將獲取數(shù)據(jù)返回,失敗則返回準(zhǔn)考證號(hào)和姓名分冈。
另外兩個(gè)api一個(gè)是獲取中國(guó)教育考試網(wǎng)的驗(yàn)證碼圾另,另一個(gè)是以用戶輸入的驗(yàn)證碼去獲取成績(jī)。
程序設(shè)計(jì)時(shí)考慮到學(xué)信網(wǎng)非常容易崩雕沉,且到時(shí)候會(huì)有一定的改版集乔,便在學(xué)信網(wǎng)爬蟲部分使用了很多try,并且在服務(wù)器上根據(jù)實(shí)際情況修改請(qǐng)求的timeout坡椒,避免很多用戶長(zhǎng)時(shí)間的阻塞在這扰路,從而占用過多線程數(shù)導(dǎo)致服務(wù)不可用。
為保證可用性倔叼,準(zhǔn)備了兩個(gè)爬蟲汗唱,在查詢準(zhǔn)考證號(hào)的api里如果學(xué)信網(wǎng)不可用則只返回準(zhǔn)考證號(hào)和姓名,接著使用中國(guó)教育考試網(wǎng)的爬蟲來獲取成績(jī)丈攒。
為避免到時(shí)候cet官方準(zhǔn)考證號(hào)查詢接口不可用哩罪,提前緩存了所有大二大三的準(zhǔn)考證號(hào),使主體用戶在情況最糟糕的情況下都能使用核心功能(此時(shí)大一還沒考四六級(jí))巡验。
3.遇到的問題 && 當(dāng)時(shí)該怎么做更好
25日發(fā)現(xiàn)成績(jī)能提前查詢時(shí)际插,在服務(wù)器上直接將查詢準(zhǔn)考證號(hào)api里使用學(xué)信網(wǎng)爬蟲的代碼刪掉,避免在這里無意義的浪費(fèi)時(shí)間(當(dāng)時(shí)學(xué)信網(wǎng)還不可用)显设。
27日臨近九點(diǎn)時(shí)使用git checkout --恢復(fù)代碼框弛,并將學(xué)信網(wǎng)請(qǐng)求部分的timeout設(shè)為2秒,幾分鐘內(nèi)服務(wù)可用捕捂。隨后學(xué)信網(wǎng)開始以一定概率爆出驗(yàn)證碼瑟枫,服務(wù)開始不可用,但以后端代碼的設(shè)計(jì)邏輯來講指攒,服務(wù)并不會(huì)因此崩潰力奋,所以當(dāng)時(shí)的猜測(cè)是因?yàn)橹袊?guó)教育考試網(wǎng)太過擁擠或我們服務(wù)器的ip已被ban掉,進(jìn)行curl和wget后確認(rèn)沒有被ban幽七,丟包率也確實(shí)非常高景殷,再加上后端的監(jiān)控系統(tǒng)沒有報(bào)與timeout相關(guān)以外的錯(cuò)誤,便沒有懷疑是代碼本身有問題,而將目光放在了丟包上猿挚。于是當(dāng)時(shí)直接在服務(wù)器上咐旧,提高中國(guó)教育考試網(wǎng)的爬蟲的請(qǐng)求數(shù),如果單次調(diào)用爬蟲绩蜻,發(fā)出5次網(wǎng)絡(luò)請(qǐng)求都還沒有成功才會(huì)返回铣墨。但隨后發(fā)現(xiàn)服務(wù)依然不可用,便開始感到焦慮办绝。本地進(jìn)行了一些測(cè)試后發(fā)現(xiàn)這部分代碼效果提升不明顯伊约,便git checkout --恢復(fù)了這部分代碼。
開始將目光放到學(xué)信網(wǎng)上孕蝉,研究了當(dāng)時(shí)學(xué)信網(wǎng)頁面的邏輯屡律,再次確認(rèn)從代碼上講爬蟲無論如何都會(huì)返回布爾值為false的值或成績(jī)。此時(shí)離公布成績(jī)的時(shí)間已經(jīng)過去了快一個(gè)半小時(shí)降淮,心態(tài)已經(jīng)非常焦急超埋,便抱著試試的心態(tài)又將使用學(xué)信網(wǎng)爬蟲的幾行代碼刪掉,隨后發(fā)現(xiàn)服務(wù)可用佳鳖。
當(dāng)時(shí)非常不解為什么那幾行代碼會(huì)出問題霍殴,本地跑了后端部分后,用postman測(cè)試并沒有出現(xiàn)問題系吩,學(xué)信網(wǎng)的爬蟲也確實(shí)返回了一個(gè)布爾值為false的值来庭,而docker+virtualenv一般也不會(huì)因?yàn)榄h(huán)境問題使服務(wù)不可用。當(dāng)時(shí)也沒有考慮使用log在生產(chǎn)環(huán)境調(diào)試穿挨,不過現(xiàn)在覺得應(yīng)該做一下看看到底發(fā)生了什么月弛。
現(xiàn)在看來當(dāng)時(shí)有很明顯的證據(jù)證明問題出在哪——準(zhǔn)考證號(hào)沒有返回,那就說明查詢準(zhǔn)考證號(hào)的api出了問題絮蒿,而自己的準(zhǔn)考證號(hào)又已經(jīng)緩存,檢查過redis后便只可能是學(xué)信網(wǎng)的爬蟲部分出了問題叁鉴。
而這部分當(dāng)初設(shè)計(jì)時(shí)是覺得無論如何都要返回的土涝,所以便在覺得可能出問題的地方使用了try』夏梗可如果要保證服務(wù)的可用性但壮,又不確定爬蟲到時(shí)會(huì)出如何的錯(cuò)誤,建議在調(diào)用爬蟲的外面加一層try常侣,這樣即使這個(gè)爬蟲出了你完全沒有預(yù)想到的錯(cuò)誤蜡饵,也不會(huì)影響服務(wù)的可用性。
4.總結(jié)
1.出問題時(shí)首先明確哪出了問題胳施,像這次就很明顯是查詢準(zhǔn)號(hào)api不可用溯祸,首先應(yīng)看到并修復(fù)它,再考慮之后別的api丟包的問題。
2.在出成績(jī)的時(shí)候爬蟲普遍都會(huì)阻塞很久甚至失敗焦辅,這時(shí)候應(yīng)該首先保證服務(wù)的可用性博杖,比起長(zhǎng)時(shí)間的網(wǎng)絡(luò)請(qǐng)求,try的性能犧牲并不大筷登,而如果不是百分百確定哪會(huì)出問題剃根,則可以在調(diào)用爬蟲時(shí)套層try。