從客戶端的角度設(shè)計(jì)后端的接口

前言

雖然一個(gè)api接口的業(yè)務(wù),數(shù)據(jù)邏輯是后端提供的,但真正使用這個(gè)接口的是客戶端,一個(gè)前端功能的實(shí)現(xiàn)流程與邏輯,客戶端算是接口的需求方。所以建議在前期接口設(shè)計(jì)和評(píng)審時(shí),客戶端的應(yīng)該更多的思考和參與,什么時(shí)機(jī)調(diào)什么接口?每個(gè)接口需要哪些字段?數(shù)據(jù)含義怎么給?只有這些都考慮清楚,且達(dá)成一致并產(chǎn)出接口文檔后,當(dāng)項(xiàng)目真正啟動(dòng)時(shí),根據(jù)接口協(xié)議進(jìn)行開(kāi)發(fā),才能盡量避免各種不確定因素對(duì)項(xiàng)目整體進(jìn)度的影響。

API設(shè)計(jì)核心原則:

  1. 遵循Web標(biāo)準(zhǔn)
  2. 對(duì)開(kāi)發(fā)者友好
  3. 在使用上應(yīng)該保持簡(jiǎn)單、直觀和一致性,不僅僅是容易使用,而應(yīng)該讓使用者感到愉悅
  4. 有效率的

接口設(shè)計(jì)規(guī)范

基本規(guī)范

1.通用請(qǐng)求參數(shù)

每個(gè)請(qǐng)求都要攜帶的參數(shù),用于描述每個(gè)請(qǐng)求的基本信息,后端可以通過(guò)這些字段進(jìn)行接口統(tǒng)計(jì),或APP終端設(shè)備的統(tǒng)計(jì),可以放在請(qǐng)求頭部header中。

 const header = {
   version: '1.0.0',                           // 客戶端版本version
   token: '6aab9eb8f32e566dfa41cbd48f53c80d',  // 登陸成功后,登陸令牌token
   platform:'android',                         // android/ios
   model:'Note3',                              // 機(jī)型信息
   appid:''                                    // app唯一標(biāo)識(shí),服務(wù)可能提供多個(gè)app應(yīng)用
 }

總是給你的API加上版本化。API版本化能夠讓你的API迭代地更快,防止老的請(qǐng)求訪問(wèn)你的API最新版。這樣能夠讓你在進(jìn)行API重大升級(jí)時(shí),能夠持續(xù)對(duì)老版本API進(jìn)行一段時(shí)間的支持。

有很多的人在討論,API的版本化,應(yīng)該體現(xiàn)在URL上,還是在請(qǐng)求Header里。理論上講,應(yīng)該放在Header里。

API被發(fā)布出來(lái),不會(huì)永遠(yuǎn)不變。變化是不可避免的。重要的是,我們?cè)趺慈ス芾磉@種變化。

2.請(qǐng)求路由鏈接

命名規(guī)范的基礎(chǔ)上盡量保持良好的可讀性,見(jiàn)名知意。

接口請(qǐng)求路由參考restful規(guī)范。

REST的核心思想是,把API按照邏輯上的資源來(lái)進(jìn)行區(qū)分。這些資源被HTTP的不同方法(GET, POST, PUT, PATCH, DELETE)進(jìn)行請(qǐng)求,每個(gè)方法代表不同的含義。(GET=查找,POST=增加,PUT=修改,DELETE=刪除)

REST的偉大之處在于,采用了既有的HTTP methods,在一個(gè)單獨(dú)的鏈接下,實(shí)現(xiàn)了多樣的功能操作。你不需要遵循任何的命名規(guī)范,僅僅需要一個(gè)干凈和整潔的URL結(jié)構(gòu)。

3.響應(yīng)數(shù)據(jù)

數(shù)據(jù)返回格式:

  {
    code:200,       // 200:成功;非200:失敗
    msg:'成功',     // 請(qǐng)求失敗時(shí)的message
    Desc: '',      // 返回描述字符
    data: {         // 數(shù)據(jù)實(shí)體
      name:'張三',
      age:20
    }
  }  

array類型數(shù)據(jù):

  {
    code: 200,       // 200:成功;非200:失敗
    msg:'成功',     // 請(qǐng)求失敗時(shí)的message
    Desc: '',      // 返回描述字符
    data: {         // 數(shù)據(jù)實(shí)體
      list:[{
        name:'張三',
    age:20
      }]
     }
  }  

判斷code==200的情況下繼續(xù)解析datacode!=200時(shí),根據(jù)業(yè)務(wù)提示文案放在Desc字段,客戶端直接顯示就可以了。

array類型的數(shù)據(jù),即使只有1個(gè)list字段,也要保證data下是個(gè)完整的object結(jié)構(gòu),這樣就可以統(tǒng)一將data層級(jí)下的數(shù)據(jù)當(dāng)對(duì)象解析。

4.命名規(guī)范

統(tǒng)一命名:一般采用小駝峰法,無(wú)絕對(duì)標(biāo)準(zhǔn)。

避免冗余字段:每次在新增接口字段時(shí),注意是否已經(jīng)存在同一個(gè)含義的字段,保持命名一致。

注釋清晰(重要):每個(gè)接口/字段都需要有詳細(xì)的描述信息,很多時(shí)候接口體現(xiàn)業(yè)務(wù)邏輯,是團(tuán)隊(duì)中很重要的文檔沉淀,同時(shí),詳細(xì)的接口文檔,可以幫助新人快速熟悉業(yè)務(wù)。

5.返回字段類型討論統(tǒng)一

需要和兩端商討關(guān)于數(shù)據(jù)類型的返回,特別式特殊的類型,比如布爾類型等,不同語(yǔ)言表示方法不同

6.上傳/下載接口,根據(jù)md5校驗(yàn)數(shù)據(jù)完整性

上傳,下載文件/圖片時(shí),除了file本身,還要攜帶該filemd5,在傳輸過(guò)程中可能丟失部分?jǐn)?shù)據(jù),導(dǎo)致文件損毀,所以需要通過(guò)md5值進(jìn)行完整性校驗(yàn)。
上傳成功后將圖片url返回

7.避免浮點(diǎn)型計(jì)算

浮點(diǎn)型計(jì)算可能導(dǎo)致精度丟失,為了避免,可以縮小單位進(jìn)行存儲(chǔ)。
例:1.5元,后端會(huì)以150分存到數(shù)據(jù)庫(kù),1.5km會(huì)存成1500m。
同理,如果一個(gè)類似距離的字段,如果是展示用,則直接返回"1.5km",如果涉及到邏輯判斷與計(jì)算(如:>1000m,執(zhí)行邏輯A,>1500m,執(zhí)行邏輯B),可以返回"1500,單位(m)",至少比傳1.5來(lái)的方便。當(dāng)然如果要計(jì)算浮點(diǎn)型也是可以的,需要用到BigDecimal,這么設(shè)計(jì)只是為了減少出錯(cuò)的可能性。

8.json數(shù)據(jù)保持良好結(jié)構(gòu)

  {
    userId: 1
    userName: '灑哥',
    userAvatar: 'http://xxx',
    orderId: 2,
    orderType: 1
    addressId: 5,
    addressDtl: '蘿崗'
  }

json的3類信息user,order,address,全部堆在一起,字段多了以后,對(duì)于接口信息的讀取很不直觀;
客戶端在定義model的時(shí)候,會(huì)將全部字段定義在一個(gè)model中,如果其他地方也有用到addressId,Name,Detail等字段信息,則需要重新定義addressmodel,無(wú)法實(shí)現(xiàn)model的復(fù)用。

  {
      user:{
        id: 1
        name: '灑哥',
        avatar: 'http://xxx'
      }
      order:{
        id: 2
        type: 1
      }
      address:{
        id: 5,
        detail: '蘿崗'
      }        
  }

優(yōu)化后user,order,address字段在各自的對(duì)象內(nèi),一眼就可以看出這個(gè)接口有哪些類型的數(shù)據(jù)。還有點(diǎn)要注意,如果放在同一級(jí)別,id字段就需要用userId,orderId,addressId區(qū)分開(kāi),而現(xiàn)在根據(jù)不同結(jié)構(gòu)體區(qū)分字段類型后,直接使用id就可以了。

撰寫接口文檔

好的文檔,和好的接口同樣重要。接口文檔需要被很容易地找到和訪問(wèn)。大部分開(kāi)發(fā)者會(huì)在進(jìn)行接口開(kāi)發(fā)之前,檢查并查看接口文檔。如果這些接口文檔是寫在PDF文檔里,或者需要登錄才能查看,那將不僅僅是難于查找,還不利于搜索。

接口文檔應(yīng)該描述完整,并附上具體的例子。最好是,這些例子應(yīng)該是真實(shí)可以訪問(wèn)的。

一旦你發(fā)布了一個(gè)API,那意味著,在沒(méi)有通知調(diào)用者的情況下,你有責(zé)任不去破壞該接口的已有功能。如果你在今后修改該接口,需要及時(shí)更新接口文檔,并且在發(fā)布接口的更新之前,及時(shí)通知你的接口調(diào)用者。

瘦客戶端

眾所周知,客戶端任何的修改都是需要發(fā)版的,特別是iOS需要走AppStore的審核流程。為了修一個(gè)bug,僅僅改幾行代碼,而重新走一輪發(fā)版流程,并且舊版本得bug一直都在,很是勞民傷財(cái)?shù)摹K栽诮涌谠O(shè)計(jì)的時(shí)候,也需要適當(dāng)考慮這點(diǎn),將業(yè)務(wù)重心交給服務(wù)端,客戶端保持邏輯簡(jiǎn)單。服務(wù)端可以隨時(shí)發(fā)版,客戶端一個(gè)版本卻只能發(fā)一次,有些團(tuán)隊(duì)一開(kāi)始并沒(méi)意識(shí)到這點(diǎn),總覺(jué)后端就是重度業(yè)務(wù)邏輯的所在,管那么多前端的展示,字符串拼接邏輯干嘛,可當(dāng)真正有問(wèn)題(bug或需求變更)需要發(fā)版的時(shí)候,客戶端需要重新一輪新的版本得發(fā)版。

客戶端盡量只負(fù)責(zé)展示邏輯,不處理業(yè)務(wù)邏輯

例如:客戶端有個(gè)TextView,服務(wù)端只給個(gè)status字段,status=1時(shí),展示文案1;status=2時(shí),展示文案2;這樣設(shè)計(jì)的缺點(diǎn)是,如果以后要修改status=3時(shí),展示文案1,那么這個(gè)status判斷邏輯時(shí)寫死在客戶端,就沒(méi)辦法支持這種修改,且這種設(shè)計(jì)限定死了TextView只能展示2種文案。推薦方案是后端直接將TextView需要展示的文案下發(fā),這樣不管是status的判斷,還是文案的展示,后期都是可變的。

客戶端不處理金額的計(jì)算

例如:外賣APP,用戶在下單的時(shí)候,需要選擇收貨地址,支付類型,優(yōu)惠券等,任何一個(gè)選項(xiàng)的修改,都可能影響用戶最后需要支付的金額。所以這里比較常見(jiàn)的接口設(shè)計(jì)是在每次選擇完回到訂單支付頁(yè)面后,再發(fā)送一次請(qǐng)求,后端根據(jù)當(dāng)前選項(xiàng)重新計(jì)算金額。金額永遠(yuǎn)是一款產(chǎn)品最重要,最敏感的信息,如果交由客戶端計(jì)算,萬(wàn)一出錯(cuò),即使少1分,都是毀滅性的,所以,關(guān)于金額,展示就好。

客戶端少處理請(qǐng)求參數(shù)的校驗(yàn)與約束提示

例如:修改密碼功能,密碼規(guī)則"6-12字母,數(shù)字,下劃線",有3種做法:

  1. 在發(fā)送請(qǐng)求前,客戶端校驗(yàn)密碼規(guī)則,如果不符合,則不發(fā)送請(qǐng)求。
    優(yōu)點(diǎn):規(guī)則不滿足時(shí),可以減少不必要的請(qǐng)求。
    缺點(diǎn):客戶端寫死校驗(yàn)邏輯,密碼規(guī)則變化時(shí),客戶端需要發(fā)版。

  2. 客戶端只判斷null,和最短位數(shù)限制,其他校驗(yàn)規(guī)則交由后端處理。
    優(yōu)點(diǎn):靈活性最好。
    缺點(diǎn):后端壓力大,校驗(yàn)請(qǐng)求多。

  3. 后端在通用配置的接口返回正則表達(dá)式,客戶端獲取后進(jìn)行正則校驗(yàn)。
    優(yōu)點(diǎn):具有一定靈活性。
    缺點(diǎn):開(kāi)發(fā),調(diào)試成本較高。(推薦:即使出問(wèn)題,也可以清除配置,回退到第2個(gè)方案)

擴(kuò)展性

接口的設(shè)計(jì)要具有一定的擴(kuò)展性,考慮到后續(xù)版本變化,對(duì)于接口,字段的影響及變化。

接到需求之后,即使和策劃或者產(chǎn)品經(jīng)理確認(rèn)了,他們說(shuō)以后一定不會(huì)改變,但是千萬(wàn)別相信他們(程序員生存法則: 1.不要寫死 2.不要相信策劃)。我們的原則是:變與不變都能支持。

方案1:客戶端在寫頁(yè)面的時(shí)候?qū)⒆髠?cè)的"姓名","性別","年齡"寫死,右側(cè)的具體數(shù)據(jù)從json解析獲得

{
    "name": "張三",
    "sex": "男",
    "age": "20歲",
    "nickName": "小張"
}

方案2(推薦):將左側(cè)的title和右側(cè)的value,以list(key-value)的數(shù)據(jù)形式進(jìn)行下發(fā),優(yōu)點(diǎn):左,右側(cè)文案靈活配置,后期如果需要擴(kuò)展,新增或刪除一個(gè)條目,都可以通過(guò)后端控制。不過(guò)采用這種形式,也需要考慮實(shí)際場(chǎng)景,對(duì)于變化不那么頻繁,數(shù)據(jù)item較少,較固定的情況下其實(shí)沒(méi)有必要設(shè)計(jì)的太靈活,只會(huì)增加開(kāi)發(fā)成本。

{
    "userInfos":[
    {
        "key":"姓名",
        "value":"張三"
    },{
        "key":"性別",
        "value":"男"
    },{
        "key":"年齡",
        "value":"20歲"
    },{
        "key":"昵稱",
        "value":"小張"
    }]
}

3.用flag替換boolean:一般情況下,一款APP都會(huì)有config接口,用于獲取一些常量文案,通用配置等信息,會(huì)有很多類似開(kāi)關(guān)的字段,如:isAdminisPulsv等等。

{
    isAdmin:1,// 是否是管理員
    isPulsv:1,// 是否是大v用戶
}

優(yōu)化方案:通過(guò)二進(jìn)制第1位表示isAdmin,二進(jìn)制第2位表示isPulsv。如果有其他新增狀態(tài),不需要新增字段,就需要改變返回的數(shù)據(jù)即可。

flag:3 // 二進(jìn)制:11,表示2個(gè)狀態(tài)都為true

安全性

響應(yīng)數(shù)據(jù)中包含用戶隱私的字段數(shù)據(jù),需要加*號(hào)。如:手機(jī)號(hào),身份證,用戶郵箱,支付賬號(hào),郵寄地址等。

請(qǐng)求參數(shù)中包含用戶隱私的字段參數(shù),如:登陸接口的密碼字段,需要進(jìn)行加密傳輸,避免被代理捕捉請(qǐng)求后獲取明文密碼。

客戶端和服務(wù)器通過(guò)約定的算法,對(duì)傳遞的參數(shù)值進(jìn)行簽名匹配,防止參數(shù)在請(qǐng)求過(guò)程中被抓取篡改。

總是使用HTTPS,沒(méi)有例外。當(dāng)今,只要連接了互聯(lián)網(wǎng),你的API就能夠在世界任何地方被訪問(wèn)。不是所有的訪問(wèn)都是安全的。有一些API數(shù)據(jù)沒(méi)有被加密,很容易遭到劫持并被篡改。

兼容性

在版本1.0.0在使用接口/users,如果在開(kāi)發(fā)1.1.0版本的時(shí)候修改了接口/users的邏輯,在1.1。0發(fā)版的時(shí)候線上就會(huì)出現(xiàn)兩個(gè)版本的客戶端訪問(wèn)同一個(gè)接口/users,為了保證1.0.0版本調(diào)用接口/users不會(huì)出錯(cuò),就需要通過(guò)version字段或在路由中的/v1/users/v2/users進(jìn)行區(qū)分,不同版本客戶端訪問(wèn)同一接口時(shí)處理邏輯要各自獨(dú)立。

接口或者字段的刪除、修改要謹(jǐn)慎:對(duì)于已經(jīng)存在的接口進(jìn)行修改,需要考慮對(duì)線上版本的影響,盡量是數(shù)據(jù)含義,和新增字段,而不是去修改。

性能優(yōu)化

合并接口

為了減少客戶端和服務(wù)器建立連接和斷開(kāi)連接消耗的時(shí)間、資源、電量,盡量避免頻繁的間隔網(wǎng)絡(luò)請(qǐng)求。

業(yè)務(wù)場(chǎng)景允許的情況下,盡量一個(gè)頁(yè)面對(duì)應(yīng)一個(gè)接口。原先一個(gè)頁(yè)面要通過(guò)多個(gè)請(qǐng)求獲取多種類型數(shù)據(jù)的情況,最好能通過(guò)一個(gè)接口全部獲取得到。又如:在調(diào)用B接口前需要A接口的前置數(shù)據(jù)的情況,可以讓后端支持下,在調(diào)用A接口時(shí)直接返回B接口的數(shù)據(jù),減少類似這種的連續(xù)請(qǐng)求。

字段精簡(jiǎn)

定義字段名時(shí),在保證良好可讀性的前提下,盡量精簡(jiǎn),減少流量的消耗

md5緩存

對(duì)于頻繁調(diào)用且數(shù)據(jù)不常變化的接口,可以在返回的數(shù)據(jù)中添加md5字段(用于校驗(yàn)除md5外其他數(shù)據(jù)是否變化),在下次請(qǐng)求的時(shí)候?qū)⑦@個(gè)md5作為參數(shù)傳給后端,md5沒(méi)有變化的情況下,不返回data,客戶端可以直接使用上次請(qǐng)求緩存在本地的data

限制API返回的字段

API調(diào)用者有時(shí)候不希望資源的所有字段都返回。如果能夠在調(diào)用時(shí),選擇API能夠返回的字段,或者同個(gè)接口不同狀態(tài)下需要返回的字段各不相同的時(shí)候,將減少網(wǎng)絡(luò)傳輸流量,加速調(diào)用方的業(yè)務(wù)處理。

可以使用fields查詢參數(shù)來(lái)限制API返回的字段。比如,以下請(qǐng)求只返回需要的字段信息: /users/12?fields=id,name,age

圖片裁剪服務(wù)

客戶端上傳圖片后,當(dāng)需要在列表這些圖片區(qū)域較小的地方展示的時(shí)候,沒(méi)必要直接加載原圖,可以先在后端通過(guò)圖片裁剪服務(wù)處理后再進(jìn)行展示。

局部刷新

一個(gè)頁(yè)面,如果之前已經(jīng)加載了20%的數(shù)據(jù),那么就不需要每次都返回100%數(shù)據(jù),只要返回剩余80%即可。例:社區(qū)帖子列表,每個(gè)列表中的帖子其實(shí)已經(jīng)具有title、content、createTime等字段,那么點(diǎn)擊進(jìn)入貼吧詳情的時(shí)候,title、content、createTime就可以從列表傳遞過(guò)來(lái),詳情頁(yè)的請(qǐng)求只需要返回剩余數(shù)據(jù),客戶端需要額外處理數(shù)據(jù)組裝邏輯,將前一個(gè)頁(yè)面?zhèn)鬟f過(guò)來(lái)的字段和詳情頁(yè)請(qǐng)求到的字段組裝成完整的model數(shù)據(jù)。

wifi與移動(dòng)網(wǎng)絡(luò)的區(qū)別對(duì)待

WiFi連接下,網(wǎng)絡(luò)傳輸?shù)碾娏肯囊纫苿?dòng)網(wǎng)絡(luò)少很多,應(yīng)該盡量減少移動(dòng)網(wǎng)絡(luò)下的數(shù)據(jù)傳輸,多在WiFi環(huán)境下傳輸數(shù)據(jù)。例:crash日志上報(bào),數(shù)據(jù)統(tǒng)計(jì)接口等,可以在移動(dòng)網(wǎng)絡(luò)的情況下請(qǐng)求頻率降低,或緩存,在wifi網(wǎng)絡(luò)時(shí)上調(diào)請(qǐng)求頻率,或?qū)⒕彺娴臄?shù)據(jù)統(tǒng)一上報(bào)。還有上文提到的,如果是wifi網(wǎng)絡(luò)狀態(tài)下,就下發(fā)高清圖提升用戶體驗(yàn),移動(dòng)網(wǎng)絡(luò)狀態(tài)就下發(fā)縮略,或裁剪圖。

體驗(yàn)優(yōu)化

設(shè)計(jì)接口時(shí),不能只考慮減少流量消耗,性能優(yōu)化等,特定場(chǎng)景下用戶體驗(yàn)的優(yōu)化才是最高優(yōu)先級(jí)的。

通過(guò)預(yù)加載降低對(duì)網(wǎng)絡(luò)的依賴

在網(wǎng)絡(luò)較差的情況。
例:列入要做電梯或者進(jìn)地下室,這時(shí)候網(wǎng)絡(luò)比較差的,查看帖子詳情,可能就會(huì)加載不出來(lái),提示網(wǎng)絡(luò)錯(cuò)誤等,影響正常體驗(yàn)。可以考慮在列表的接口中,將詳情的數(shù)據(jù)一起請(qǐng)求下發(fā),可通過(guò)md5判斷詳情頁(yè)面數(shù)據(jù)是否變化,避免重復(fù)加載,這樣用戶在網(wǎng)絡(luò)比較好的情況下請(qǐng)求一次列表后,再進(jìn)入詳情頁(yè),就不再需要重新請(qǐng)求,對(duì)網(wǎng)絡(luò)的依賴也是最小的。
前幾頁(yè)的帖子,用戶查看詳情的概率較高,可以在返回列表的時(shí)候攜帶正文內(nèi)容,則可以實(shí)現(xiàn)秒開(kāi)詳情,也可以判斷網(wǎng)絡(luò)狀態(tài),wifi場(chǎng)景下可以將詳情數(shù)據(jù)都返回。

錯(cuò)誤代碼

就像HTML頁(yè)面出錯(cuò)了展示的錯(cuò)誤消息一樣,API在出錯(cuò)時(shí)也應(yīng)該提供一個(gè)有用的錯(cuò)誤消息給調(diào)用方。

API應(yīng)該總是返回合理的HTTP狀態(tài)碼。API的錯(cuò)誤通常分為兩類:客戶端調(diào)用錯(cuò)誤使用的400系列狀態(tài)碼,和服務(wù)端處理錯(cuò)誤使用的500系列狀態(tài)碼。

一個(gè)JSON錯(cuò)誤消息應(yīng)該包含這么幾個(gè)部分,一個(gè)有用的錯(cuò)誤消息,一個(gè)唯一的錯(cuò)誤碼(方便在接口文檔里查到更詳細(xì)的錯(cuò)誤描述)和一個(gè)詳盡的錯(cuò)誤描述。

在開(kāi)始設(shè)計(jì)的時(shí)候,

  1. 查詢類的接口,應(yīng)盡可能使用被動(dòng)式提供數(shù)據(jù)的無(wú)狀態(tài)接口,格式應(yīng)盡可能使用對(duì)象。這樣的接口對(duì)于擴(kuò)展字段非常的方便,也很容易做到向下兼容。這樣的增量接口,對(duì)于老的自動(dòng)化測(cè)試來(lái)說(shuō),不會(huì)失效,仍然可以跑。
  2. 操作類的接口,盡可能地將資源分離,比如修改用戶信息、修改用戶頭像信息、修改用戶職位信息,這樣的接口,盡可能使用獨(dú)立的資源。
  3. 比較難搞的是數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)不合理,那就是新增一個(gè)接口,只能盡可能避免。

對(duì)于實(shí)在沒(méi)有辦法需要全面升級(jí)接口的,如果可能,保持原有的業(yè)務(wù),原有的接口運(yùn)轉(zhuǎn)正常,然后構(gòu)建一套全新的隔離的接口,最后做下版本使用監(jiān)控,當(dāng)觀察到所有用戶都使用新版本的客戶端的時(shí)候,并保持一段時(shí)間的時(shí)候,放棄對(duì)老版本的維護(hù),繼而下掉老版本的資源,當(dāng)然,萬(wàn)不得已的時(shí)候還可以用強(qiáng)制更新。

接口統(tǒng)計(jì)功能

為了更好的了解我們用戶的使用情況,需要我們盡可能多的收集客戶端的信息,除了傳統(tǒng)的IPUser-Agent之外,還應(yīng)該收集一些移動(dòng)相關(guān)的信息,比如:

  • 手機(jī)操作系統(tǒng),是android還是ios,都是什么版本
  • 用戶使用的網(wǎng)絡(luò)狀況,是2G、3G、4G還是WIFI
  • 客戶端APP是什么版本信息。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,882評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,208評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 175,746評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 62,666評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,477評(píng)論 6 407
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 54,960評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,047評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,200評(píng)論 0 288
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,726評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,617評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,807評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,327評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,049評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,425評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 35,674評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,432評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,769評(píng)論 2 372

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