当前位置: 首页 > news >正文

真正理解Java中的异步

何为异步?

首先必须强调一个基础概念,异步是一种设计方式,异步操作不等于多线程。异步处理不用阻塞当前线程来等待处理完成,而是允许后续操作,直至其它线程将处理完成,并回调通知此线程。注:不是所有的异步都需要回调,异步通常处理 I/O 场景,即读写。读当然需要回调,不然干嘛读?可写就不必回调啦。所以,有一半场景需要回调,另一半则不需要。

同步处理和异步处理相对,需要实时处理并响应,一旦超过时间会结束会话,在该过程中调用方一直在等待响应方处理完成并返回。举个不恰当的例子:同步就像最初的快递,快递小哥给你打电话得等你本人来后亲自签收;异步则是使用快递站点的模式,快递到后快递小哥给你发个短信告知你到哪取、取件码多少,收到短信后按短信内容去相应站点取你的快递就行了。

异步处理的实现方式有很多种,常见多线程,消息中间件,发布订阅的广播模式,其根本逻辑在于先把请求承接下来,放入存储容器中,在从容器中把请求取出,统一调度处理。

使用异步的优劣

  • 异步可以解耦业务间的流程关联,降低耦合度;
  • 降低接口响应时间,例如用户注册,异步生成相关信息表;
  • 异步可以提高系统性能,提升吞吐量;
  • 流量削峰即把请求先承接下来,然后在异步处理;
  • 异步用在不同服务间,可以隔离服务,避免雪崩;

异步处理模式

异步流程处理的实现有很多方式,但是实际开发中常用的就那么几种,例如:

  • 基于接口异步响应,常用在第三方对接流程;
  • 基于消息生产和消费模式,解耦复杂流程;
  • 基于发布和订阅的广播模式,常见系统通知

注:异步适用的业务场景,对数据实时性、强一致性的要求不高,异步处理的数据更多时候追求的是最终一致性。关于“最终一致性有空在给大家介绍”。

与第三方对接

请添加图片描述

大致流程如下:

  1. 地服务发起请求,调用第三方服务接口;
  2. 请求包含业务参数,和成功或失败的回调地址;
  3. 第三方服务实时响应流水号,作为该调用的标识;
  4. 之后第三方服务处理请求,得到最终处理结果;
  5. 如果处理成功,回调本地服务的成功通知接口;
  6. 如果处理失败,回调本地服务的失败通知接口;

注:如果本地服务多次请求第三方服务,需要根据流水号判断该请求的状态,业务的状态设计也是极其复杂,要根据流水号和状态追溯整个流程的执行进度,避免错乱。(保证请求一致性,避免相同请求数据重复请求重复处理)

生产消费模式

在这里插入图片描述

  1. 消息生成之后,写入Kafka/MQ队列 ;
  2. 消息处理方获取消息后,进行流程处理;
  3. 消息在中间件提供的队列中持久化存储 ;
  4. 消息发起方如果挂掉,不影响消息处理 ;
  5. 消费方如果挂掉,不影响消息生成;

注:基于这种消息中间件模式,完成业务解耦,提高系统吞吐量,是(分布式)架构中常用的方式。即使有多个消息消费方,也只会在一个消费方处理消息,这就是该模式的特点。

发布订阅模式

在这里插入图片描述

  1. 提供一个消息传递频道channel;
  2. 多个订阅频道的客户端client;
  3. 消息通过PUBLISH命令发送给频道channel ;
  4. 客户端就会收到频道中传递的消息 ;

注:广播模式更注重通知下发,流程交互性不强。实际开发场景:运维总控系统,更新了某类服务配置,通知消息发送之后,相关业务线上的服务在拉取最新配置,更新到服务中。(Nacos使用的就是该种模式)

使用注意

任务积压监控
生成一个消息,就因为有一个处理该消息的任务要执行,这就导致任务可能出现积压的情况,常见原因大致有如下几个:

任务产生的服务过多,任务处理的服务过少,不均衡;
任务处理时间太长,也导致生产过剩;
中间件本身容量偏小,需要扩容或集群化管理;
如果任务积压过多,可能要对任务生成进行流量控制,或者提升任务的处理能力,从而避免雪崩情况。

Spring中使用

Spring管理的异步线程数量有限,如果是web项目的话,线程数量由tomcat的线程池配置有关系,所以最好自己配置线程配置类。
异步回调,异步方法执行完之后,我怎么才能让用户知道我已经调用成功了呢?异步方法返回Future类型的结果对象,然后通过websocket将执行消息发送给用户界面
在生产环境一定要设置合理的超时时间,防止程序无限期等待下去。另外就是要考虑异步任务执行过程中报错抛出异常的情况,需要捕获future的异常信息。Future没有提供通知的机制,就是回调,我们无法知道它什么时间完成任务。

相关文章:

  • 《Unity3D脚本编程与游戏开发》学习Day one
  • JavaScript:JavaScript编程语言学习之前端框架(VUE)架构(MVVM)的简介、案例应用之详细攻略
  • [Python]闭包
  • 《C++程序设计原理与实践》笔记 第5章 错误
  • 静息态fMRI方法在脑动力学表征上的比较
  • LabVIEW自动整理程序框图
  • 拨测API接口+监控方案
  • 第一性原理详解
  • 信息化转型?数字化转型?企业到底该如何选择
  • ES6的Class继承--super关键字
  • Linux 简单命令 - find -grep命令深入学习
  • OP-TEE driver(五):libteec库中的接口在驱动中的实现
  • F-003 FPGA基础配置
  • java-php-python-ssm百分百教育集团教务管理系统设计计算机毕业设计
  • Apple M1 Macos 安装虚拟机软件UTM
  • [nginx文档翻译系列] 控制nginx
  • [译] React v16.8: 含有Hooks的版本
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • Laravel 中的一个后期静态绑定
  • Mocha测试初探
  • MySQL几个简单SQL的优化
  • node.js
  • PHP 7 修改了什么呢 -- 2
  • Python 基础起步 (十) 什么叫函数?
  • quasar-framework cnodejs社区
  • SAP云平台运行环境Cloud Foundry和Neo的区别
  • Service Worker
  • Vue.js 移动端适配之 vw 解决方案
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 浮动相关
  • 浮现式设计
  • 码农张的Bug人生 - 初来乍到
  • 如何在GitHub上创建个人博客
  • 入门级的git使用指北
  • 深度解析利用ES6进行Promise封装总结
  • 移动端 h5开发相关内容总结(三)
  • 再谈express与koa的对比
  • 你学不懂C语言,是因为不懂编写C程序的7个步骤 ...
  • #pragma once与条件编译
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (33)STM32——485实验笔记
  • (C语言)球球大作战
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (二)windows配置JDK环境
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (免费领源码)Java#ssm#MySQL 创意商城03663-计算机毕业设计项目选题推荐
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】
  • (四)Android布局类型(线性布局LinearLayout)
  • (转) Android中ViewStub组件使用
  • (转)LINQ之路
  • (转)负载均衡,回话保持,cookie
  • (转)母版页和相对路径
  • .NET建议使用的大小写命名原则
  • .NET连接MongoDB数据库实例教程
  • .net中生成excel后调整宽度