本文转载自微信公众号「程序新视界」,作者二师兄。转载本文请联系程序新视界公众号。
当你打开本文,首先想说的是,这篇文章不仅仅是在讲一个知识点,更重要的是在讲一种学习方法:质疑与求证。
前言
最近在研究Spring Boot的异步处理,准备写一篇文章。在搜集资料时发现一篇文章《SpringBoot中异步请求和异步调用》,以及许多它的衍生文章。文章的确不错,但文章中提到的“异步请求和异步调用”这两个概念,一直百思不得其解,衍生文章中也是在混着用。
终于忍不住想探究一番,发现除了那篇文章和衍生的文章之外,并没有其他证据来区别这两个概念。直到在Stack Overflow上搜到了一篇七年前的文章,这个疑惑才解开。
今天就带大家一起探究一下“异步请求和异步调用”这两个概念。
异步请求和异步调用的区别
上面提到的文章中有这样两段话来讲异步请求和异步调用的区别:
区别一:异步请求用来解决并发请求对服务器造成的压力,从而提高对请求的吞吐量;而异步调用是用来做一些非主线流程且不需要实时计算和响应的任务,比如同步日志到kafka中做日志分析等。
区别二:异步请求是会一直等待response相应的,需要返回结果给客户端的;而异步调用往往会马上返回给客户端响应,完成这次整个的请求,至于异步调用的任务后台运行就可以了,客户端不会关心。
仔细阅读和分析之后,文章中提到的异步请求应该指的是通过Servlet的AsyncContext对象或Spring中的Callable、DeferredResult、WebAsyncTask等方式进行业务的异步处理。而文中异步调用指的是类似在Spring中调用@Async注解的异步方法。
你看了上面的两个概念的区别,是否觉得很有道理?感觉已经成功区分了异步请求和异步调用了吗?
那么,是否想过一个问题,我们通常说请求一个接口和调用一个接口时难道不是一个意思吗?怎么在这里就变成两个截然不同的概念了?
疑问探究
带着上面的疑问,开始用搜索引擎进行搜索。发现当搜索“异步请求和异步调用的区别”时,搜出来的内容基本上都来自上述文章及衍生文章,或者是讲异步和同步的区别。这并不能说明什么,但也说明了这两个概念的区别并没有得到普遍的认可。
于是开始尝试通过英文搜索引擎进行搜索。先搜了“the difference between asynchronous call and asynchronous request”,没有想要的结果,大多数文章还是讲异步和同步的区别。
改变关键字搜“the difference between asynchronous call and asynchronous method”,结果一样,并没有想要的文章。但却搜出了一个Stack Overflow上的关联问题“Synchronous Vs Asynchronous related to web services”。
在该问题的下面出现了两个词组:Asynchronous service和Asynchronous calls。再仔细看两个词组的解释,发现正是想要的结果。
异步调用与异步服务
其实在英文搜索的过程中已经发现了,探讨异步与同步的区别时,经常会出现asynchronous request和asynchronous call这两个词组,而且它们都是在讲异步与同步的区别,而没有讲它们两个的区别。所以无论异步调用还是异步请求本质上是一回事。
而《SpringBoot中异步请求和异步调用》一文中所说的异步请求和异步调用的区别,概念上也并没有说清楚什么是异步请求,什么是异步调用。而且只有那几篇文章这么讲,所以可以认为异步请求和异步调用是同一个概念(asynchronous call)。而作者所讲的“异步调用”指的应该异步服务(Asynchronous service)。
为了进一步证明上面的结论,下面将问答中对两个概念的解释简单翻译一下。
Asynchronous service和Asynchronous calls
Asynchronous service
当你的web服务执行需要耗费大量时间,比如从文件系统中读取一个大文件。此时,如果你使用“同步”的web服务,那么客户端必须等待处理完成,通常会阻塞线程,对于高并发的服务,会出现性能问题。
如果将web服务设置为异步服务,那么可以把耗时服务委托给另外一个线程,或者使用非阻塞机制,在未来的某刻进行返回。还以读取大文件为例,可以使用异步的ReadFile方法来读取大文件。这样便能避免线程阻塞,提高吞吐量。
Asynchronous calls
值得注意的是:你可以通过异步的方式调用一个非异步的的服务。比如在JavaScript中的Ajax的调用:
- var jqxhr = $.ajax( "AnyService.svc" )
- .done(function() { alert("success"); })
- .fail(function() { alert("error"); })
- .always(function() { alert("complete"); });
- alert("Called");
执行上述示例,首先展示“Called”,然后展示“success”,因为执行的过程中并不需要等到服务返回的结果。而被调用的服务也不需要是异步的。
总之,服务实现的异步与同步特性完全独立于客户端调用的异步和同步特性。也就是说客户端可以异步的去调用同步服务,而且客户端也可以同步的去调用异步服务。
小结
通过上面的追踪分析,关于异步请求和异步调用我们可以理解为是一回事,同时我们还得知了所谓的客户端异步和同步与服务的异步与同步是相互独立的。也就是客户端可以异步请求也可以同步请求,服务可以异步处理也可以同步处理。两两组合可以有四种情况。
另外,更重要的是我们要学会通过搜索中英文资料来解答自己心中的疑惑,而且英文资料相对更准确一些,所以首推英文。在探索疑惑问题的过程中往往还能有不少意外的收获。