千萬級WebSocket消息推送
===
### 技術復雜度分析
* 在線人數: 100萬
* 發送消息: 1000條/秒
* 推送頻率: 100萬 \* 1000條/秒 = 10億條/秒
* N個業務推送頻率: N \* 10億條/秒
### [](https://github.com/dollarkillerx/Tens-of-thousands-of-messages-pushed#%E6%8E%A8%E6%A8%A1%E5%BC%8F%E4%B8%8E%E6%8B%89%E6%A8%A1%E5%BC%8F)推模式與拉模式
* 拉模式
* 數據更新頻率低,大多數請求是無效的
* 在線用戶數多,服務端查詢負載高
* 定時輪詢拉取,無法滿足時效性要求
* 推模式
* 僅在數據更新時才需要推送
* 需要維護大量的在線長連接
* 數據更新立即推送,高時效性
* 基于WebSocket協議
* 瀏覽器支持socket編程,輕松維持服務端長連接
* 基于TCP可靠傳輸之上的協議,無需關系通訊細節
* 提供高度抽象編程接口,業務才發成本較低
### [](https://github.com/dollarkillerx/Tens-of-thousands-of-messages-pushed#%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%8A%80%E6%9C%AF%E9%80%89%E9%A1%B9)服務端技術選項
* NodeJS
* 單線程模型,推送性能有效
* C/C++
* TCP通訊,WebSocket協議實現成本高
* Go
* 多線程,基于協程模型并發
* 成熟的WebSocket標準庫,不需造輪子
### [](https://github.com/dollarkillerx/Tens-of-thousands-of-messages-pushed#%E6%8A%80%E6%9C%AF%E9%9A%BE%E7%82%B9)技術難點
* 3個性能瓶頸
* 內核瓶頸
* 推送量大: 100萬在線\*10條/秒 = 1000萬條/秒
* linux內核發送TCP的極限包頻率 約為 100萬/秒
* 鎖瓶頸
* 需要維護在線用戶集合(100萬在線),通常是一個字典結構
* 推送消息即遍歷整個集合,順序發送消息,耗時極長
* 推送期間,客戶端仍舊正常上/下線,所以集合需要上鎖
* CPU瓶頸
* 瀏覽器與客戶端通常采取json格式通訊
* json編碼非常耗費CPU資源
* 向100萬在線推送1次,則需100萬次json encode
### [](https://github.com/dollarkillerx/Tens-of-thousands-of-messages-pushed#%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88)解決方案
* 內核瓶頸
* 優化原理
* 減少網絡小包的發送
* 優化方案
* 將同一s內的n條消息,合并成1條消息
* 合并后,每秒推送次數只等于在線連接數
* 鎖瓶頸
* 優化原理
* 大拆小
* 優化方案
* 連接打散到多個集合中,每一個集合有自己的鎖
* 多協程并發推送多個集合,避免鎖的競爭
* 讀寫鎖取代互斥鎖,多個推送可以并發遍歷相同集合
* CPU瓶頸
* 優化原理
* 減少重復計算
* 優化方案
* json編碼前置,1次消息編碼 + 100 萬次推送
* 消息合并前置,n條消息合并后只編碼一次
* 單機架構

* 分布式架構
* 單機瓶頸
* 維護海量長連接會話費不少內存
* 消息推送瞬間消耗大量CPU資源
* 消息推送瞬時帶寬高達400~600MB(4-6Gbits),主要瓶頸
* 網管集群
* 每一個消息進來 分配給不同的網管
* 這時就會出現問題,返回消息怎么知道是那個網管的呢?(一般廣播解決)
* 邏輯集群
* 基于HTTP/2協議想gateway集群分發消息
* HTTP/2支持鏈接復用,用于PRC性能更佳
* 基于HTTP/1協議對外提供推送API
* HTTP/1更加普及,對業務方更加友好
OK

[https://github.com/dollarkillerx/Tens-of-thousands-of-messages-pushed](https://github.com/dollarkillerx/Tens-of-thousands-of-messages-pushed)
- 初認GOlang Web
- 關于環境配置
- 路由
- 路由進階與目錄架構
- 靜態文件服務器
- 自定義Middleware
- 與MySQL起舞
- 主從模式概念
- 部署主從集群
- 分庫分表
- 補充:事務
- 補充:常用SQL示例
- Template使用
- 一些小的,但是要知道的東西
- 調度任務
- 流控算法
- 鑒權
- JWT鑒權前置知識:加密解密
- session
- 文件上傳與下載
- 帶緩存讀寫拷貝io
- 參考
- 寫好的文件上傳
- 文件下載
- 拓展:秒傳功能實現
- 擴展:分塊上傳和斷點續傳
- 擴展:分塊上傳
- 擴展:斷點續傳
- 擴展:分布式存儲
- 部署ceph集群
- cephAuth
- go操作ceph集群
- 擴展:云存儲
- go操作oss
- 補充:xorm框架
- 命令小結
- 補充:xorm框架高級部分
- 補充
- MongoDB
- 基礎概念
- 簡簡單單NoSql
- 操作集合(Collection)
- 操作文檔(Document)
- 帶條件的文檔 db.find
- 復雜條件抽文檔 db.find
- redis
- redis操作
- go操作redis
- (新增)配置鑒權
- 密碼學
- 文件校驗算法
- 未來課程的安排
- RPC實踐
- 爬蟲
- 正則表達式
- 爬取手機號
- 爬取郵箱
- 爬取超鏈接
- 爬取身份證號
- 并發爬圖片
- 擴展:CICD
- GO實現自動化部署系統
- 國際化支持
- 并發帶來問題的解決
- GOWEB小知識
- Sync包講解
- sync.Pool
- 千萬級WebSocket消息推送
- 微服務入門:開篇
- 路由通訊
- RabbitMQ
- RabbitMQ工作原理和轉發模式
- Dcoker 下 RabbitMQ and Ui
- Go操作RabbitMQ
- 初步微服務
- go-micro
- 補充:consul
- 快速入門
- 補充:consul超時
- 微服務架構
- 微服務架構全景圖
- 服務注冊和發現
- raft協議基本概念
- raft協議leader選舉詳解
- raft協議日志復制詳解
- raft協議safefy詳解
- rpc調用個服務監控
- etcd
- 命令行使用
- Golang操作etcd
- GO操作etcd OP方式 (分布式鎖基礎)
- etcd 分布式集群樂觀鎖
- (新增)鑒權
- 服務注冊
- 服務發現原理
- 選項設計模式介紹
- 基于插件的注冊組建
- 課前知識
- etcd注冊開發1
- ffmpeg
- 2.0新的啟航
- 高可用Mysql
- mysql邏輯架構
- 常見的MySQL高可用方案
- 索引
- MYSQL調優
- 什么影響了MYSQL的性能
- Mysql 服務器參數配置
- Go深入并發
- 基本同步原語
- 擴展同步原語
- 原子操作
- M P G 模型
- 簡單的消息總線
- GoMicro入門
- GO任務池編寫
- GO依賴注入
- 一些補充
- golang defer在什么時候執行
- 分布式理論篇(面試吹牛必備)
- CAP理論
- Raft協議
- 保證注冊中心的可靠性
- 鏈路追蹤
- 怎么實現強一致性