zoukankan      html  css  js  c++  java
  • 记一次生产上的紧急修复之后解疑过程

    A系统作为调用方,在esb平台调用CBSJK0001接口时,采用的阻塞请求方式。
    B系统身为被调用方,造数逻辑除使用的是同步请求方式。

    因为响应报文的时间超过了29秒,导致esb平台告警。并且A系统因为没有收到响应报文而无法保存数据。

    为了解决这个问题,科技当时建议采用异步请求方式返回响应报文,实现手段是采用多线程方式实现。

    在B系统返回响应报文的这个主线程下,需要另外启用一个线程来处理造数逻辑,所以为了方便管理线程,我们使用了线程池来管理。

    因此牵涉到同步请求、异步请求、多线程的理解问题。

    【1】什么是同步、什么是异步?

    这个解释涉及到调用方A与被调用方B两个对象。

    同步请求,A调用B,B的处理是同步的,在处理完之前他不会通知A,只有处理完之后才会明确的通知A。
    异步请求,A调用B,B的处理是异步的,B在接到请求后先告诉A我已经接到请求了,然后异步去处理,处理完之后通过回调等方式再通知A。
    所以说,同步和异步最大的区别就是被调用方的执行方式和返回时机。同步指的是被调用方做完事情之后再返回,异步指的是被调用方先返回,然后再做事情,做完之后再想办法通知调用方。

    讲完同步与异步之后,进而联系到阻塞与非阻塞请求

    阻塞请求,A调用B,A一直等着B的返回,别的事情什么也不干。
    非阻塞请求,A调用B,A不用一直等着B的返回,先去忙别的事情了。
    所以说,阻塞和非阻塞最大的区别就是在被调用方返回结果之前的这段时间内,调用方是否一直等待。阻塞指的是调用方一直等待别的事情什么都不做。非阻塞指的是调用方先去忙别的事情。

    同步场景会包含阻塞和非阻塞情况
    异步场景也会包含阻塞和非阻塞情况

    Java中的三种IO模型
    在Java语言中,一共提供了三种IO模型,分别是阻塞IO(BIO)、非阻塞IO(NIO)、异步IO(AIO)。
    这里面的BIO和NIO都是同步的IO模型,即同步阻塞IO和同步非阻塞IO,异步IO指的是异步非阻塞IO。
    BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。
    NIO (New I/O):同时支持阻塞与非阻塞模式,但主要是使用同步非阻塞IO。
    AIO (Asynchronous I/O):异步非阻塞I/O模型。

    BIO (Blocking I/O):举个栗子:有一排水壶在烧开水,BIO的工作模式就是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

    NIO (New I/O):NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

    AIO ( Asynchronous I/O):为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。

    【2】怎么实现异步呢?

     首先要理解异步和多线程有什么区别?

    其实,异步是目的,而多线程是实现这个目的的方法。异步是说,A发起一个操作后(一般都是比较耗时的操作,如果不耗时的操作 就没有必要异步了),可以继续自顾自的处理它自己的事儿,不用干等着这个耗时操作返回。

    多线程和异步操作的异同
      多线程和异步操作,两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为多线程和异步操作是等同的概念。但是,多线程和异步操作还是有一些区别的。而这些区别造成了使用多线程和异步操作的时机的区别。
      异步操作的本质
      所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。
    DMA就是直接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。
      线程的本质
      线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。
      异步操作的优缺点
      因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些出入,而且难以调试。
      多线程的优缺点
      多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。
      适用范围
      在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。
      而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往 往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处理大量的并发操作时就不合适了。

    异步调用与多线程
    异步调用并不是要减少线程的开销, 它的主要目的是让调用方法的主线程不需要同步等待在这个函数调用上, 从而可以让主线程继续执行它下面的代码.与此同时, 系统会通过从ThreadPool中取一个线程来执行,帮助我们将我们要写/读的数据发送到网卡.由于不需要我们等待, 我们等于同时做了两件事情. 这个效果跟自己另外启动一个线程来执行等待方式的写操作是一样的.但是, 异步线程可以利用操作系统/.Net的线程池, 系统可以根据吞吐量动态的管理线程池的大小.

    异步与多线程,从辩证关系上来看,异步和多线程并不是一个同等关系,
    异步是目的,多线程只是我们实现异步的一个手段.
    什么是异步:异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回.
    实现异步可以采用多线程技术或者交给另外的进程来处理

    线程池的实现方法与线程是不一样的.
    初始化时在线程池里的线程为0.当进程需要一个线程时,创建一个线程,由此线程执行用户的方法.需要注意的是,此线程执行完后并不立即销毁,而是挂起等待,如果有其他方法需要执行,回唤醒进行处理.只有当它等到40秒(没有官方记录,有可能是其它数字)还没有任务执行时 才唤醒自己,并销毁自己,释放资源.当然,如果线程池中的线程不够处理任务时,会再次创建一个新线程进行执行.
    异步有的时候用普通的线程,有的时候用系统的异步调用功能。

    异步通常用系统线程池的线程,通常情况下性能好些。(因为可以多次利用,申请时不需要重新申请一个线程,只需要从池里取就行了。)
    异步是一种效果,多线程是一种具体技术。可以说,用“多线程”实现“异步”。
    异步和多线程是两个不同的概念,
    不能这样比较.异步请求一般用在IO等耗时操作上,他的好处是函数调用立即返回,相应的工作线程立即返还给系统以供重用。 由于系统的线程资源是非常宝贵的,通常有一定的数目限制。
    若使用异步方式,用这些固定数目的线程在固定的时间内就可以服务更多的请求,
    而如果用同步方式,那么每个请求都自始至终占用这一个线程,服务器可以同时服务的请求数就少了。
    当异步操作执行完成后,系统会从可用线程中选取一个执行回调程序,这时的这个线程可能是刚开始发出请求的那个线程,也可能是其他的线程,因为系统选取线程是随机的事情,所以不能说绝对不是刚开始的那个线程。 多线程是用来并发的执行多个任务。
    不过有个问题,异步有时优先级比主线程还高。这个特点和多线程不同。

  • 相关阅读:
    (笔试题)关于C++的虚函数和多态性
    (笔试题)只用逻辑运算实现乘法运算
    (笔试题)只用逻辑运算实现加法运算
    (C++)浅谈多态基类析构函数声明为虚函数
    (C++)C++多态性中的静态绑定和动态绑定
    (C++)C++类继承中的构造函数和析构函数
    (C++)浅谈using namespace std
    (笔试题)不用除法操作符,实现两个整数的除法
    (笔试题)不用除法操作符,实现两个正整数的除法
    当你学会专注,人生才算真正成熟
  • 原文地址:https://www.cnblogs.com/smallwangmusk/p/9147068.html
Copyright © 2011-2022 走看看