总结:记一次transfer服务并发优化经验

一、背景

业务反馈Java的Transfer服务有调用超时情况。

二、问题排查与优化

阅读代码发现,数据来了之后,循环处理,消息放到本地队列,是同步的方式,这里并发肯定会影响性能,果断优化;

三、优化过程

四、经验总结

1、尽量减少IO操作

    尤其是网络IO,尤其是在for循环中使用网络IO,如果必须要使用,考虑使用缓存替代。

  • 案例一:本次调用hbs获取uuid,其实可以从DB获取,只有获取不到的情况才从接口获取;这个调用接口问题也是服务慢的最主要原因,每次请求如果list的size是1000,且不带uuid,那么就要访问1000次接口,怎么快?
  • 案例二:循环中会往kafka投递数据,这个也是网络IO,可能比调用hbs快很多,但是还是网络IO,还是影响性能的,所以后面改成了本地IO,并使用基于乐观锁的ConcurrentLinkedQueue。

2、异步处理

    业务如果不关心服务响应内容,可考虑将接口修改成异步,这样业务的请求立即返回,服务端需要考虑的就是如何快速处理服务。

    如本次优化,异步后最起码可以解决客户端等待问题,避免由于服务端问题影响客户端

3、NIO理念,分段处理,减少等待

    先说下优化之后的逻辑(分四段处理),每一段一个线程池,每个线程池用不同的名称,方便观察:

  • --》接收请求,多线程异步处理
  • --》循环中往ConcurrentLinkedQueue添加数据的时候,采用多线程异步(虽然乐观锁,但是也会碰到自旋情况)
  • --》新增个定时任务,一秒钟一次消费ConcurrentLinkedQueue的数据,并将数据放到list
  • --》多线程处理,当list达到200时,push到kafka

然后对每一段的线程池的缓冲队列增加监控,观察哪一步有积压,说明那一步可能比较慢,可以适当增加线程的数量。

4、第三方缓存与本地缓存合理使用

    本地缓存

        优点:速度快,不需要经过建立远程连接,网络传输过程等消耗;

        缺点:占用本地内存,当系统处理速度慢的时候,造成本地数据积压,从而消耗本地内存,导致频繁的GC

    第三方缓存 

        优点:不占用本地缓存

        缺点:速度慢,需要经过建立远程连接,网络传输过程等消耗;

    本系统采集两种方式结合:在offer数据的时候使用本地ConcurrentLinkedQueue存储,消费ConcurrentLinkedQueue数据投递到平台服务端的时候使用kafka进行缓冲,使用flink进行消费kafka数据发送到平台服务端。

为什么这么做呢?

1、在offer数据的时候使用本地ConcurrentLinkedQueue存储,主要考虑这种数据消费起来比较快,不会造成本地积压;

2、投递到平台服务,由于是要建立http连接,有可能受到此服务稳定性的影响,所以为了保障本服务的稳定性,使用flink做这个事情。

5、计算密集型服务与IO密集型服务分离

    合理申请相关配置咨询,提高并发能力。

    本服务是两种操作都有,如循环遍历的时候是计算密集型;

    将数据推送到远端是网络IO密集型,如果放到一个服务,尤其是一个线程逻辑的时候很容易造成等待,所以此处需要分离,然后对于计算密集型的,申请cpu性能好的,对于IO密集型的选择磁盘或者网卡好的

    计算机的并发瓶颈怎么估算?

    对于一个2GHZ的CPU,运输速度是20亿次/秒,意味着如果是纯CPU密集型操作,对于简单的请求,理论上能达到20亿次并发,当然这当然是不可能的,因为网络请求还有很多因素的影响,如线程切换消耗,网络IO开销,连接建立过程等,仅供评估使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值