談談軟件設計師眼裡的攜號轉網


談談軟件設計師眼裡的攜號轉網

“攜號轉網”的事情已經談了很久很久了,但看看我們四周,真正成功辦理了攜號轉網的人似乎不多,即便辦理成功,似乎也有這樣那樣的問題。

到底有什麼問題?似乎眾說紛紜。身處IT行業,凡事都應該擺事實講道理,能說得清楚。“攜號轉網”之所以難辦,似乎不只是運營商偷懶,還有技術上的難點。我們不妨從軟件設計的角度來看看攜號轉網這回事,應當會有許多新的發現。

攜號轉網的問題其實在世界上普遍存在,它有個專門的名稱叫Mobile Number Portability(MNP,移動號碼遷移),其中主要涉及三個概念:原運營商(donor)、新運營商(recipient)、轉網需求(number portability request,NPR)。對應的,它的技術方案也是現成的,主要有兩種技術方案。

第一種是美國、歐洲以及國際通行的方案,叫recipient-led。用戶在轉網時,先向新運營商提出申請,然後新運營商會聯繫原運營商,經過數據校驗之後完成資料轉移,將原號碼“調過來”。

第二種是英國和印度用的方案,叫donor-led。用戶在轉網時,先向原運營商提出申請,獲得對應代碼(英國叫PAC,porting authorisation code,印度叫UPC,unique porting code)之後轉交給新運營商,新運營商據此完成轉網。

第二種方案雖然看起來麻煩,但可以避免欺騙,因為原運營商有機會直接核實號碼所有者的身份。但是,這也會導致不公平競爭,因為原運營商可能會藉此機會故意拖延,想各種辦法挽留用戶。


談談軟件設計師眼裡的攜號轉網

兩種轉網方式

完成了運營商遷移,還只是遷移了移動用戶和運營商之間的關係,問題還沒完。要知道,移動通訊不只是發生在運營商和用戶之間,還發生在用戶和用戶之間。所以還要讓呼入的電話(其他用戶)知道,這個號碼已經遷移到了新的運營商,這樣呼入的電話、發來的短信才能正確抵達新運營商承載的用戶。這種抵達的專業叫法是routing,也就是“路由”。

路由的實現方式同樣不止一種。國際和歐洲通行的方案是集中式號碼庫CDB(Central Database)。簡單說,它就像一張大表,詳細記錄了每個號碼屬於哪個運營商。相應的,每次發生攜號轉網,都必須在CDB中新增對應的記錄。運營商會維護CDB的副本,在外呼電話或者外發短信時先查詢它,然後直接聯繫對應號碼的當前運營商。根據RFC3482,這個查詢叫ACQ(All Call Query)。合起來的整套方案就叫做ACQ/CDB routing,美國用的也是這套方案,只是美國的管理機構叫NPAC(Number Porting Administration Center)。

上面說的只是一種路由方式,英國的攜號轉網流程不同,路由方式同樣獨樹一幟。英國沒有采用ACQ/CDB,即便用戶已經攜號轉網,呼入的電話或發來的短信仍然會首先抵達原運營商,原運營商再將它轉發給新運營商,這就是“間接路由”(indirect routing),它類似Unix中的符號鏈接。

這種方案避免了對集中式號碼庫的依賴,將攜號轉網的信息分散給運營商各自維護,問題第一是增加了無謂傳輸,第二是已經轉網的用戶仍然無法擺脫對原運營商的依賴——所謂“打斷骨頭連著筋”,如果原運營商故障或者倒閉,已經轉網的用戶仍然會受影響,這樣用戶可能很難理解。

談談軟件設計師眼裡的攜號轉網

兩種呼入路由方式

現在來說國內移動運營方案。按照目前國內運營商公佈的攜號轉網流程,用戶攜號轉網時,必須先向當前運營商諮詢資格,並獲得授權碼,然後才能到新運營商處辦理轉入手續。據此可以猜測出,國內應當採用的是donor-led方案。不過,因為國內的手機號可能還有捆綁套餐,轉網時需要進行復雜的業務確認。通過詢問辦理過攜號轉網的夥伴得知,這個“複雜的業務確認”過程,恰恰是原運營商極力挽留用戶的過程。

好玩的是,雖然轉網是donor-led方案,而且國內之前似乎是沒有集中式數據庫的。這個事情也不難理解,很長時間裡似乎只有三大運營商,各運營商自成一體,工信部更多的是行使管理職能,而沒有基礎系統的建設和維護。

攜號轉網對任何一家運營商來說,似乎都是“得不償失”的。如果用戶要轉出去,相當於自己流失了用戶;如果用戶要轉進來(按照目前看到的報道,攜號轉網的用戶比例極低),又要額外增加系統建設,其實相當不划算。所以看來看去,還是工信部牽頭最合適,也最有可能。

按照我看到的技術文檔,現在我國正在採用類似ACQ/CDB的方案來完成轉網用戶的路由。具體來說,工信部會維護統一的中心攜號轉網數據庫(CNPDB),還有管理全國NP業務中心CSMS。聯通、電信、移動三家會維護各自的LNPDB和LSMS,數據與CNPDB保持一致。


談談軟件設計師眼裡的攜號轉網

中國聯通攜號系統架構。來源:張偉強,杜忠巖,李嵩泉,肖祿《移動號碼攜帶核心網部署方案探討》

用戶每次外呼時,運營商先查詢自己的LNPDB,判斷外呼號碼對應的運營商(“進行NP查詢),然後將外呼信號做對應路由。整套技術方案看起來沒有問題,但是之前並沒有集中式的數據庫,所以CNPDB的建設,以及整套流程的理順都需要時間。


談談軟件設計師眼裡的攜號轉網

運營商呼叫流程。來源:張偉強,杜忠巖,李嵩泉,肖祿《移動號碼攜帶核心網部署方案探討》

那麼目前,攜號轉網遇到的最大問題是什麼呢?我覺得是短信的路由問題。這一點也被許多攜號轉網者的經歷所證實——客服會告知,轉網之後許多短信可能收不到了。為什麼會這樣呢?

目前大量的短信服務提供商判斷用戶所屬的運營商時,完全是按照線下約定的規則。比如“130開頭是聯通的,135-139開頭是移動的,189開頭是電信的”。短信服務商在收到短信數據包之後,會首先按照號段把任務分開,對接到不同的運營商通道進行發送。對於攜號轉網的用戶,會被首先按照號碼分配到原有的運營商通道,而該運營商已經不負責該用戶了,短信就無法發送——當然反過來看,它也可以屏蔽大部分垃圾短信。

這個問題在充值時也存在。許多充值網站會根據用戶輸入的手機號來自動選擇運營商,它看起來方便,但攜號換網的用戶也會出現錯誤。此外,在一些需要判斷用戶歸屬運營商的場合,也會有同樣問題,如果你輸入的手機號“看起來”是聯通的,其實已經轉到了移動,而系統又是根據號段來判斷運營商的,就會報錯,無法繼續使用。

在軟件設計中我們經常會遇到這種“線下約定”的情況,它的好處是簡單易記,查詢不需要聯網,問題則是不夠靈活,如果後續要變化,很難及時通知到各方。

如果我們暫時忘記對運營商的評價,單純聚焦在攜號轉網的技術方案,就會發現這其實是開發中很常見的問題:資源遷移的要如何設計?

狹義的遷移很簡單,只是donor(原資源持有方)對recipient(新資源持有方)做數據傳輸而已。但是安全的系統必須要解決一個問題:如何判斷這種遷移真的可信的?

攜號轉網的recipient led方案中,recipient可以直接發起資源遷移請求,donor會信任這種請求,這看起來足夠簡單直接,但它有一個前提條件,運營商數量不多,成立門檻很高,追責也很方便。如果不具備這個前提條件,成立資源持有方很多,成立門檻也很低,那麼直接由recipient向donor申請數據遷移就會面臨安全問題。

這個問題要怎麼解決?我們可以想想如今網上流行的OAuth是怎麼做的?當recipient向donor發出申請時,多了一道“donor與用戶確認”的手續,因為有用戶的直接參與,就解決了“信任”的問題。

當然辦法不止一種,也可以借鑑donor led的方案,由用戶先向donor獲得許可及驗證碼,再完成遷移——實際上,域名遷移正是採用的這種方案,它解決了“眾多服務商”環境下建立信任的問題。

但是隻做到這一步,並不算資源遷移方案。稱職的工程師一定不能只看到眼前的這一點,還必須做完整的方案,保證遷移完成之後,所有相關的業務都保持平穩順利,不受影響。你看了上面的ACQ/CDB方案,大概會覺得“這不是顯然的事”嘛,但現實未必如此,這是有無數痛苦教訓的。

許多年前我開發過電商的物流系統。有一天業務的人問:“為了節省成本,同一個收件人的兩件貨品,是不是可以合併發貨?” 負責開發的程序員一聽:“這個沒問題呀,這個簡單,我馬上就可以做好”。沒兩天真的就開發完成了,揀貨、打包、出倉、掛號分配和錄入,確實都沒有問題,於是就順利上線了。結果上線兩天,前方就叫苦不迭,吃不消了。

一問才發現,這個工程師根本沒考慮異常情況。兩件貨可以拼單,那麼三件貨,四件貨呢?合併的最小單位到底是貨物還是訂單?如果用戶要發票,到底是開一張票還是兩張票?和供應商結算的時候,運費怎麼分攤?包裝的時候簡單合成一個包裝就可以嗎?如果是一個長杆和一個小方塊,弄個巨大的箱子可能反而不如分開包裝划算。最麻煩的是逆向流程——如果用戶要針對其中某件商品退款或者退貨,到底要如何操作?費用又如何計算?

這一下才知道,“合併發貨”真不是看上去那麼簡單,遠比想象的要麻煩得多。它也不是程序員或者小產品經理能搞定的,還必須加上物流、財務等等一大圈人。程序員想當然“沒問題”,造成了很多問題,給所有人都挖了個大坑……

回到數據遷移問題,我見過好些數據遷移方案,完全就是想當然,“我知道這裡數據遷走了”,拍拍腦袋就做了,拍拍屁股就遷了。設計者根本不考慮其他人,完全沒想過“其他人或業務知不知道數據遷走了”,也不關心其他人或其它業務後來會怎麼辦。

在“攜號轉網”的方案裡,要解決這個問題,就必須保持數據的同步更新。一種方案是提供集中式記錄(ACQ/CDB)方案,這種方案職責清晰,能保持通話路徑最短,但是對中心節點的穩定性、響應速度、複雜能力都提出了很高的要求。

另一種indirect routing在某種意義上可以稱為“分佈式”方案,即必須通過原服務商來中轉,這時候轉網信息碎片其實是由運營商各自維護的。這種方案不需要花大力氣建設中心節點,缺點則是職責不清晰,多了不必要的中轉,已遷移用戶仍然會受原運營商服務質量的影響。

中轉還會帶來其它問題:如果用戶多次遷移就會形成“中轉鏈條”,鏈條一長,不但影響效率,排查問題也異常麻煩。這還沒完,如果設計不當還可能形成環路……


談談軟件設計師眼裡的攜號轉網

拉鍊法可能拉出一個環來

最後我們不妨再深挖一點——所謂“攜號轉網”,真正跳出來看,核心就是一個函數問題。

函數最簡單的方式是 f(x) = y,這大家都知道。對攜號轉網來說,關鍵也是根據手機號查詢運營商,它可以看作 f(x) = y,其中 x 就是“具體的手機號”,y 就是“運營商”。只要掌握了這個信息,其它都好辦。

雖然我們都知道有 f(x) = y這個函數,但許多人也知道函數f的內部到底是怎麼做的,所以大家都自己實現了一遍:130~133號段是聯通,135~139號段是移動,189號段是電信……

同時我們也知道,軟件設計中提倡“暴露接口而不暴露實現”。為什麼呢?因為接口是關於抽象行為的定義,比如“輸入手機號,得到運營商”就是抽象行為,至於哪個手機號對到哪個運營商,規則可能不停變化,甚至有一些特例,但外部不必知道細節,只要放心調用這個接口既可以,外部原有業務流程照跑。如果暴露的是實現,你就需要在各處不停更新號段規則,如果遇上攜號轉網這種特例,維護難度更是上了幾層樓。

那麼“根據手機號查詢運營商”的功能,為什麼暴露的是實現而不是接口呢?這大概有歷史原因,缺乏頂層設計,一開始沒有權威公用接口,實現這種接口要承受巨大的負載,技術上有挑戰……

所以,早期許多技術問題,確實都是採用“線下共識”來解決的。比如早期不少電商的訂單號,上面就承載了很多信息,單純看訂單號就可以識別出下單日期、所屬倉庫、商品種類等等。

不過現在,隨著軟件的複雜度越來越高,隨時在線變得越來越普遍,這種“線下共識”已經越來越多地被替代了。不信你可以看看各大電商的訂單號,早年還可以從中看出下單日期、當日序號等等,但是現在,已經基本看不出任何編號規律了。但是手機號處理起來很麻煩,手機號綁定的線下規則很多,不只有判斷運營商,還有歸屬地……

總之,從攜號轉網這麼個“簡單直觀”的事情中我們可以看到,軟件設計要解決的問題原型往往簡單,但這些問題往往牽連眾多因素,而且沒有放之四海而皆準的方案,不同的方案各有利弊,必須根據具體環境來取捨和抉擇——許多時候,這恰恰是架構設計中最重要的因素,也是架構人才的核心競爭力。

P.S. 高春輝、胡姝琦對本文亦有貢獻,在此表示感謝。


分享到:


相關文章: