億級網(wǎng)關(guān)janus性能優(yōu)化與jvm調(diào)優(yōu)實踐
個人簡介
蔡磊 在唯品會基礎(chǔ)架構(gòu)服務(wù)化團隊,負(fù)責(zé)唯品會API Gateway/Reverse Proxy的設(shè)計與開發(fā)辣垒,性能調(diào)優(yōu)與疑難雜癥枫吧。
大綱
- janus背景介紹與技術(shù)選型
- 線程模型與優(yōu)化
- netty深度調(diào)優(yōu)與實踐
- 性能瓶頸快速定位工具與方法論
- 高并發(fā)下的gc優(yōu)化與排查,控制每月一次頻率
- 通用計數(shù)器需求場景實現(xiàn)
- 一個有意思的gc問題
- 踩坑后的代碼規(guī)范總結(jié)
janus網(wǎng)關(guān)背景
- 定位:高性能腹纳,高可用身腻,可擴展,可管理厘熟,可治理屯蹦,安全的網(wǎng)關(guān)產(chǎn)品,作為所有流量的入口
- 網(wǎng)關(guān)價值:中心化網(wǎng)關(guān)所能提供的所有統(tǒng)一控制盯漂。權(quán)限,安全笨农,資源限制就缆,防刷,聚合谒亦,熔斷與重試竭宰,同機房路由,灰度導(dǎo)流等等
- 底層技術(shù)選型份招,從servlet到akka到netty
- 目前主要是ApiGateway 由于容器與功能復(fù)用切揭,也做了部分反向代理
線程模型與優(yōu)化
- 經(jīng)典的netty boss worker模型
- 多個worker線程池共享:接入請求的worker與轉(zhuǎn)發(fā)的http/rpc請求線程worker共用相同線程池
- 一次轉(zhuǎn)發(fā)的worker線程盡量不切換:接收請求的netty的worker與轉(zhuǎn)發(fā)請求的worker在同一線程,減少切換锁摔,不會放入隊列再出隊
- 插件化引入共享線程池+獨立線程池模型
- 性能數(shù)據(jù)介紹
netty深度調(diào)優(yōu)與實踐
- 基于worker線程內(nèi)共享,無鎖化;安全共享處理各種非線程安全代碼,全異步化
- netty native epoll
- bytebuf有解析請求時使用堆內(nèi)對外對比
- boss線程根據(jù)端口數(shù)來決定,
- 重寫netty handle的提前半解析優(yōu)化
- 重度使用netty InternalThreadLocalMap jdk7使用PlatformDependent工具
- worker線程池合并
- 一次請求過程worker線程不切換上下文
性能瓶頸快速定位工具與方法論
- 沒有魔法廓旬,盡可能的善用工具,識別優(yōu)化最大價值點
- 從系統(tǒng)底層監(jiān)控到j(luò)vm層
- 火焰圖:系統(tǒng)函數(shù)調(diào)用+jvm方法棧消耗
- jmc java自帶分析工具
- jmh 最好通讀官方demo谐腰,避免寫錯誤的使用
高并發(fā)下的gc優(yōu)化與排查
- 控制每月一次cms頻率
- 內(nèi)存溢出問題各種踩坑:熔斷與指標(biāo)統(tǒng)計
- log4j2升級2.6版本free gc
- 源碼無秘密:jdk7默認(rèn)出發(fā)cms為什么是92%
- kafka原生代碼的指標(biāo)采樣導(dǎo)致old區(qū)晉升過快
- 高io導(dǎo)致jvm停頓孕豹,gc日志放ramfs,并生產(chǎn)環(huán)境加入-XX:+PerfDisableSharedMem來避免生成perf
- 重用對象減少垃圾對象數(shù)量
通用計數(shù)器實現(xiàn)方案
- 滑動窗口實現(xiàn):時間輪+數(shù)組桶
- 提前清理vs使用時清理
- 清理對象復(fù)用 使用時清理:清理上次時間到當(dāng)天時間十气,需要加鎖励背,自旋鎖清理
- 內(nèi)存與性能:AtomicLong vs LongAdder
- 哪些場景可以用到(限流 防刷 熔斷所有要計數(shù)的需求)
一個有意思的gc問題
- 使用lru使用角度來談gc問題選擇
- lru準(zhǔn)確性,由于不夠用砸西,所以盡量大則準(zhǔn)確叶眉,那么gc問題就來了
- 跟著ygc隨波逐流址儒,釋放對象,解決就要根據(jù)流量模型設(shè)置大小
- 進一步抽象衅疙,所有能熬過ygc到老年代莲趣,并且存在反復(fù)創(chuàng)建的都有此問題,比如從各種鏈接池清理閑置鏈接
網(wǎng)關(guān)代碼總結(jié)幾條:
- 盡可能復(fù)用對象炼蛤,盡快釋放對象
- 參考netty代碼實現(xiàn)技巧
- 盡量無狀態(tài)無鎖妖爷,一定要有狀態(tài)優(yōu)先線程內(nèi)共享其次cas
- 了解你所寫的每行代碼內(nèi)部邏輯,jmh測試度量(一個簡單gson例子)