昨日回顧
昨天我們討論了服務間是否應該提供批量介面的問題,很多同學留言討論,非常好,一起討論一起進步。
其中,留言最多的一種觀點是說可以提供,但是要限制條數,比如每次最多傳1000條資料過來。
說句實話,我們的專案很多也是這麼做的。
不過我還是堅持我的觀點,最好就不要提供批量介面。
因為隨著資料量的不斷增大,勢必導致儲存架構升級。
我們以商品查詢為例,資料量變大,肯定是要上Redis的吧,以前批量介面可能直接一個資料庫in就解決了,現在你是先走快取還是不走呢?走的話要改程式碼,不走的話效能肯定不高。資料量再繼續增大,分庫分表了,批量介面怎麼處理?上Elasticsearch了,怎麼處理?
這裡,我們舉例是說的批量查詢,如果換成批量操作呢?每次儲存架構升級可能都要改這塊的程式碼,而且還有另外一個操蛋的問題,比如你們規定服務間呼叫超時最大是1秒鐘,超過1秒就有熔斷邏輯,那麼,你要不要單獨為這個批量介面配置超時?
所以,批量介面極其容易形成瓶頸,需要花費巨大的代價去維護這個程式碼,還是不提供比較好。
當然,如果你們的資料量在可以預見的未來都不會增長到那麼大,提供一個批量介面也不是不可以,視情況自行決定哈。(資料量都沒有,還不趕緊跑路?)
今日話題
好了,關於昨天的問題先嘮這麼多,今天,我們看另外一個問題:對前端提供的批量介面,後端如何快速響應?有沒有通用的解決方案呢?
場景
首先,我們分析一下這個場景。
這裡說的批量介面,肯定不是查詢哈,而是批量操作類的介面,比如批量匯入,批量發貨,批量刪除,批量流轉,批量修改某種狀態,等等,有很多,不過做2C系統的可能比較少見,一般2B的系統會有非常多這種批量的介面,往往他們也是系統中的頑固,需要投入很多精力不斷打磨不斷優化。
一般解決方案
好了,場景我們清楚了,那麼,怎麼解決這類難題呢?
一般地,我們提供一個批量介面,前端傳一堆id過來,或者資料過來,後端慢慢處理,處理完了再給前端返回,因為是2B的系統,使用者也願意等待。
但是,這裡其實有很多問題,最典型的就是超時問題,超時這個問題說簡單也簡單,說複雜也複雜,以我們的系統為例,我們部署到華為雲上面,可能會有這麼幾個超時的地方:
1、華為雲的防火牆有超時;
2、華為雲ELB有超時;
3、前端nginx有超時;
4、前端程式碼裡寫死了超時;
5、後端閘道器有超時;
6、後端服務有超時;
7、遠端呼叫有超時;
所以,你看,一個超時問題能把你折磨死,而且,這種問題非常難排查,當然,你躺完一次這個坑之後後面可能會好很多。(所以,我為什麼知道這麼多地方可能有問題呢?)
超時只是一個典型的問題,並不是全部,再說一個情形,以批量發貨為例,晚上,很多商家都喜歡批量發貨,比如一次1000條,這麼多商家的請求呢,一不小心就會出現很多打到同一臺機器上面去了,然後大家都在搞批量,都要申請大量的記憶體,都在搞記憶體,記憶體扛不住呀,然後就OOM了,這是典型的請求傾斜的問題,所以,怎麼設定你的負載均衡策略呢?目前,並沒有很好的解決方案。
通用解決方案
基於以上這些可能會出現的問題,我一直在思考,能不能提供一種通用解決方案呢?
其實是有的,但是,要改原型。
比如,批量發貨,本來狀態只有未發貨、已發貨、發貨失敗,能不能加一個“發貨中”呢?
別小看這個發貨中的威力,真的很強大。
後端接收到批量發貨這個請求,先檢查資料的正確性,然後把資料庫這些單據的狀態改成發貨中,接著把這些資料一個一個的丟到訊息佇列中,就可以返回了,前端查詢的時候就顯示發貨中,旁邊放一個重新整理按鈕。此時,使用者完全去幹別的事,比如去建商品,等會回來再看有沒有發貨完成或者發貨失敗的。
最後,有一組消費者不斷的從訊息佇列中消費資料,呼叫物流服務發貨等等。
經過這麼一折騰,本來前端要hang死幾分鐘的請求幾秒鐘就返回了,使用者體驗上去了,也不用去搞超時、請求傾斜等問題了,解放了生產力,可以多划水了。
而且,這還是一個可以無限橫向擴充套件的架構,隨著使用者量的不斷增大,理論上來說,只要堆機器就可以了。
好了,關於前端批量介面的處理就到這裡了。
寫在最後
最後,我想問,你們系統中是怎麼處理前端批量介面的呢?
歡迎留言討論。