- 什麼是 RPC?
- RPC 有什麼作用?
- RPC 步驟
- 爲什麼需要序列化?
- 零拷貝
- 動態代理實現
- HTTP/2 特性
- 爲什麼需要服務發現?
- 定時任務 & 時間輪
- 如何註冊和發現服務?
- 如何實現 RPC 遠程調用?
- 如何追蹤微服務?
- 註冊中心選型
- 開源 RPC 框架
- Spring Cloud 微服務架構
什麼是 RPC?
Remote Procedure Call,遠程過程調用。
RPC 有什麼作用?
- 屏蔽遠程調用、本地調用的區別
隱藏底層網絡通信的複雜性
,讓我們更專注於業務
RPC 步驟
爲什麼需要序列化?
- 網絡傳輸必須是「二進制」,調用方的參數都是對象
- 請求↔二進制消息體
零拷貝
什麼是零拷貝?
爲什麼需要零拷貝?
網卡
等操作,只能通過內核操作
,應用程序
要發送網絡數據,需要將數據複製到內核
。
如何實現零拷貝?
虛擬內存
- mmap + write
- sendfile
Netty 的零拷貝有何不同?
- 一個請求,可能拆分成多個數據包
- 數據包的組合在用戶空間,解決用戶空間內存的拷貝處理問題,CompositeByteBuf
- 也包括用戶空間、內核空間的數據拷貝:Direct Buffers
動態代理實現
- JDK:只能代理接口
Javassist
:操作底層字節碼
,不需要反射,性能好Byte Buddy
:更容易的 API,速度比 Javassist 快,Spring、Jackson 使用
HTTP/2 特性
多路複用
,同一鏈路雙向發送stream數據Header 壓縮
爲什麼需要服務發現?
公共的“通訊錄”
爲什麼不用 DNS?
- DNS多級緩存,且緩存時間長
- 需要搭建負載均衡,額外成本
定時任務 & 時間輪
定時任務的問題?
- future 啓動線程進行異步編程,sleep
- 如果5秒超時,高併發的
- 讓CPU額外輪詢遍歷,浪費CPU
時間輪的應用
- 延遲消息
- 訂單過期(10分鐘未付款,取消訂單)
時鐘輪本質
減少額外的掃描操作
時間輪在 RPC 的應用
調用端請求的超時處理,節省CPU
時間輪實現
Netty的 TimeWheel
如何註冊和發現服務?
RPC Server
提供服務,向 Registry 註冊自身RPC Client
調用服務,從 Registry 拉取服務列表- Server 節點變更時,同步變更,Client 感知刷新本地的「服務節點列表」
實現:
- 註冊中心 API
- 服務健康狀態監測:ZooKeeper 的會話超時控制機制
- 服務狀態變更通知:ZooKeeper 的 Watcher 機制
如何實現 RPC 遠程調用?
- 客戶端、服務端如何建立網絡連接:HTTP、Socket
- 服務端如何處理請求:NIO(使用
Netty
) - 數據傳輸採用什麼協議
- 數據如何序列化、反序列化:JSON,PB,Thrift
如何追蹤微服務?
核心理念:調用鏈,全局唯一的 ID
將同一請求串聯起來,從而還原調用關係,統計系統指標。
註冊中心選型
高可用
- 集羣部署:多個實例
- 多機房部署:一個機房斷電等不可抗因素
數據一致性
CP
型:ZooKeeper(Redis),強一致性,機房間斷網,註冊中心不可用- AP 型:犧牲一致性,保證可用性。Eureka
開源 RPC 框架
限定語言
- Dubbo:Java,阿里
- Motan:Java,微博
- Tars:C++,騰訊(已支持多語言)
- Spring Cloud:Java
- 網關 Zuul
- 註冊中心 Eureka
- 服務超時熔斷 Hystrix
- 調用鏈監控 Sleuth
- 日誌分析 ELK
跨語言 RPC 框架
- gRPC:HTTP/2
- Thrift:TCP
Spring Cloud 微服務架構
代碼、思維導圖筆記鏈接
代碼和思維導圖在 GitHub 項目中,歡迎大家 star!
coding 筆記、點滴記錄,以後的文章也會同步到公衆號(Coding Insight)中,希望大家關注_