基于對(duì)象池模式的 JSON 處理性能提升實(shí)踐
前言
在應(yīng)用開發(fā)過(guò)程中,我們經(jīng)常會(huì)遇到對(duì)象的頻繁創(chuàng)建和銷毀操作。以Jackson 庫(kù)中的ObjectMapper為例,它用于JSON與Java對(duì)象之間的序列化和反序列化,在處理大量JSON數(shù)據(jù)時(shí),若每次使用都實(shí)例化一個(gè)新的ObjectMapper對(duì)象,不僅會(huì)消耗大量系統(tǒng)資源,還會(huì)帶來(lái)顯著的性能損耗。
實(shí)例化問(wèn)題分析
public class JsonUtils {
public static String toJson(Object obj) {
try {
// 每次調(diào)用都創(chuàng)建新的ObjectMapper實(shí)例
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(obj);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
public static <T> T fromJson(String json, Class<T> clazz) {
try {
// 每次調(diào)用都創(chuàng)建新的ObjectMapper實(shí)例
ObjectMapper mapper = new ObjectMapper();
return mapper.readValue(json, clazz);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}ObjectMapper是Jackson庫(kù)的核心類,負(fù)責(zé)處理Java對(duì)象和JSON之間的轉(zhuǎn)換工作。然而,ObjectMapper的實(shí)例化過(guò)程并非輕量級(jí)操作,它需要進(jìn)行一系列的初始化工作,包括配置默認(rèn)的序列化和反序列化規(guī)則、加載插件等。當(dāng)在高并發(fā)場(chǎng)景下,頻繁地實(shí)例化ObjectMapper對(duì)象,會(huì)產(chǎn)生以下問(wèn)題:
- 性能損耗:每次實(shí)例化
ObjectMapper都需要消耗CPU和內(nèi)存資源,尤其是在短時(shí)間內(nèi)大量實(shí)例化時(shí),會(huì)導(dǎo)致系統(tǒng)性能下降,響應(yīng)時(shí)間變長(zhǎng)。 - 垃圾回收壓力:頻繁創(chuàng)建和銷毀
ObjectMapper對(duì)象,會(huì)使Java虛擬機(jī)(JVM)的垃圾回收機(jī)制頻繁工作,占用大量的CPU時(shí)間,影響系統(tǒng)的整體吞吐量。
對(duì)象池模式簡(jiǎn)介
對(duì)象池模式(Object Pool Pattern)是一種創(chuàng)建型設(shè)計(jì)模式,它的核心思想是在系統(tǒng)初始化時(shí)預(yù)先創(chuàng)建一定數(shù)量的對(duì)象,并將這些對(duì)象存放在一個(gè)池子中。當(dāng)系統(tǒng)需要使用該對(duì)象時(shí),直接從對(duì)象池中獲取,使用完畢后再將對(duì)象放回池中,而不是每次都重新創(chuàng)建和銷毀對(duì)象。通過(guò)這種方式,可以減少對(duì)象創(chuàng)建和銷毀的開銷,提高系統(tǒng)的性能和資源利用率,對(duì)象池模式適用于以下場(chǎng)景:
- 對(duì)象的創(chuàng)建和銷毀過(guò)程比較復(fù)雜、開銷較大。
- 對(duì)象的使用頻率較高,且生命周期較短。
- 系統(tǒng)對(duì)性能和資源利用率有較高的要求。
設(shè)計(jì) ObjectMapper 對(duì)象池
- 初始化對(duì)象池:在系統(tǒng)啟動(dòng)時(shí),創(chuàng)建一定數(shù)量的
ObjectMapper對(duì)象,并將它們放入對(duì)象池中。 - 獲取對(duì)象:從對(duì)象池中獲取一個(gè)可用的
ObjectMapper對(duì)象,如果對(duì)象池為空,則根據(jù)需要?jiǎng)?chuàng)建新的對(duì)象。 - 歸還對(duì)象:使用完畢后,將
ObjectMapper對(duì)象歸還到對(duì)象池中,以便后續(xù)使用。
實(shí)現(xiàn) ObjectMapper 對(duì)象池
public class ObjectMapperPool {
private static final int POOL_SIZE = 10;
private final Queue<ObjectMapper> objectMapperQueue;
public ObjectMapperPool() {
objectMapperQueue = new LinkedList<>();
initializePool();
}
private void initializePool() {
for (int i = 0; i < POOL_SIZE; i++) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapperQueue.add(objectMapper);
}
}
public ObjectMapper borrowObjectMapper() {
if (objectMapperQueue.isEmpty()) {
return new ObjectMapper();
}
return objectMapperQueue.poll();
}
public void returnObjectMapper(ObjectMapper objectMapper) {
objectMapperQueue.add(objectMapper);
}
}使用 ObjectMapper 對(duì)象池
public class JsonUtil {
private static final ObjectMapperPool objectMapperPool = new ObjectMapperPool();
public static String toJson(Object object) {
try {
ObjectMapper objectMapper = objectMapperPool.borrowObjectMapper();
String json = objectMapper.writeValueAsString(object);
objectMapperPool.returnObjectMapper(objectMapper);
return json;
} catch (Exception e) {
throw new RuntimeException("Failed to convert object to JSON", e);
}
}
public static <T> T fromJson(String json, Class<T> clazz) {
try {
ObjectMapper objectMapper = objectMapperPool.borrowObjectMapper();
T result = objectMapper.readValue(json, clazz);
objectMapperPool.returnObjectMapper(objectMapper);
return result;
} catch (Exception e) {
throw new RuntimeException("Failed to convert JSON to object", e);
}
}
}進(jìn)階版
common-pool2是Apache開源的對(duì)象池管理工具,相比自行實(shí)現(xiàn)簡(jiǎn)單的對(duì)象池,它具備諸多優(yōu)勢(shì):
- 功能豐富:提供了對(duì)象創(chuàng)建、激活、銷毀、空閑檢測(cè)等全生命周期管理功能,支持靈活配置對(duì)象池參數(shù)。
- 性能優(yōu)越:通過(guò)高效的資源管理算法,減少資源爭(zhēng)奪,提升并發(fā)性能,降低系統(tǒng)開銷。
- 線程安全:內(nèi)部實(shí)現(xiàn)充分考慮多線程環(huán)境,確保在高并發(fā)場(chǎng)景下對(duì)象池操作的線程安全性,無(wú)需開發(fā)者額外進(jìn)行復(fù)雜的同步處理。
定義 ObjectMapper 對(duì)象工廠
public class ObjectMapperFactory implements PooledObjectFactory<ObjectMapper> {
@Override
public ObjectMapper create() throws Exception {
return new ObjectMapper();
}
@Override
public PooledObject<ObjectMapper> wrap(ObjectMapper objectMapper) {
return new DefaultPooledObject<>(objectMapper);
}
@Override
public void destroyObject(PooledObject<ObjectMapper> pooledObject) throws Exception {
// 若ObjectMapper有資源清理操作,可在此執(zhí)行,一般無(wú)需特殊處理
}
@Override
public boolean validateObject(PooledObject<ObjectMapper> pooledObject) {
return pooledObject.getObject() != null;
}
@Override
public void activateObject(PooledObject<ObjectMapper> pooledObject) throws Exception {
// 激活對(duì)象時(shí)的操作,通常無(wú)需特殊處理
}
@Override
public void passivateObject(PooledObject<ObjectMapper> pooledObject) throws Exception {
// 鈍化對(duì)象時(shí)的操作,如重置ObjectMapper配置,一般無(wú)需特殊處理
}
}create方法負(fù)責(zé)創(chuàng)建新的ObjectMapper實(shí)例。wrap方法將創(chuàng)建的對(duì)象包裝成PooledObject,便于common-pool2管理。destroyObject定義對(duì)象銷毀邏輯,對(duì)于ObjectMapper一般無(wú)需特殊清理。validateObject用于驗(yàn)證對(duì)象是否可用,這里通過(guò)簡(jiǎn)單的序列化操作進(jìn)行判斷。activateObject和passivateObject分別處理對(duì)象激活和鈍化時(shí)的操作,通常情況下保持默認(rèn)即可。
配置并使用 ObjectMapper 對(duì)象池
public class ObjectMapperPool {
private static final GenericObjectPool<ObjectMapper> objectMapperPool;
static {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
// 設(shè)置對(duì)象池參數(shù)
config.setMaxTotal(20); // 最大對(duì)象數(shù)
config.setMaxIdle(10); // 最大空閑對(duì)象數(shù)
config.setMinIdle(5); // 最小空閑對(duì)象數(shù)
config.setBlockWhenExhausted(true); // 當(dāng)池耗盡時(shí),請(qǐng)求線程是否阻塞等待
config.setMaxWaitMillis(3000); // 最大等待時(shí)間(毫秒)
ObjectMapperFactory factory = new ObjectMapperFactory();
objectMapperPool = new GenericObjectPool<>(factory, config);
}
public static ObjectMapper borrowObjectMapper() {
try {
return objectMapperPool.borrowObject();
} catch (Exception e) {
throw new RuntimeException("Failed to borrow ObjectMapper", e);
}
}
public static void returnObjectMapper(ObjectMapper objectMapper) {
objectMapperPool.returnObject(objectMapper);
}
}- 通過(guò)靜態(tài)代碼塊配置
GenericObjectPoolConfig,設(shè)置對(duì)象池的關(guān)鍵參數(shù),如最大對(duì)象數(shù)、空閑對(duì)象數(shù)等,以適應(yīng)不同的業(yè)務(wù)場(chǎng)景和系統(tǒng)資源情況。 - 基于配置和
ObjectMapperFactory創(chuàng)建GenericObjectPool實(shí)例,用于管理ObjectMapper對(duì)象。 borrowObjectMapper方法從對(duì)象池中獲取ObjectMapper對(duì)象,若獲取失敗則拋出異常。returnObjectMapper方法將使用完畢的對(duì)象歸還到對(duì)象池。
最終版
在Java中,枚舉類型天然是線程安全的,并且在類加載時(shí)就會(huì)完成實(shí)例化,保證了單例的唯一性。
@Getter
public enum ObjectMapperInstance {
INSTANCE;
private final ObjectMapper objectMapper = new ObjectMapper();
ObjectMapperInstance() {
}
}























