【代码优化】PAY:移除 PayClient 缓存,减少复杂性,性能足够(非高频读取)

pull/123/MERGE
YunaiV 2024-07-24 23:03:59 +08:00
parent c0df6eab4e
commit f717c0f9c6
6 changed files with 25 additions and 49 deletions

View File

@ -2,10 +2,12 @@ package cn.iocoder.yudao.framework.web.core.handler;
import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.JakartaServletUtil; import cn.hutool.extra.servlet.JakartaServletUtil;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService; import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.common.util.collection.SetUtils;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
@ -222,8 +224,17 @@ public class GlobalExceptionHandler {
// 不包含的时候,才进行打印,避免 ex 堆栈过多 // 不包含的时候,才进行打印,避免 ex 堆栈过多
if (!IGNORE_ERROR_MESSAGES.contains(ex.getMessage())) { if (!IGNORE_ERROR_MESSAGES.contains(ex.getMessage())) {
// 即使打印,也只打印第一层 StackTraceElement并且使用 warn 在控制台输出,更容易看到 // 即使打印,也只打印第一层 StackTraceElement并且使用 warn 在控制台输出,更容易看到
StackTraceElement[] stackTrace = ex.getStackTrace(); try {
log.warn("[serviceExceptionHandler]\n\t{}", stackTrace[0]); StackTraceElement[] stackTraces = ex.getStackTrace();
for (StackTraceElement stackTrace : stackTraces) {
if (ObjUtil.notEqual(stackTrace.getClassName(), ServiceExceptionUtil.class.getName())) {
log.warn("[serviceExceptionHandler]\n\t{}", stackTrace);
break;
}
}
} catch (Exception ignored) {
// 忽略日志,避免影响主流程
}
} }
return CommonResult.error(ex.getCode(), ex.getMessage()); return CommonResult.error(ex.getCode(), ex.getMessage());
} }

View File

@ -22,9 +22,9 @@ import java.time.LocalDateTime;
public class PayOrderSyncJob { public class PayOrderSyncJob {
/** /**
* N * N
* *
* 10 * 10
* 10 * 10
* 3060 * 3060
*/ */

View File

@ -14,22 +14,17 @@ import cn.iocoder.yudao.module.pay.convert.channel.PayChannelConvert;
import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO; import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper; import cn.iocoder.yudao.module.pay.dal.mysql.channel.PayChannelMapper;
import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient; import cn.iocoder.yudao.module.pay.framework.pay.core.WalletPayClient;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import jakarta.annotation.PostConstruct; import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import jakarta.validation.Validator; import jakarta.validation.Validator;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import java.time.Duration;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.cache.CacheUtils.buildAsyncReloadingCache;
import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
/** /**
@ -42,25 +37,6 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
@Validated @Validated
public class PayChannelServiceImpl implements PayChannelService { public class PayChannelServiceImpl implements PayChannelService {
/**
* {@link PayClient} smsClientFactory
*/
@Getter
private final LoadingCache<Long, PayClient> clientCache = buildAsyncReloadingCache(Duration.ofSeconds(10L),
new CacheLoader<Long, PayClient>() {
@Override
public PayClient load(Long id) {
// 查询,然后尝试清空
PayChannelDO channel = payChannelMapper.selectById(id);
if (channel != null) {
payClientFactory.createOrUpdatePayClient(channel.getId(), channel.getCode(), channel.getConfig());
}
return payClientFactory.getPayClient(id);
}
});
@Resource @Resource
private PayClientFactory payClientFactory; private PayClientFactory payClientFactory;
@ -102,9 +78,6 @@ public class PayChannelServiceImpl implements PayChannelService {
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO) PayChannelDO channel = PayChannelConvert.INSTANCE.convert(updateReqVO)
.setConfig(parseConfig(dbChannel.getCode(), updateReqVO.getConfig())); .setConfig(parseConfig(dbChannel.getCode(), updateReqVO.getConfig()));
payChannelMapper.updateById(channel); payChannelMapper.updateById(channel);
// 清空缓存
clearCache(channel.getId());
} }
/** /**
@ -135,18 +108,6 @@ public class PayChannelServiceImpl implements PayChannelService {
// 删除 // 删除
payChannelMapper.deleteById(id); payChannelMapper.deleteById(id);
// 清空缓存
clearCache(id);
}
/**
*
*
* @param id
*/
private void clearCache(Long id) {
clientCache.invalidate(id);
} }
private PayChannelDO validateChannelExists(Long id) { private PayChannelDO validateChannelExists(Long id) {
@ -202,7 +163,8 @@ public class PayChannelServiceImpl implements PayChannelService {
@Override @Override
public PayClient getPayClient(Long id) { public PayClient getPayClient(Long id) {
return clientCache.getUnchecked(id); PayChannelDO channel = validPayChannel(id);
return payClientFactory.createOrUpdatePayClient(id, channel.getCode(), channel.getConfig());
} }
} }

View File

@ -23,9 +23,10 @@ public interface PayClientFactory {
* @param channelId * @param channelId
* @param channelCode * @param channelCode
* @param config * @param config
* @return
*/ */
<Config extends PayClientConfig> void createOrUpdatePayClient(Long channelId, String channelCode, <Config extends PayClientConfig> PayClient createOrUpdatePayClient(Long channelId, String channelCode,
Config config); Config config);
/** /**
* Class PayClient * Class PayClient

View File

@ -71,8 +71,8 @@ public class PayClientFactoryImpl implements PayClientFactory {
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <Config extends PayClientConfig> void createOrUpdatePayClient(Long channelId, String channelCode, public <Config extends PayClientConfig> PayClient createOrUpdatePayClient(Long channelId, String channelCode,
Config config) { Config config) {
AbstractPayClient<Config> client = (AbstractPayClient<Config>) clients.get(channelId); AbstractPayClient<Config> client = (AbstractPayClient<Config>) clients.get(channelId);
if (client == null) { if (client == null) {
client = this.createPayClient(channelId, channelCode, config); client = this.createPayClient(channelId, channelCode, config);
@ -81,6 +81,7 @@ public class PayClientFactoryImpl implements PayClientFactory {
} else { } else {
client.refresh(config); client.refresh(config);
} }
return client;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -34,7 +34,8 @@ public class WxNativePayClient extends AbstractWxPayClient {
@Override @Override
protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
// 构建 WxPayUnifiedOrderRequest 对象 // 构建 WxPayUnifiedOrderRequest 对象
WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO); WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO)
.setProductId(reqDTO.getOutTradeNo()); // V2 必须传递 productId无需在微信配置。该参数在 V3 简化,无需传递!
// 执行请求 // 执行请求
WxPayNativeOrderResult response = client.createOrder(request); WxPayNativeOrderResult response = client.createOrder(request);