百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

一个可供参考的Java高并发异步应用案例--转

toyiye 2024-05-25 20:11 24 浏览 0 评论

泰康在线微信公众号系泰康在线财产保险股份有限公司旗下平台,希望可以通过持续不断的创新,提升客户对于保险的认知及体验,通过对大数据技术的应用,精准的为客户设计产品以及提供服务。泰康在线微信公众号,现有1000多万粉丝。在日常的运营中,借助于红包奖励、卡券分享、消息通知、微信分享等手段,通过好的内容,好的活动、好的产品以及相应的精准营销来增强用户的粘性和活跃度。



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

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

部署示意图

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

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

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

典型的用户场景

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

  • 发送短信验证码
  • 购买成功或者抽奖成功短信通知
  • 卡券或优惠券发放
  • 发放微信红包
  • 微信消息通知
  • 订单流程处理
  • 定时批处理(比如数据同步)
  • 工作流性质的异步任务(未完成异步任务补偿)

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

  1. 不同场景(用户注册,用户购买产品等)下的短信验证码发送,可以使用异步方式发送: 一方面是因为客户这个时效性要求没有那样高,另一方面在特定时间范围内用户没有收到验证码,用户可以点击再次发送验证码。
  2. 购买成功或者抽奖成功后短信或者邮件通知,可以通过异步的方式进行。 因为涉及用户的利益,要谨慎对待。一方面一定要把数据先存到数据库或者日志里面(注意信息安全^-^,别存敏感明文信息或者加密存储),然后再放入到异步队列中执行。另一个方面,要考虑到应用服务意外停止时,没有发送成功数据的补偿机制。 这种情况不常见,并且为了减少耦合和当前异步程序的复杂度。我们使用单独的服务上部署异步任务补偿程序,来扫描未完成的任务,并且进行重放(一定要注意严谨性)。
  3. 优惠券和卡券的发放,跟购买成功或抽奖成功的方式类似。\u000b可以在当前活动高峰后延时发放,并且使用异步的方式进行。
  4. 微信红包,因为需要跟微信进行交互,并且微信会通知客户红包的情况,可以使用异步的方式进行。 当涉及资金或者礼品时,一定要谨慎对待设计,并且需要有方便进行异步任务停止和启动的功能。
  5. 微信消息通知,因为跟微信进行交互,成功后微信进行通知,可以使用异步。 这个跟短信验证码类似。
  6. 订单流程处理,可以使用异步,因为涉及到后续步骤可以使用简单工作流来完成。有几个开源的框架可以参考。
  7. 数据同步或者异步任务补偿,因为是延时处理,可以使用异步进行处理。在使用时,可以配合定时任务,比如cron4j来周期性的进行补偿。适合后面总-分-总的任务处理模式。

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

无处不在的异步

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

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

  • 一个生产者生产数据,多个消费者消费数据(这里面有两种情况:同一个消息,可以被多个消费者分别消费。或者多个消费者组成一个组,一个消费者消费一个数据)。
  • 多个生产者生产数据,单个消费者消费数据,可以用在限流或者排队等候单一资源处理的场景中。
  • 多个生产者分别生产数据,多个消费者消费数据(这里面有两种情况:同一个消息,可以被多个消费者分别消费。或者多个消费者组成一个组,一个消费者消费一个数据)。

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

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

  1. 使用堵塞队列的线程池
  2. 使用固定步长或固定时间的队列
  3. 使用Disruptor
  4. 使用MQ或Kafka

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

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

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

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

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

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



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

英文文章入门:https://github.com/LMAX-Exchange/disruptor/wiki/Getting-Started

中文的demo链接:http://my.oschina.net/u/2273085/blog/507735?p=1

并发框架Disruptor相关译文:http://ifeve.com/disruptor/

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

下面从代码层面说明disruptor的几种用法。

使用Disruptor(单生产者多消费者)

Disruptor 提供了多个 WaitStrategy的实现,每种策略都具有不同性能和优缺点,根据实际运行环境的 CPU 的硬件特点选择恰当的策略,并配合特定的 JVM的配置参数,能够实现不同的性能提升。 例如,BlockingWaitStrategy、SleepingWaitStrategy、YieldingWaitStrategy 等,其中:

  • BlockingWaitStrategy 是最低效的策略,但其对CPU的消耗最小并且在各种不同部署环境中能提供更加一致的性能表现;
  • SleepingWaitStrategy 的性能表现跟 BlockingWaitStrategy 差不多,对 CPU的消耗也类似,但其对生产者线程的影响最小,适合用于异步日志类似的场景;
  • YieldingWaitStrategy的性能是最好的,适合用于低延迟的系统。在要求极高性能且事件处理线数小于 CPU逻辑核心数的场景中,推荐使用此策略;例如,CPU开启超线程的特性。

我们现在使用BlockingWaitStrategy这种模式。

使用Disruptor(多生产者多消费者)


使用Disruptor(多生产者多消费者)

这个例子中,使用类似线程池的消费组处理数据。

多步模式工作流:Disruptor

使用异步后的烦恼

烦恼一: 数据丢失的风险

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

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

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

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

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

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

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

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

    • 量力而行:根据业务特点进行技术选型,业务量小尽量避免使用异步。有所为,有所不为
    • 数据说话:异步时一定要进行必要的压力测试
    • 先找出系统的关键点:优化单体系统内的性能,再通过整体系统分解来全局优化
    • 根据团队和项目的特点选择框架。



原文地址:http://chuansong.me/n/355827651252

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码