为了实现提高支付对象的连接效果,我通过使用一个定时器来实现一个AlipayClient的简易连接池,当用户正在使用AlipayClient对象进行支付的时候,通过修改连接对象连接池的对象来达到,别人无法使用的效果,保证了支付对象的一对一性,不会出现在同一个时间段内多人同时使用同一个对象。并且通过AtomicInteger来实现在高并发环境下进行计数,达到限流的操作。希望各位大佬留下你们宝贵的意见,使这个来连接池的效果更加明显。
连接对象的封装:
package org.tamall.payservice.config;
import com.alipay.api.AlipayClient;
import lombok.Data;
/**
* @author Lenovo
*/
@Data
public class PayClientBean {
//alipay对象
private AlipayClient alipayClient;
//是否永久存在(是否为核心对象)
private Boolean isPermanentSurvival;
//连接对象状态(0:存活,1:闲置,2:正在使用,3:回收)
private Integer objectStatus;
//对象创建时间
private long createTime;
public PayClientBean(AlipayClient ac,boolean isPermanentSurvival,Integer state){
this.alipayClient = ac;
this.isPermanentSurvival = isPermanentSurvival;
this.objectStatus = state;
this.createTime = System.currentTimeMillis();
}
}
连接池的简易实现:
package org.tamall.payservice.config;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayConfig;
import com.alipay.api.DefaultAlipayClient;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.Setter;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.tamall.payservice.common.PayClientBeanState;
import org.tamall.payservice.exception.LimException;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* alipay连接对象池
* @author Lenovo
*/
@Configuration
@ConfigurationProperties(prefix = "alipay")
@Setter
@Log4j2
public class PayConfig {
@Resource(name = "createpool")
ThreadPoolTaskExecutor threadPool;
//用来存储alipy客户端的连接对象
private CopyOnWriteArrayList<PayClientBean> coreAlipayClientPool = new CopyOnWriteArrayList<>();
private String netWorkUrl;
private String appId;
//设置私钥
private String privateKey;
//公钥
private String publicKey;
private String format="json";
//设置字符类型
private String chartSet = "UTF-8";
//设置签名类型
private String signType="RSA2";
//链接超时时间
private int connectionTimeOut = 3000;
//读取超时时间
private int readTimeOut = 1500;
//设置连接的存货时间
private int livingTime = 5000;
//设置默认存在的连接数,默认为5
private int permanentSurvivalCount = 5;
//设置最大连接数
private int maxConnectionCount = 15;
//定时回收时间,单位(秒)默认3秒进行一次回收
private long timedRecyclingTime = 3;
//拒绝服务临界值
private int rejectServiceCriticalValue = 25;
//请求个数
private static AtomicInteger count = new AtomicInteger(0);
//设置初始化方法
@PostConstruct
@Operation(description = "初始化方法")
private void init(){
if(rejectServiceCriticalValue < maxConnectionCount){
throw new IllegalArgumentException("拒绝服务临界值必须大于最大连接数总和");
}
System.out.println("=========alipay连接池开始进行加载========");
for (int i = 0; i < permanentSurvivalCount; i++) {
threadPool.submit(()->coreAlipayClientPool.add(
new PayClientBean(createClient(),true,PayClientBeanState.FREE_STATE)
));
}
try{
//启用定时方法
expirationChecker();
}catch (Exception e){
log.error("初始化出现错误");
}
System.out.println("=========alipay连接池加载完成========");
}
public PayClientBean getClient(){
//请求加1,具备线程安全
count.incrementAndGet();
if(count.get() > rejectServiceCriticalValue){
count.decrementAndGet();
log.error("避免服务器压力过载,拒绝返回请求对象");
throw new LimException("避免服务器压力过载,拒绝服务");
}
int listlen = coreAlipayClientPool.size();
ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();
//进行加锁,保证线程安全
lock.lock();
PayClientBean p = null;
/*
判断是否进行阻塞,阻塞条件总的连接数大于等于最大连接数,且所有连接对象处于活动状态
总的连接数 = 缓存连接数 + 生成的连接数
*/
if(listlen >= maxConnectionCount && isAllActive()){
DisarmWait disarmWait = new DisarmWait(condition, lock);
try{
disarmWait.start();
log.info("请求进入等待状态");
condition.await();
}catch (Exception e){
log.error("等待出现错误");
condition.notify();
lock.unlock();
}
}else if(listlen <= maxConnectionCount && querState()){
log.info("返回空闲对象");
for (PayClientBean pa :coreAlipayClientPool){
if(pa.getObjectStatus().equals(PayClientBeanState.FREE_STATE)){
pa.setObjectStatus(PayClientBeanState.ACTIVE_STATE);
p = pa;
break;
}
}
} else {
log.info("创建新对象");
p= new PayClientBean(createClient(),false,PayClientBeanState.ACTIVE_STATE);
coreAlipayClientPool.add(p);
}
lock.unlock();
return p;
}
/**
* 长时间监听集合,并在满足条件后解除等待,停止线程
* */
public class DisarmWait extends Thread{
private final Condition condition;
private final ReentrantLock lock;
public DisarmWait(Condition condition,ReentrantLock lock){
this.condition =condition;
this.lock = lock;
}
@Override
public void run() {
boolean flg = true;
while (flg){
try{
//空余位置,重新创建对象,解除等待
if(coreAlipayClientPool.size() < maxConnectionCount){
log.info("等待结束");
lock.lock();
try {
condition.signal();
}catch (Exception e){
log.error("结束等待出现异常",e);
}finally {
lock.unlock();
}
flg = false;
}else{
//出现空闲对象,解除等待
for (PayClientBean p:coreAlipayClientPool){
if(p.getObjectStatus().equals(PayClientBeanState.FREE_STATE)){
log.info("等待结束");
lock.lock();
try {
condition.signal();
}catch (Exception e){
log.error("结束等待出现异常",e);
}finally {
lock.unlock();
}
flg = false;
}
}
}
}catch (Exception e){
log.error("等待出现错误",e);
flg = false;
}
}
}
}
//所有连接对象是否处于使用状态
public boolean isAllActive(){
for (PayClientBean p : coreAlipayClientPool){
if(p.getObjectStatus().equals(PayClientBeanState.ACTIVE_STATE)){
return true;
}
}
return false;
}
//查询对象状态是否为正在使用,如果是返回true,不是返回false
private boolean querState(){
for (PayClientBean p : coreAlipayClientPool){
if(p.getObjectStatus().equals(PayClientBeanState.FREE_STATE)){
return true;
}
}
return false;
}
//对象归还器
public synchronized void returnObject(PayClientBean p){
int index = coreAlipayClientPool.lastIndexOf(p);
/*
只要不对PayClientBean对象的equal方法进行重写,那么即使创建了一个新的对象,
也不会在列表中找到对应的索引
*/
if(index ==-1){
log.error("对象不存在于集合中");
throw new RuntimeException("传入非集合中的对象");
}
//归还时减少请求数
count.decrementAndGet();
//刷新一次创建时间
coreAlipayClientPool.get(index).setCreateTime(System.currentTimeMillis());
coreAlipayClientPool.get(index).setObjectStatus(PayClientBeanState.FREE_STATE);
}
@Operation(description = "过期检查器,定时进行回收,不可以被继承和重写")
private synchronized void expirationChecker(){
ScheduledExecutorService scheduledExecutorService= null;
try{
scheduledExecutorService = Executors.newScheduledThreadPool(1);
Runnable task = ()->{
coreAlipayClientPool.forEach(e->{
//检查是否位空闲状态和非缓存连接,并且已经过期
if(e.getObjectStatus().equals(PayClientBeanState.FREE_STATE)
&& e.getIsPermanentSurvival().equals(false)
&& System.currentTimeMillis() - e.getCreateTime() >= livingTime){
log.info("创建时间,{},当前时间,{}",e.getCreateTime(),System.currentTimeMillis());
log.info("回收完成一个支付连接客户端对象!");
coreAlipayClientPool.remove(e);
}
});
};
//每两分钟执行一次
scheduledExecutorService.scheduleWithFixedDelay(task ,0,timedRecyclingTime, TimeUnit.SECONDS);
}catch (Exception e){
log.error("创建ScheduledExecutorService出现异常",e);
if(Objects.isNull(scheduledExecutorService)){
scheduledExecutorService.shutdown();
}
}
}
// 用来创建AlipayClient的方法
@Operation(description = "用于创建一个新的AlipayClient实例对象")
private AlipayClient createClient() {
AlipayConfig ap = new AlipayConfig();
ap.setAlipayPublicKey(publicKey);
ap.setCharset(chartSet);
ap.setAppId(appId);
ap.setConnectTimeout(connectionTimeOut);
ap.setFormat(format);
ap.setReadTimeout(readTimeOut);
ap.setSignType(signType);
ap.setServerUrl(netWorkUrl);
ap.setPrivateKey(privateKey);
ap.setConnectTimeout(connectionTimeOut);
DefaultAlipayClient defaultAlipayClient =null;
try{
defaultAlipayClient = new DefaultAlipayClient(ap);
}catch (Exception e){
log.error("创建连接对象出现错误",e);
}
return defaultAlipayClient;
}
}