目標:構建高可靠、高性能的web應用,這是接下來學習的一些重點。
一、可靠性:可擴展性、服務降級、負載均衡
垂直擴展(scala up):提高機器硬件配置,如加內存等
水平擴展:加機器,服務須無狀態,可分佈式
數據庫擴展sharding:
–垂直拆分(一個庫數據量太大,表間將關聯密切的表劃分在一起):
如User Order庫拆成 ->User 、 Order
–水平拆分(一個表的數據量太大,一表拆多表,根據查詢使用過情況確定規則,單表數據不要超過1000萬,做好索引):
如Order表根據 -hash , -代理商拆分
二、性能:緩存、併發、池化、異步
①負載均衡
Ngin反向代理服務器:http轉發,一個請求對應多臺機器
策略:
Random,隨機打到哪臺機器
RoundRobin,輪詢
LeastActive,如果一個機器A處理請求返回慢,可能就把請求打到另一臺機器B
IPHash, Hash策略 ,如根據hash做hash,特定用戶打到特定機器,
ConsistentHash,如根據內容做hash,有緩存的請求打到 同一臺機器
健康檢查:
Healthcheck.html, Nginx定期檢查Healcheck.html,如不能查到說明這機器掛了
②服務降級
對提供的服務進行分級,核心 服務具有更高的優先級,動態地關閉某個功能等
功能開關:全流程開關, 如去哪兒的qconfig
③併發-Servlet
容易出現的 問題 :
- count++;語句是線程不安全的
- 在多線程環境下如servlet中的全局變量定義使用HashMap,可以使用ConcurrentHashMap()或者Collections.unmodifiableMap(new HashMap() )來進行安全的讀(get)操作,在doGet或doPost定義的本地map是線程安全的
④併發-鎖
低併發推薦使用 AtomicInteger、AtomicLong
synchronized, 一直等。ReentrantLock:可重入鎖、互斥,它有timeout機制
讀寫鎖:ReadWriteLock 讀鎖是共享鎖,寫鎖是排它鎖互斥的,讀寫鎖有級別,獲取到讀鎖的線程不能升級成寫鎖,能降級,寫鎖能獲取到讀鎖,適合讀多寫少
樂觀鎖:分佈式鎖 ?
悲觀鎖:
⑤緩存-本地
HashMap
ConcurrentHashMap
用戶的搜索結果進行緩存等,可以用Guava Cache,設置過期策略
memcached集羣, 使用key-value 如 username_zhangsan -> {“username:zhangsan”, “nickname”:“二哈”}
LRU: 近期最少使用
分佈式 : 一致性Hash, client實現
Client : xmemcached 、spymemcached
⑥緩存-redis
豐富的數據結構,可持久化: Hash , List, Set , SortedSet(給set中的每個元素給個score分,如實現分佈式 優先級隊列)
⑦序列化
方式有:
- Json (fastjson或者jackson)
- Java serialization (記得顯示指定serializeVersionID?)
- Hessian (dubbo使用)
dubbo中序列化不要使用枚舉類,否則枚舉變了服務更新不同步
⑧池化技術,複用資源
- 線程池: Executor
- 連接池: tomcat-jdbc、dbcp,c3p0
- 對象池:spring針對對象的管理其實是一個對象池,又比如說A-B, A-C, A-D可以建個A的對象池,節約內存
⑨性能-異步
–前端輪詢、後端異步,如做一個搜索系統,搜索很耗時,不能同步地等待應使用異步,但異步要控制好流量,別把別人的服務請求崩了
Futrue/CountDownLatch
消息隊列,消息一定要被消費,qmq使用推的方式,kafka只存下消息,讓客戶端自己來消費
QMQ/Kafka/AMQ/rabbitmq
HTTP
async-http-client
Apache HttpComponents
Dubbo
異步調用、參數回調