智能停车平台线上系统优化处理总结

春节前我们智能停车平台出现,用户支付成功通知停车能力提供平台延时较高,最大达到了5分钟,造成车场车辆积压严重,客诉很严重。

出现的问题上面描述了,先整体说明一下智能停车的线上支付整体流程;

  • 1.车辆入场
    • 1.1用户车辆进入车场,停车场本地系统拍照抬竿;
    • 1.2停车场本地系统通知停车能力提供方线上平台,该车辆入场;
    • 1.3停车能力提供方线上平台调用飞凡停车服务同步入场信息;
  • 2.用户缴费
    • 2.1用户开启应用查费
      • 2.1.1智能停车平台调用停车能力提供方车辆信息接口,查询车辆在场和费用信息;
    • 2.2 用户创建订单
      • 2.2.1 智能停车平台调用停车能力提供方查费接口,查询确认当前车费;
      • 2.2.2 智能停车平台调用停车能力提供方创建订单接口,创建外部订单;
      • 2.2.3 智能停车平台调用交易平台接口创建本平台订单;
    • 2.3 用户进入收银台进行支付
      • 2.3.1 用户支付完成,交易平台获得支付完成信息,通知加入消息队列
      • 2.3.2 智能停车平台监听消息队列,获得支付成功消息;
      • 2.3.3 智能停车平台将支付信息同步给停车能力提供方订单通知接口;
  • 2.3 用户离场
    • 2.3.1 用户车辆驶离车场,本地岗亭识别车牌,调用停车能力提供方线上平台查询支付状态
    • 2.3.2 抬竿出场

这个问题出现在2.3流程。当时消息队列消费情况如下图:

消息队列情况

消费延时情况

发现消费延时较大,完全来不及消费里面的支付消息。

经过排查代码发现是单线程消费消息队列,通知逻辑是串行的,效率可想而知,另外由于停车能力提供方接口响应也较慢,平均响应时间将近300毫秒,因此单线程每秒钟最多通知3笔订单。

由于临近春节,不便修改代码,一开始想到的解决方案是扩容,但分析下来由于消费支付消息队列使用的是kafka,这个topic只有4个partition,而每个partition智能由1个线程进行消费,而支付系统与消息队列耦合较大,无法进行扩容,因此该方案不具操作性。

那么只能第二条路,优化代码逻辑。优化策略是使用线程池进行能力提供方的支付通知;

由于消费partition的线程只能单一,因此消费线程暂时无法优化,而通知线程进行线程池优化。代码如下:

//线程池队列
private LinkedBlockingDeque<Runnable> linkedBlockingDeque;
//通知线程池
private ThreadPoolExecutor notifyExecutor;
//消息队列消费状态
private volatile boolean isRun;

if(null == notifyExecutor){
	linkedBlockingDeque = new LinkedBlockingDeque<Runnable>(8);
	notifyExecutor  = new ThreadPoolExecutor(8, 32, 20L,
			TimeUnit.SECONDS, linkedBlockingDeque, new ThreadPoolExecutor.CallerRunsPolicy());
	isRun = true;
}

由于线上服务器cpu核数为8,因此core线程数定义为8,然而通知能力方接口延时较长,并没有完全消耗cpu资源,因此最大线程数定义为32,当线程和队列都满情况下,有新任务加入,使用CallerRunsPolicy策略,即调用线程本身执行该任务。

改造后需考虑服务重启无法处理已消费消息的情况,而应用是基于tomcat的,因此需要注册事件通知:

@Component
public class MessageConsumerLauncher implements ApplicationListener<ApplicationEvent> {

	private static final Logger logger = LogManager.getLogger(MessageConsumerLauncher.class.getName());

	@Autowired
	private OrderStatusMessageReceiver orderStatusMessageReceiver;

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		logger.info("MessageConsumerLauncher.onApplicationEvent ContextRefreshedEvent "
				+ event.getSource().toString() + "; " + event.getClass().getName());
		if(event instanceof ContextClosedEvent){
			try {
			logger.info("MessageConsumerLauncher.onApplicationEvent.orderStatusMessageReceiver stopping...");
				orderStatusMessageReceiver.stopReceiver();
				logger.info("MessageConsumerLauncher.onApplicationEvent.orderStatusMessageReceiveron.ApplicationEvent() stopping...");
			} catch (Exception e) {
				logger.error(e.getStackTrace());
			}
		}
	}
}

stopReceiver的逻辑为:

public void stopReceiver(){
        logger.info("stop begin OrderStatusMessageReceiver threadPool...........");
        if(null != threadPool) {
            isRun = false;  //状态置为partition消费关闭
            threadPool.shutdown(); //关闭partition消费线程池(只有1个线程)
        }
        logger.info("stop end OrderStatusMessageReceiver threadPool...........");

        logger.info("stop begin OrderStatusMessageReceiver threadPool...........");
        if(null != notifyExecutor){
            notifyExecutor.shutdown(); //关闭通知线程池
        }
        logger.info("stop end OrderStatusMessageReceiver threadPool...........");
    }

当notifyExecutor执行完剩余任务,应用关闭。

经过上面改造进在测试环境进行压测,由于测试环境使用4cpu,4G内存,生产环境使用8cpu,8G内存。测试结果如下:

压测结果

效率有将近12倍的提升,完全达到系统要求。

转载于:https://my.oschina.net/tree/blog/1622621

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值