0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

案例参考:一个Java高并发异步应用

如意 来源:CSDN 作者:finethere 2020-06-20 09:16 次阅读

在日常运营中,公众号会通过给用户下发营销或者科普类的消息来通知客户。 根据经验,微信消息下发后10分钟后流量会逐步上升,30分钟左右到达峰值,1个小时后会显著下降。在这个时间段内,系统的压力会很大。

在系统设计和改进中,系统的很多场景使用异步进行实现,一方面能缩短主流程的时间处理,另一方面能够通过异步队列进行一定程度的削峰。今天重点介绍单个JVM内的异步优化实践,不涉及分布式时的异步优化实践。在异步执行时,可以调用远程的服务集群来实现一定的任务分解。

部署示意图

案例参考:一个Java高并发异步应用

整个系统都部署在公有云上,虚拟机上有部署1个Nginx,4个Tomcat,Nginx使用随机的方式负载均衡到Tomcat上面。虚机之间通过LB将客户请求转发到Nginx上面负载均衡,Nginx再将请求分配到tomcat应用服务器上。

由多台应用服务器,对外服务提供Rest服务,在每个Tomcat内部使用异步队列。同时由一台控制服务器,进行异步任务的补偿任务和管理功能。Tomcat和Redis使用多级缓存来降低对Redis的压力,并减少依赖。

为什么要在虚机上部署Nginx将请求转发到Tomcat,而不是由LB直接转发到Tomcat。这是因为LB能够支持的IP个数是有限的。

典型的用户场景

在公众号的运营过程中,典型的事件包括:

发送短信验证码

购买成功或者抽奖成功短信通知

卡券或优惠券发放

发放微信红包

微信消息通知

订单流程处理

定时批处理(比如数据同步)

工作流性质的异步任务(未完成异步任务补偿)

面详细说明不同场景能够异步的原因:

不同场景(用户注册,用户购买产品等)下的短信验证码发送,可以使用异步方式发送: 一方面是因为客户这个时效性要求没有那样高,另一方面在特定时间范围内用户没有收到验证码,用户可以点击再次发送验证码。

购买成功或者抽奖成功后短信或者邮件通知,可以通过异步的方式进行。 因为涉及用户的利益,要谨慎对待。一方面一定要把数据先存到数据库或者日志里面(注意信息安全^-^,别存敏感明文信息或者加密存储),然后再放入到异步队列中执行。

另一个方面,要考虑到应用服务意外停止时,没有发送成功数据的补偿机制。 这种情况不常见,并且为了减少耦合和当前异步程序的复杂度。我们使用单独的服务上部署异步任务补偿程序,来扫描未完成的任务,并且进行重放(一定要注意严谨性)。

优惠券和卡券的发放,跟购买成功或抽奖成功的方式类似。\u000b可以在当前活动高峰后延时发放,并且使用异步的方式进行。

微信红包,因为需要跟微信进行交互,并且微信会通知客户红包的情况,可以使用异步的方式进行。 当涉及资金或者礼品时,一定要谨慎对待设计,并且需要有方便进行异步任务停止和启动的功能。

微信消息通知,因为跟微信进行交互,成功后微信进行通知,可以使用异步。 这个跟短信验证码类似。

订单流程处理,可以使用异步,因为涉及到后续步骤可以使用简单工作流来完成。有几个开源的框架可以参考。

数据同步或者异步任务补偿,因为是延时处理,可以使用异步进行处理。在使用时,可以配合定时任务,比如cron4j来周期性的进行补偿。适合后面总-分-总的任务处理模式。

针对这些“无处不在的异步”,后面详细分析其内在模型。

无处不在的异步

下图包含了4种典型的异步队列模型(图片来源于网络):

案例参考:一个Java高并发异步应用

一个生产者生产数据,一个消费者消费数据,一般用在后台处理的业务逻辑中。

一个生产者生产数据,多个消费者消费数据(这里面有两种情况:同一个消息,可以被多个消费者分别消费。或者多个消费者组成一个组,一个消费者消费一个数据)。

多个生产者生产数据,单个消费者消费数据,可以用在限流或者排队等候单一资源处理的场景中。

多个生产者分别生产数据,多个消费者消费数据(这里面有两种情况:同一个消息,可以被多个消费者分别消费。或者多个消费者组成一个组,一个消费者消费一个数据)。

案例参考:一个Java高并发异步应用

总分总任务模型:特别适第一个线程取出一批数据放到队列中(比如select);由多个线程分别执行业务逻辑;执行后的结果由一个线程来执行(比如update操作,这样能够防止数据库锁)

这是从技术上分析的几种常见模型,在实践中涉及怎样选择框架。

使用堵塞队列的线程池

使用固定步长或固定时间的队列

使用Disruptor

使用MQ或Kafka

使用线程池实现异步 (支持多生产者,多消费者)

案例参考:一个Java高并发异步应用

特点:可以使用JDK自带的线程池实现异步,编程简单,资料多。建议在并发量小的场景下优先选择。

使用Guava Queues (支持多生产者单消费者)

案例参考:一个Java高并发异步应用

特点:异步批量队列,在队列到达指定长度,或者到达指定时间后,批量进行数据处理。适合于对响应时间要求低,能够容忍一定的数据丢失的场景。比如短小文本数据的批量保存。

在经过一段时间调研后,我们发现Disruptor更能满足我们需要。

首先介绍一下Disruptor的强悍的性能。

案例参考:一个Java高并发异步应用

这张图包含我列举的上述的异步队列模型景,因此很有代表意义。Disruptor因为使用无锁的队列方式,具有很高的性能。具体的原理不详述,大家可以搜索看到。Disruptor支持上面典型场景,并且灵活使用Disruptor的工作流机制,能简化编程。

再贴一下官方的测试结果。

案例参考:一个Java高并发异步应用

使用异步后的烦恼

烦恼一: 数据丢失的风险

解决方式:先写日志或数据库,后放入异步队列。

烦恼二:对其他系统的压力变大

解决方式:使用一定的限流和熔断,对其他系统进行保护。

烦恼三:数据保存后异步任务未执行

解决方式:使用异步任务补偿的方式,定期从数据库中获取数据,放到队列中进行执行,执行后更新数据状态位。

烦恼四:怎样队列长设置和消费者数量

解决方式:使用实际的压力测试来获得队列长度。或者使用排队论的数学公式得到初步的值,然后进行实际压测。

最后介绍一下项目中的经验:

量力而行:根据业务特点进行技术选型,业务量小尽量避免使用异步。有所为,有所不为

数据说话:异步时一定要进行必要的压力测试

先找出系统的关键点:优化单体系统内的性能,再通过整体系统分解来全局优化

根据团队和项目的特点选择框架。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • JAVA
    +关注

    关注

    19

    文章

    2903

    浏览量

    102940
  • 异步
    +关注

    关注

    0

    文章

    60

    浏览量

    17995
收藏 人收藏

    评论

    相关推荐

    HarmonyOS如何使用异步并发能力进行开发

    一、并发概述 并发是指在同一时间段内,能够处理多个任务的能力。为了提升应用的响应速度与帧率,以及防止耗时任务对主线程的干扰,HarmonyOS系统提供了异步并发和多线程
    的头像 发表于 02-18 09:18 278次阅读

    从服务端视角看并发难题

    `所谓服务器大流量并发指的是:在同时或极短时间内,有大量的请求到达服务端,每个请求都需要服务端耗费资源进行处理,并做出相应的反馈。 从服务端视角看并发服务端处理请求需要耗费服务端的
    发表于 11-02 15:11

    java异步回调和同步回调

    java异步回调和同步回调 最近,在准备有关Java并行流的讨论时,我注意到经典文章“ 免费午餐结束 ”(TFLiO)已经过了十岁生日。 对于大多数程序员而言,本文及其伴随的宣传是他们的第一个
    发表于 07-28 08:36

    详细介绍了Java泛型、注解、并发编程

    介绍了Java泛型、注解、并发编程、数据传输与序列化、高效IO、容器集合、反射与类加载以及JVM重点知识线程、内存模型、JVM运行时内存、垃圾回收与算法、Java中四种引用类型、GC 分代收集算法
    发表于 08-20 06:09

    如何去实现种基于SpringMVC的电商并发秒杀系统设计

    参考博客Java并发秒杀系统API目录业务场景要解决的问题Redis的使用业务场景首页倒计时秒杀活动,抢购商品要解决的问题并发下库存的控
    发表于 01-03 07:50

    如何使用多线程和异步操作等并发设计方法来最大化程序的性能

    的DMA操作。  线程的本质  线程不是计算机硬件的功能,而是操作系统提供的种逻辑功能,线程本质上是进程中并发运行的代码,所以线程
    发表于 08-23 16:31

    HarmonyOS如何使用异步并发能力进行开发

    并发概述 并发是指在同时间段内,能够处理多个任务的能力。为了提升应用的响应速度与帧率,以及防止耗时任务对主线程的干扰,HarmonyOS系统提供了
    发表于 09-22 17:35

    Java并发程序设计教程

    Java并发程序设计教程
    发表于 03-19 11:23 2次下载

    Java并发编程实战

    Java并发编程实战
    发表于 03-19 11:24 7次下载

    详解java并发机制

    在一般性开发中,笔者经常看到很多同学在对待java并发开发模型中只会使用一些基础的方法。比如Volatile,synchronized。像Lock和atomic这类高级并发包很多人并不
    发表于 09-27 14:31 0次下载

    java并发编程实战之辅助类用法

    Java并发编程:CountDownLatch、CyclicBarrier和Semaphore2017-09-18 13:07程序设计/58 在java 1.5中,提供了一些非常有用的辅助类来帮助
    发表于 09-27 16:50 0次下载

    JAVA并发编程实践

    JAVA并发编程实践资料免费下载。
    发表于 06-01 15:31 14次下载

    Java并发编程的艺术

    Java并发编程的艺术说明。
    发表于 06-01 15:31 16次下载

    Kali Linux安装Java 安装显卡驱动 安装网卡补丁 并发线程限制 电源优化

    Kali Linux安装Java 安装显卡驱动 安装网卡补丁 并发线程限制 电源优化安装Java安装Java
    发表于 01-06 16:18 0次下载
    Kali Linux安装<b class='flag-5'>Java</b> 安装显卡驱动 安装网卡补丁 <b class='flag-5'>并发</b>线程限制 电源优化

    java redis锁处理并发代码

    问题。 本文将详细介绍如何在Java代码中使用Redis实现并发代码的锁处理。我们将分为以下几个方面来讨论: Redis分布式锁的原理 Redis分布式锁的实现方式 在Java中使用Redis分布式锁的代码示例 Redis分布式
    的头像 发表于 12-04 11:04 276次阅读