記一次web服務的調優

2021-07-23 03:29:16 字數 2525 閱讀 6783

首先,描述一下環境,簡單的web服務,關鍵日誌寫入kafka,要求qps達到單機10k即可。

後面將遇到的問題、解決方案和原理記錄如下:

1、記憶體占用過大,雖然

jvm的堆記憶體設為

1g,但程序實際記憶體使用量達到了

12g

解決方案:程式中使用了

kafka

,new

出kafka producer

來向kafka

中寫日誌,調整

kafka

引數解決,調大了

batch.size

和partition

原理:原因還是

batch.size

和partition

設定過小,導致要傳送的資料報過多,都堵在了

producer

的機器上,而

kafka producer

又使用了

zero copy

技術,使得占用了大量的核心態記憶體無法釋放,而核心態記憶體又不是堆記憶體,不由使用者控制,所以出現了程序占用記憶體過大的情況,

kafka

版本為0.8.2.2

。(其實這裡還存在一點疑問,網上說kafka通訊時使用了zerocopy,但我實際跟進**時,producer使用的是bytebuffer.allocate,也就是說使用的是堆記憶體,而沒有呼叫bytebuffer.allocatedirect建立非堆記憶體,與網上說的有衝突。如果哪位朋友知道這個問題的原理,還請賜教)

2、長時間負載高的情況下,程式效能下降明顯,檢視

gc情況,發現頻繁進行

full gc

解決方案

通過使用

jmap -dump

將記憶體中的物件資訊匯出到檔案,使用

jhat

命令分析,查出是乙個

kafka callback

物件過多,而這個

callback

物件包含了一些內容較長的字串型別的私有變數,導致字串佔了較多記憶體,而

kafka

的producer

有快取機制,就會導致

callback

物件佔據記憶體無法釋放,後來通過刪除了

callback

的私有變數,將

call

back

變為單例,來減少了記憶體占用

3

、多執行緒丟資料

解決方案:由於有實時性要求,所以不能阻塞,只能通過加大佇列長度和子執行緒的數量的方式 

原理:主線程向子執行緒分配任務時,未自己管理

blockingqueue

,而是交由作業系統自己管理,向子執行緒分配任務時,直接分配

callable

物件

// 建立執行緒池

executorservice pool = newthreadpoolexecutor(threadpoolsize, threadpoolsize, 0l, timeunit.milliseconds,

newlinkedblockingqueue<>(queuecapacity));

// 向子執行緒分配任務

pool.submit(() ->producer.send(new producerrecord<>(topic, null, record), kafkacallback));

由於submit

方法呼叫了

blockingqueue

的offer

方法來新增,若佇列已滿,則返回

false

,而不是阻塞,且會丟擲

rejectedexecutionexception

(runtimeexception

的子類),導致丟擲異常和資料丟失

若考慮使用阻塞的方式,則可修改為自己控制

blockingqueue

,若不想使用阻塞的方式,則可加大

queuecapacity

和threadpoolsize

4

、日誌使用

log4j

記錄和寫

kafka

效能差別過大,寫日誌檔案達到

3000qps

,寫kafka

能達到11kqps

解決方案:改為使用log4j 2.x,或使用kafka

原理:通過跟進log4j的**,發現

log4j 1.x

中使用了很多

sychronized

**,導致

log4j

多執行緒下效能問題嚴重,改為

log4j 2.x

可使qps

提高到10k

記一次oracle sql調優過程

這裡兩天都在對一條sql進行調優。該sql並不複雜,類似於 select from some view union all select from some table where datetime d1 and datetime d2 and 底層使用ibatis2.1.6 oracle 10g。...

記一次php fpm http502的調優

最近,公司產線幾乎每天都有短暫的http502錯誤,同時nginx會丟擲大量的報錯,報錯內容是no live upstreams while connecting to upstream 網上查詢,這種錯誤可能是php fpm 程序已經全部被占用,沒有空閒的程序來處理多餘的請求,查了一下php fp...

記一次uwsgi django nginx 調優

uwsgi project fortune cat uid ubuntu gid ubuntu path fortune cat base home uid chdir base path project master true thunder lock true processes 2 cheap...