App 後臺架構

轉載請註明出處:http://blog.csdn.net/smartbetter/article/details/53933096html

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

提及架構,咱們先看一下何爲架構,百度百科是這樣說的:架構,又名軟件架構,是有關軟件總體結構與組件的抽象描述,用於指導大型軟件系統各個方面的設計。那麼咱們也能夠看出,架構是和業務緊密相關的,是由業務驅動的。數據庫

因爲App客戶端的特性,所以App後臺對技術實現和通常的Web後臺是有區別的。首先看一個適合App開發的開發模式:編程

1.敏捷開發模式

這裏推薦Scrum這個敏捷開發框架,具體能夠查看Scrum官網學習使用,這裏只是引入。json

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) 將會是很好的選擇。服務器

軟件優化:markdown

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

硬件優化:網絡

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

架構優化:

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

讀寫分離架構

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

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 查看網絡相關信息
  • 1
  • 2
  • 3

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
  • 2

這樣,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」 表。
  • 1
  • 2
  • 3

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

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

相關文章
相關標籤/搜索