app后台


做App做的久了,就想研究一下與之相關的App后台,發現也是蠻有趣的。App后台的兩個重要作用就是 遠程存儲數據 和 消息中轉。這里面的知識體系也是相當復雜,做好一個App后台也是需要長期錘煉的。本篇文章從 App 后台架構 的角度介紹。好了,下面進入正題:

說起架構,我們先看一下何為架構,百度百科是這樣說的:架構,又名軟件架構,是有關軟件整體結構與組件的抽象描述,用於指導大型軟件系統各個方面的設計。那么我們也可以看出,架構是和業務緊密相關的,是由業務驅動的。

由於App客戶端的特性,因此App后台對技術實現和一般的Web后台是有區別的。首先看一個適合App開發的開發模式:

1.敏捷開發模式

這里推薦Scrum這個敏捷開發框架,具體可以查看Scrum官網學習使用,這里只是引入。

Scrum流程如下圖:

Scrum流程

2.選擇合適的數據庫產品和服務器系統

數據庫產品眾多,這里我就針對Redis、MongoDB、MySQL還有MySQL的分支MariaDB展開說明:

1.數據庫產品

數據庫 數據存放位置 查找數據的區別
Redis 內存 基於鍵值對存儲,讀寫速度快
MongoDB 同時使用了硬盤和內存 每個數據有一個id(索引),知道id(索引)查詢速度快,不知道id(索引)效率低
MySQL(MongoDB) 硬盤 每個數據有一個id(索引),知道id(索引)查詢速度快,不知道id(索引)效率低

 

 

 

 

然后根據不同的產品需求選擇恰當的數據庫產品,如果沒有特殊的需求,Redis做緩存系統,MySQL 或 MariaDB 做數據庫(常見的設置是 數據庫默認字符集utf8,默認排序utf8_general_ci) 將會是很好的選擇。

軟件優化:

  1.  
    1)正確使用MyISAM和InnoDB存儲引擎
  2.  
    2)正確使用索引
  3.  
    3)避免使用 select *
  4.  
    4)字段盡可能的設置 非NULL

硬件優化:

  1.  
    1)增加物理內存
  2.  
    2)增加應用緩存
  3.  
    3)使用SSD硬盤

架構優化:

  1.  
    1)分表
  2.  
    2)讀寫分離

讀寫分離架構

  1.  
    3)分庫(把一張表的數據分別存儲在不同的數據庫,可用MyCat實現,MyCat,關系型數據庫分布式處理軟件)。
  2.  
    MyCat以代理服務器的形式位於App服務器和后台數據庫之間,
  3.  
    對外開放的接口是MySQL通信協議,將App服務器傳過來的sql語句按照路由的規則拆解轉發到不同的后台數據庫,並把結果匯總返回。
  4.  
    MyCat部署模型如下:

MyCat部署模型

2.服務器系統

CentOS 則是一個不錯的選擇。關於服務器的部署,我在之前已經介紹過了,地址如下:

Nginx + Tomcat 反向代理 負載均衡 集群 部署指南 
http://blog.csdn.net/smartbetter/article/details/53535435

Nginx + Tomcat 反向代理 如何在高效的在一台服務器部署多個站點 
http://blog.csdn.net/smartbetter/article/details/53615313

下面補充兩個常見的Linux命令:

  1.  
    top 顯示系統資源情況
  2.  
    netstat 查看網絡相關信息

3.選擇合適的消息隊列軟件

當后台系統發現完成某些小任務需要花費很多時間,而且遲點晚成也不影響整個任務的完成進度時,就會把這些小任務交給消息隊列。例如發送郵件、短信、推送消息等任務都非常適合在消息隊列中處理。

把這些任務放在消息隊列中,可加快App后台請求都響應時間。同時消息隊列也能把大量的並發請求變成串行的請求,來減輕服務器的負擔。

常見的消息隊列軟件有:

消息隊列軟件 說明
RabbitMQ 重量級,適合企業級的開發,自帶Web監控界面,方便監控隊列的情況
Redis 輕量級,是一個key-value系統,但是也支持消息隊列這種數據結構,App后台中Redis被廣泛使用
ZeroMQ 號稱最快,尤其針對大吞吐量的需求場景
ActiveMQ Apache的一個子項目,能夠以代理人和點對點的技術實現隊列

 

 

4.使用分布式服務實現業務的復用

隨着業務不斷增加,后台系統由一個單一應用膨脹為一個巨無霸系統,系統中聚合了大量的應用和服務,各個模塊之間有很多功能重復實現(例如登錄模塊),造成了開發、運維、部署的麻煩。

膨脹的系統

大量應用中的重復模塊會帶來大量的訪問,而每個應用與數據庫的連接,一般是使用數據庫的連接池,這個連接池的資源一般是不釋放且一直保留着。假設連接池中有10個連接,中一個數百的服務器集群中,就占用了數據庫1000個連接。數據庫中的每個連接都是十分珍貴的資源,在資源有限的情況下,這里被占用了,其他能用的資源就少了。

解決這些問題的方法就是把重復實現的模塊獨立部署為遠程服務,新增的業務調用遠程服務所提供的功能實現相關的業務,不依賴於里面具體的代碼實現。

使用遠程服務后的系統

實現遠程服務可以 參考 REST設計原則 和 RPC遠程調用協議。

開源的RPC庫有:

開源的RPC庫 說明
Hprose 輕量級、跨語言、跨平台、無侵入式、高性能動態遠程對象調用引擎庫
Dubbo 分布式服務框架,致力於提供高性能和透明化的RPC遠程調用服務和SOA服務治理方案

 

 

5.用戶驗證方案最佳實踐

App操作中經常涉及用戶登錄操作,登錄就需要使用到用戶名和密碼,為了安全起見,在登錄過程中暴漏密碼的次數越少越好。

1.使用HTTPS協議

HTTPS協議是 HTTP協議 和 SSL/TLS協議 的組合。其是一個安全通信通道,基於HTTP開發,用於在客戶計算機和App后台之間交換信息。其使用安全套接字層(SSL)進行信息交換,簡單來說就是HTTP的安全版。

HTTPS實際上應用了安全套接字層(SSL)作為HTTP應用層的子層。

HTTPS的模型:

HTTP
SSL/TLS(安全套接字層/傳輸層安全協議)
TCP
IP
網絡傳輸

 

 

 

 

避免信息的泄漏,最基本的方案是所有涉及安全性的API請求都必須使用HTTPS協議。

2.選擇JSON作為數據交換格式

JSON是一種輕量級的數據交換格式,采用完全獨立於語言的文本格式,易於編寫,也易於機器解析和生成,而且對比XML更省流量,這些特性使得JSON成為理想的數據交換語言。

3.基本的用戶驗證方案

傳統Web網站使用Cookie+Session保持用戶的登錄狀態,App后台則使用token進行驗證,流程如下:

App后台基本的用戶登錄方案

此時App已經獲取到了token值,為了安全,我們不在網絡上傳輸token,而使用簽名校驗(這里使用URL簽名)的方式,API請求加上URL簽名sign和用戶id后如下:

test.com/user/update?uid=2&sign=3f1e736bc4ae958ae7e8500b45aefdbb&age=22 
  • 1

這樣,token就不需要附在URL上了。App后台簽名校驗流程如下:

App后台簽名校驗流程

還有的童鞋喜歡設置時間戳,這樣時間一長,URL就失效了,也是一種不錯的進一步的優化方案。

建議:為了保障數據安全,這里建議 同時使用 HTTPS 和 簽名校驗。

6.App后台架構的演進原則

App后台的架構是由業務規模驅動而演進的,App后台是為業務服務的,App后台的價值在於能為業務提供其所需要的功能,不應過度設計。

從項目的角度,當App訪問量不大時,應該快速搭建App后台,讓App盡快上線給用戶提供服務,驗證商業模式的正確性,同時快速迭代產品。

當App訪問量不斷上升,這時要在保證快速迭代的前提下,同時兼顧高性能和高可用。

當App訪問量達到一定階段后,增長曲線就會放緩,但業務變得更加復雜,對高性能和高可用的要求也更高,性能問題、模塊間的耦合、代碼的復雜性會更加突出和明顯,這時要使用業務拆分、分布式服務調用,甚至是技術轉型等問題。

1.項目啟動時——單機部署

我們看一個App后台極簡化的架構:

App后台極簡化的架構

一開始就使用Redis的好處:

既能用作緩存,又能充當隊列服務,而且並發性能高,能在長時間內應對業務壓力,非常適合初期的項目。

這里使用Redis驗證用戶信息,充當消息隊列。

而文件服務初期可以選擇 文件雲存儲服務,或者自己搭建一個資源服務器。

2.項目一定規模時——分布式部署

我們看一個百萬級到千萬級的架構:

百萬級到千萬級的架構

這里新增了專門用於連接內部服務器的SSH服務的外網通道,保證SSH操作隨時可用,同時加入了服務器集群,提供負載能力。

隨着業務的發展,某些數據表的規模會以幾何級增長,當數據達到一定規模時,查詢讀取性能就下降的厲害,數據庫主從的架構不能應對業務上的讀寫壓力,這時架構上要考慮分表(水平拆分/垂直拆分)。

當業務繼續不斷發展,數據庫分表后的讀寫性能也可能沒法滿足業務上的需求,這時只能采用進一步的拆分策略——分庫。用 Cobar 或者 MyCat 等關系型數據等分布式處理系統后,分庫后的架構如下:

分表分庫的架構

下來看一個真實社交App項目所采用的后台架構方案:

7.社交App后台架構設計方案分享

場景:類似 微博,用戶與用戶之間存在關注/粉絲兩種關系,一個用戶發表了新內容,關注他的用戶也能在個人主頁上收到最新的動態。類似 微博 這種場景:

weibo

社交核心功能是 Feed(指用戶通過關注,聚合了被關注用戶的最新的內容,也包含自己的內容,以供自己瀏覽的信息服務)。

1.Feed基本表結構

常見的Feed架構是把數據存儲在MySQL,熱點數據存儲(一般最近3天)在緩存(Redis/Memcached),保證絕大多數請求通過緩存直接返回,只有少量請求穿透緩存落到數據庫。

下面看一下最簡單的Feed表結構:

send_content:發送內容表,存儲用戶發表的內容:

字段 說明
feed_id 發表的feed的id,主鍵自增
author_id 發表該feed的用戶id
content feed的內容

 

 

 

 

reveive_content:接收內容表,用於推模式時存儲用戶接收的內容:

字段 說明
feed_id 發表的feed的id,主鍵自增
author_id 發表該feed的用戶id
reveive_id 接收該feed的用戶id
content feed的內容

 

 

 

 

 

followings:關注表,存儲用戶關注的人:

字段 說明
id 主鍵自增
uid 用戶id
following_id 該用戶關注的其他用戶id

 

 

 

 

followers:粉絲表,存儲用戶的粉絲:

字段 說明
id 主鍵自增
uid 用戶id
follower_id 關注該用戶的用戶id

 

 

 

2.Feed推拉模式——推模式用戶發表一條內容的流程

1)uid為1的用戶發表一條內容 “HelloWorld” 信息。 
2)這條內容寫入發送內容表 “send_content” 后內容如下:

feed_id author_id content
1 1 HelloWorld

 

 

3)在粉絲表 “followers” 查找uid為1用戶的粉絲,粉絲表 “followers” 的內容如下:

id uid follower_id
1 1 2

 

 

可知,id為1用戶的粉絲是id為2的用戶。

4)因為id為2的用戶的feed中需要顯示這條內容,因此把內容寫入接收內容表 “reveive_content”,寫入后接受內容表 “reveive_content” 內容如下:

feed_id author_id reveive_id content
1 1 2 HelloWorld

 

 

5)當id為2的用戶顯示feed時,通過sql語句 “select * from reveive_content where reveive_id=2” 就能查詢該用戶需要顯示的數據了。

推模式的缺點是:

  1. 推送人數過大會出現延時,而且浪費存儲空間;
  2. 更新操作成本大,不但變更 “send_content” 表,而且需要同步變更 “reveive_content” 表。

 

3.Feed推拉模式——拉模式用戶發表一條內容的流程:

1)uid為5的用戶發表一條內容 “Thinks” 信息。 
2)這條內容寫入發送內容表 “send_content” 后內容如下:

feed_id author_id content
1 1 HelloWorld
2 5 Thinks

 

 

 

3)當uid為10的用戶顯示feed時,在關注表 “followings” 查找uid為10所關注的用戶,關注表如下:

id uid following_id
1 10 5

 

 

 

可知,uid為10的用戶關注了uid為5的用戶,因此需要獲取uid為5的用戶發表的內容。

4)uid為5的用戶通過sql語句 “select * from send_content where author_id in (5)” 查詢所以需要顯示的內容。

由上述可知,拉模式采用了時間換空間的策略,用戶推送內容時效率很高,但當用戶顯示feed時,需要花費大量的時間在聚合運算上。

總結:

- 發表內容 顯示feed 變更通知
推模式 推送給所有粉絲 一個sql語句就能完成 變更成本高
拉模式 不推送 需要大量的聚合運算 無變更成本

 

 

 

像 “微博” 中公開的微博采用拉模式,私密性的微博采用推模式。

拉模式最大的問題就是大量的聚合運算,請求的響應時間可能較長,可以通過緩存策略讓大部分的請求的響應時間達到2到3毫秒。

8.其他的一些經驗

1.高效更新數據——內容的推拉

平常App設計中,如果App需要知道首頁是否有內容更新,通過一個輪詢機制訪問獲取數據API,從API是否返回更新的數據得知是否有內容更新,輪詢上很典型的拉模式,但是耗電、耗流量。

怎么減少輪詢呢? 這里給出解決方案是推模式,如下圖:

內容的推拉

當然不能只用推模式,因為手機環境的復雜性,不能保證數據更新的通知一定能夠到達App,所以也要采用輪詢的方式定期拉數據,時間間隔設置可以相對長一點,通過這種推拉結合的模式,就能大大減少App訪問App后台的頻率和傳輸的數據量。

2.處理表情的一些技巧

表情在MySQL的存儲,表情UTF-8編碼有的是3個字節,有的是4個字節,所以一般的UTF編碼(3個字節)是無法存儲表情數據的,常用的解決方案是:

把MySQL升級到5.5以上,然后把字符編碼改為utf8mb4_general_ci。

3.可供選擇的成熟穩定的開源軟件

功能 可供選擇的開源軟件
項目管理軟件 Mantis、BugFree
代碼管理軟件 SVN、Git
編程語言 Java、PHP、Python等
服務器系統 CentOS、Ubuntu
HTTP/HTTPS服務器 Nginx、Tomcat、Apache
負載均衡 Nginx、LVS、HAProxy
郵件服務 Postfix、Sendmail
消息隊列 RabbitMQ、ZeroMQ、Redis
文件系統 Fastdfs、mogileFS、TFS
Android推送 Androidpn、gopush
IOS推送 Javapns、Pyapns
地理位置查詢LBS MongoDB
聊天 Openfire、ejobberd
監控 ngiOS、zabbix
緩存 Memcache、Redis
關系型數據庫 MySQL、MariaDB、PostgreSQL
NoSQL數據庫 Redis、MongoDB、Cassandra
搜索 Coreseek、Solr、ElasticSearch
圖片處理 GraphicsMagick、ImageMagick
分布式訪問服務 dubbo、dubbox

 

 

 

 

 

 

 

 

 

 

 

 

3.可供選擇的成熟可靠的雲服務

對於初創公司還是建議盡可能的使用成熟可靠的雲服務和開源軟件,自身只專注於業務邏輯。

功能 可供選擇的雲服務
項目管理工具 Teambition、Tower
代碼托管平台 GitHub、Gitlab、Bitbucket、CSDN CODE、Coding
負載均衡 阿里雲SLB、騰訊雲CLB
郵件服務 SendCloud、MailGun
消息隊列 阿里雲MNS、騰訊雲CMQ
文件系統、圖片處理 七牛雲、阿里雲對象存儲OSS、騰訊雲對象存儲COS
Android推送 極光、個推、百度推送
IOS推送 極光、個推、百度推送
聊天 融雲、環信
監控 監控寶、雲服務器自帶的監控服務
緩存 阿里雲緩存服務、騰訊雲彈性緩存
關系型數據庫 阿里雲RDS、騰訊雲CDB
NoSQL數據庫 阿里雲NoSQL產品、騰訊雲NoSQL產品
搜索 阿里雲開放搜索、騰訊雲搜TCS
分布式訪問服務 阿里雲EDAS
防火牆 阿里雲雲盾、騰訊雲安全
短信發送 shareSDK、bmob、Luosimao
社交登錄分享 shareSDK

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

最后,在移動互聯網項目中,產品的研發講求 小步快走,快速迭代。 架構的設計也可以遵循同樣的思路,喜歡本文的記得 頂 一下哦!

 

轉自:

http://blog.csdn.net/smartbetter/article/details/53933096

https://blog.csdn.net/yangzhongxuan/article/details/77949315


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM