移動端主動推送訊息原理

來源:互聯網
上載者:User

標籤:dev   code   產品   ber   handler   UI   知乎   tool   evo   

轉:https://www.zhihu.com/question/19628406/answer/77205019

一、服務端主動推送訊息到用戶端過程謝澤帆   李琰
連結:https://www.zhihu.com/question/24938934/answer/85359794
來源:知乎
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。

服務端主動推送到用戶端是怎麼一個過程


目前服務端給用戶端推送,普遍做法是用戶端與服務端維持一個長串連,用戶端定時向服務端發送心跳以維持這個長串連。當有新訊息過來的時候,服務端查出該訊息對應的TCP Channel的ID並找到對應的通道進行訊息下發。


這隻是最基本的通訊模型,在此之上,有衍生出針對訊息的發布/訂閱模型,用戶端可以訂閱某一個Topic,服務端根據Topic找到對應的Channel進行批量的訊息下發。所有的用戶端隱式的訂閱的all這個opic,所以『類似中國移動給全網訊號內所有手機發訊息的模式』亦可以理解『廣播訊息』,即給all這個Topic發訊息。


在此基礎上,又要幾個開源的協議來幫你定義這個事情,比較有名的如MQTT協議(剛好這幾天我看到MQTT協議的中文翻譯,分享給大家),Github上搜尋MQTT可以找到對應的開源的協議實現項目,有興趣可以自行搜尋。


現在的APP是如何使用訊息推送的


實際上,主流的移動平台都已經有系統級的推送產品,Android上有GCM,iOS上有APNS,WinPhone有MPNS。但因為某些你懂的原因,GCM在國內處於不可用狀態,所以國內的行動裝置 App採用另外一種做法---在後台運行一個Service,維持應用於服務端的TCP長串連,以達到即時訊息送達的效果。


但是在移動端如何穩定的維持長串連是一件非常複雜的事情,前面說了,用戶端通過定時發送心跳訊號(Heartbeat)以維持與服務端的長串連,但是,如果心跳的頻率太頻繁,行動裝置耗電增加,心跳間隔太久又可能使得串連被斷開。並且普遍認為行動裝置處於一個多變的網路環境中,WIFI,2G,4G切換,基站切換都會引起網路變動,在不同網路環境下的心跳頻率,與網路變動的重連動作,都需要大量的資料統計分析總結出來。


這僅僅是用戶端的難題,在如今行動裝置 App動輒成百上千的使用者量的情況下,如何維護如此多的長串連,如果應對大規模的訊息下發以及後續針對下發訊息的各種統計動作都是技術痛點。


再者,現在應用一般都是全平台的,發送一條訊息,應該同時發送給Android,iOS, WinPhone,Android端走自建的TCP長串連通道,iOS與WinPhone走自家的系統推送通道。那麼意味著你服務端要維護這三套推送系統。


顯然對於小團隊,要獨自建立一套訊息推送系統的難度非常大,所以市場上湧現出很多優秀的推送產品,幫開發人員彙總這些推送方式,並提供統一的推送介面。國外如 Urban Airship, Parse等, 國內有JPush,百度雲推送,信鴿,LeanCloud等。(比較遺憾的是,非常優秀的Parse已經被Facebook宣布停止開發,並將於1年後關閉)


現在除了體量非常大的公司自建推送系統外,一般普通公司都是使用第三方推送服務,以上所有的第三方推送服務,基礎功能都是免費的,如果有條件的話,建議可以整合多家服務,A/B測試對比下推送效果,本人從事與以上某推送公司,在此就不評價各家產品好壞了。

二、伺服器端主動推送訊息到用戶端原理

現在手機主流的幾個平台都有自家提供Push的功能,讓應用開發人員能夠很方便地把Push能力整合到應用中。

Android 上有 GCM (Google Cloud Messaging)
iOS 上有 APNs(Apple Push Notification service)
Windows Phone 上有 MPNs(Microsoft Push Notification service)。

但是由於Windows Phone的市場佔比不高,所以一般也就沒有人會專門做wp系統的推送。至於Android的GCM在國內基本上是停用。原因主要有以下兩點:
一、國內大部分Android手機都不帶Google服務,也就用不了GCM,這是主要的問題。
二、在國內Google的服務一般都不太穩定,原因你懂的。
所以現在在做訊息推送的時候Android平台採用伺服器與裝置直接拉一條長串連的方式實現功能,而IOS平台則採用蘋果自己的APNs服務。在分別說這兩個平台推送原理的時候,先回答一下題主關於伺服器如何先找到裝置、再找到app的問題。每一個裝置都有一個自己的裝置號,而裝置中的app又都有一個唯一的包名。所以伺服器只需要找到裝置號與包名就可以定位到某個裝置的某個應用,而這裝置號與包名會一起構成一個標識符,叫做device_token,因此問題就簡化為把device_token與訊息內容等資訊交給伺服器,伺服器把內容發到唯一的device_token上。這就好像你在上海要通過順豐寄送一個快件兒給某某小區的某某房間,那麼快件兒首先會郵遞到順豐公司在北京的總網站,之後再根據小區的地址投遞/路由到某某房間,這樣一個寄件過程就算完成了。在這裡,你要寄送的快件兒就是你要發的“訊息”,送達房間相當於最終“接收訊息的App”,順豐公司在北京的總網站相當於這裡提到的“裝置”,送達房間的房間號就相當於這個環節裡面提到的“包名”。

接下來分別簡單說一下這兩個平台的推送實現原理。
首先是IOS平台,IOS的推送是通過蘋果自己的APNs服務進行的,使用者需要將device_token以及訊息內容等推送資訊交給APNs伺服器,剩下的均由蘋果自己來完成。但是如果提供的device_token是失效的(app被卸載、系統版本升級導致device_token變化等情況)那麼推送過程就會被中斷,頻繁的斷線重連甚至會被APNs認為是一直DoS攻擊。詳情可以參考為什麼蘋果的推送,兩次推送之間間隔比較久的話,第二次推送會很慢? - 沙漠的回答Android平台推送原理:Android平台在不使用GCM的情況下就需要將自己的伺服器或是第三方推送服務提供者的伺服器與裝置建立一條長串連,通過長串連進行推送。但是不建議自己設定伺服器實現推送功能,一是因為成本太高(開發成本、維護成本),自己搭建的伺服器無論是穩定性還是速度上都比不了第三方推送服務提供者的效果。另一個是因為自己的資料量較小,使用第三方推送服務提供者可以用他們的維度進行推送,實現精準推送。友盟推送就是做的比較好的,可以根據使用者分群、地區、語言等多維度進行推送,最大程度減少對於使用者的幹擾,僅把訊息推送給相關使用者。友盟推送的優勢是什嗎? - 李琰的回答
是Android平台訊息推送的簡單。
<img src="https://pic1.zhimg.com/9f93b6c802028443177b31ade2ddd550_b.png" data-rawwidth="731" data-rawheight="578" class="origin_image zh-lightbox-thumb" width="731" data-original="https://pic1.zhimg.com/9f93b6c802028443177b31ade2ddd550_r.png">
開發人員通過第三方推送服務提供者將資訊直接下發給需要的裝置,第三方推送服務提供者與裝置建立一條長串連通道,並且將訊息路由到APP中(圖中的裝置1與裝置2),對於像裝置3這種無網路連接或是沒有成功建立長串連通道的裝置,會在裝置3連網且推送訊息沒有到期的情況下自動收到由第三方推送服務提供者推送過來的訊息,保證訊息不會丟失。iOS的push推送原理:iOS應用的推送大部分情況下都要依賴蘋果生態提供的APNs(Apple Push Notification Service)服務。
下邊用兩幅圖來簡要說明其推送原理

 


首先作為裝置標識的device-token是由APNs頒發的,App開發人員或者第三方推送平台(圖中的Provider)做的工作是收集這個device-token,APNs的推送是要求基於APNs頒發的device-token來推送的。只有正確的device-token會被APNs接受,如果是一個錯誤的、或者無效的device-token(比如App已經卸載了),APNs就不會接受。

接著開發人員使用第三方推送平台(圖中的Provider)在將推送內容與範圍選定之後進行推送,第三方推送平台將資訊提交給APNs,剩下的操作全部都由APNs來進行完成,整個過程第三方推送平台就不能控制了。

對於友盟推送有更多想要瞭解的東西可以關注友盟推送的官網友盟訊息推送|app推送以及論壇http://bbs.umeng.com/forum-push-1.htmliOS實用技巧 - 私人推送實現方法

在開發企業app的時候,有的時候基於安全性的考慮,不允許裝置串連外網。這就出現了一個問題,就是iOS的推送功能沒法工作了,因為iOS的推送功能是固化在系統裡,必須串連蘋果的APNS伺服器才能工作的,為了能讓這類只能工作在內網裡的app也能擁有推送功能,就需要我們自己來實現推送功能了。

自主推送的實現方法是利用iOS的voip類app可以駐留在背景功能。這類app,系統在裝置開機時即被啟動,app可以將自己的一個socket委託給系統,在socket有資料到達時,系統就會喚醒app,給它一段很短的cpu時間來處理資料,再加上UIApplication的keepAliveTimeout handler(最小10分鐘間隔一次),可以每隔一段時間就重建立立一次串連,來達到保持socket長串連的需求。

註:由於voip類app可以使app常駐在後台並維持socket長串連,因此蘋果對這類應用有及其嚴格的審查,所有不是真正的voip的app都會被拒絕!切記!

1.設定應用為voip應用

開啟<app>-info.plist檔案,加入如下的key

Required background modes,追加App provides Voice over IP services

 

2.將socket設定成非同步模式,並將socket設定成VOIP類的,以便系統能夠託管它。

CFStreamCreatePairWithSocket(NULL, (CFSocketNativeHandle)(mosq->sock), &readStream, NULL);//保證不關閉原來的socketCFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanFalse);//設定成voip socketCFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);

 

 

3.安裝keepAliveTimeout handler,讓系統每隔一段時間重建立立串連

    UIApplication *application = [UIApplication sharedApplication];    [application setKeepAliveTimeout:600 handler:^{        [self reconnect];    }];

 

我參考了jmsnil的MQTTExample工程,這是一個使用mqtt的例子,我把它做了一些修改,以便能在後台運行接收推送。

原工程地址:

https://github.com/jmesnil/MQTTExample

我修改的樣本工程地址:

https://github.com/Guou/Demo-mqtt-push

開啟終端,輸入下面的命令即可獲得通知

curl -X PUT --data-binary "1"  http://eclipse.ttbridge.com/%2FMQTTExample%2Ftestcnpush

 

該例子只可以工作在真機上,如果您是iOS7以下,請把application:didFinishLaunchingWithOptions:中本地通知許可權請求的代碼刪掉。

--------------------

我感覺全部內網環境做推送訊息的想法還是算了吧,太麻煩,直接走簡訊和郵件通知得了

(轉)移動端主動推送訊息原理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.