blob: 1372071a8e8c7d4961370404081776960f65ceea [file] [log] [blame]
<!doctype html><html lang=en class=no-js><head><meta name=ROBOTS content="INDEX, FOLLOW"><link rel=canonical href=https://cn.dubbo.apache.org/en/blog/2018/09/02/how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo/><script>var _hmt=_hmt||[];(function(){var e,t=document.createElement("script");t.src="https://hm.baidu.com/hm.js?3b78f49ba47181e4d998a66b689446e9",e=document.getElementsByTagName("script")[0],e.parentNode.insertBefore(t,e)})()</script><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><meta http-equiv=Content-Security-Policy content="frame-src *"><meta name=generator content="Hugo 0.122.0"><link rel="shortcut icon" type=image/png href=/imgs/favicon.png><link rel=apple-touch-icon href=/favicons/apple-touch-icon-180x180.png sizes=180x180><link rel=manifest href=/manifest.webmanifest><title>How to implement a fully asynchronous calls chain based on Dubbo | Apache Dubbo</title><meta property="og:title" content="How to implement a fully asynchronous calls chain based on Dubbo">
<meta property="og:description" content="This article recalls how asynchronous call is implemented in Dubbo 2.6.x, and introduces the new way based on CompletableFuture in 2.7.0.
"><meta property="og:type" content="article"><meta property="og:url" content="https://cn.dubbo.apache.org/en/blog/2018/09/02/how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo/"><meta property="article:section" content="blog"><meta property="article:published_time" content="2018-09-02T00:00:00+00:00"><meta property="article:modified_time" content="2022-12-16T10:30:48+08:00"><meta itemprop=name content="How to implement a fully asynchronous calls chain based on Dubbo"><meta itemprop=description content="This article recalls how asynchronous call is implemented in Dubbo 2.6.x, and introduces the new way based on CompletableFuture in 2.7.0.
"><meta itemprop=datePublished content="2018-09-02T00:00:00+00:00"><meta itemprop=dateModified content="2022-12-16T10:30:48+08:00"><meta itemprop=wordCount content="1728"><meta itemprop=keywords content><meta name=twitter:card content="summary"><meta name=twitter:title content="How to implement a fully asynchronous calls chain based on Dubbo"><meta name=twitter:description content="This article recalls how asynchronous call is implemented in Dubbo 2.6.x, and introduces the new way based on CompletableFuture in 2.7.0.
"><script async src="https://www.googletagmanager.com/gtag/js?id=G-NM6FFMT51J"></script><script>var doNotTrack=!1;if(!doNotTrack){window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag("js",new Date),gtag("config","G-NM6FFMT51J",{anonymize_ip:!1})}</script><link rel=preload href=/scss/main.min.f77e221bcdbe0cadb996060fe82063c747b60c229a1f8bbf0ee529adbadd84fa.css as=style><link href=/scss/main.min.f77e221bcdbe0cadb996060fe82063c747b60c229a1f8bbf0ee529adbadd84fa.css rel=stylesheet integrity><script src=/js/jquery-3.5.1.min.js integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin=anonymous></script><meta name=theme-color content="#326ce5"><link rel=stylesheet href=/css/feature-states.css><meta name=description content="This article recalls how asynchronous call is implemented in Dubbo 2.6.x, and introduces the new way based on CompletableFuture in 2.7.0.
"><meta property="og:description" content="This article recalls how asynchronous call is implemented in Dubbo 2.6.x, and introduces the new way based on CompletableFuture in 2.7.0.
"><meta name=twitter:description content="This article recalls how asynchronous call is implemented in Dubbo 2.6.x, and introduces the new way based on CompletableFuture in 2.7.0.
"><meta property="og:url" content="https://cn.dubbo.apache.org/en/blog/2018/09/02/how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo/"><meta property="og:title" content="How to implement a fully asynchronous calls chain based on Dubbo"><meta name=twitter:title content="How to implement a fully asynchronous calls chain based on Dubbo"><meta name=twitter:image:alt content="Apache Dubbo"><meta property="og:type" content="article"><meta name=viewport content="width=device-width"><script async defer src=/js/github-buttons.js></script><link href=/css/community.css rel=stylesheet><link href=/css/contactus.css rel=stylesheet><link href=/css/language.css rel=stylesheet><script src=/js/script.js></script></head><body class="td-page td-documentation"><header><nav class="js-navbar-scroll navbar navbar-expand navbar-dark flex-column flex-md-row td-navbar" data-auto-burger=primary><a class=navbar-brand href=/en/><span class=navbar-logo></span><span class="text-uppercase font-weight-bold">Apache Dubbo</span></a><div class="td-navbar-nav-scroll ml-md-auto" id=main_navbar><ul class="navbar-nav mt-2 mt-lg-0"><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/en/overview/><span>Overview</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/en/docs3-v2/><span>SDK Manual</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class="nav-link active" href=/en/blog/><span class=active>Blog</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=/en/download/><span>Download</span></a></li><li class="nav-item mr-4 mb-2 mb-lg-0"><a class=nav-link href=https://start.dubbo.apache.org/bootstrap.html target=_blank><span>Initializer</span><i class='fas fa-external-link-alt'></i></a></li><li class="nav-item dropdown d-lg-block"><a class="nav-link dropdown-toggle" href=# id=navbarDropdownMenuLink role=button data-toggle=dropdown aria-haspopup=true aria-expanded=false>English</a><div class="dropdown-menu dropdown-menu-right" aria-labelledby=navbarDropdownMenuLink><a class=dropdown-item href=/zh-cn/>中文</a></div></li><li class="nav-item dropdown d-lg-block"><div class="nav-item d-none d-lg-block"></div></li></ul></div></nav><section class="header-hero text-white pb-0 light-text"></section></header><div class="container-fluid td-outer"><div class=td-main><div class="row flex-md-nowrap"><div class="col-12 col-md-3 col-xl-2 td-sidebar d-print-none"><script>$(function(){$("#td-section-nav a").removeClass("active"),$("#td-section-nav #m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo").addClass("active"),$("#td-section-nav #m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-li span").addClass("td-sidebar-nav-active-item"),$("#td-section-nav #m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo").parents("li").addClass("active-path"),$("#td-section-nav li.active-path").addClass("show"),$("#td-section-nav li.active-path").children("input").prop("checked",!0),$("#td-section-nav #m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-li").siblings("li").addClass("show"),$("#td-section-nav #m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-li").children("ul").children("li").addClass("show"),$("#td-sidebar-menu").toggleClass("d-none")})</script><div id=td-sidebar-menu class="td-sidebar__inner d-none"><div id=content-mobile><form class="td-sidebar__search d-flex align-items-center"><button class="btn btn-link td-sidebar__toggle d-md-none p-0 ml-3 fas fa-bars" type=button data-toggle=collapse data-target=#td-section-nav aria-controls=td-docs-nav aria-expanded=false aria-label="Toggle section navigation"></button></form></div><div id=content-desktop></div><nav class="collapse td-sidebar-nav foldable-nav" id=td-section-nav><ul class="td-sidebar-nav__section pr-md-3 ul-0"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblog-li><ul class=ul-1><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblognews-li><input type=checkbox id=m-enblognews-check>
<label for=m-enblognews-check><a href=/en/blog/news/ title="Articles About Apache Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-enblognews><span>Articles</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20240131tracing-dubbo-with-opentelemetry-li><input type=checkbox id=m-enblog20240131tracing-dubbo-with-opentelemetry-check>
<label for=m-enblog20240131tracing-dubbo-with-opentelemetry-check><a href=/en/blog/2024/01/31/tracing-dubbo-with-opentelemetry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20240131tracing-dubbo-with-opentelemetry><span>Tracing Dubbo With OpenTelemetry</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea-li><input type=checkbox id=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea-check>
<label for=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea-check><a href=/en/blog/2023/10/23/introduction-to-apache-dubbo-plugin-for-intellij-idea/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20231023introduction-to-apache-dubbo-plugin-for-intellij-idea><span>Introduction to Apache Dubbo plugin for IntelliJ IDEA</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released-li><input type=checkbox id=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released-check>
<label for=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released-check><a href=/en/blog/2023/04/15/advanced-cloud-native-dubbo-3.2-officially-released/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20230415advanced-cloud-native-dubbo-32-officially-released><span>Advanced cloud native - Dubbo 3.2 officially released</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway-li><input type=checkbox id=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway-check>
<label for=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway-check><a href=/en/blog/2022/05/04/how-to-proxy-dubbo-service-in-apache-shenyu-gateway/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20220504how-to-proxy-dubbo-service-in-apache-shenyu-gateway><span>How to proxy Dubbo service in Apache ShenYu Gateway</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix-li><input type=checkbox id=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix-check>
<label for=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix-check><a href=/en/blog/2022/01/18/makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20220118makes-it-more-convenient-for-you-to-proxy-dubbo-services-in-apache-apisix><span>Makes it More Convenient for You to Proxy Dubbo Services in Apache APISIX</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190826service-test-li><input type=checkbox id=m-enblog20190826service-test-check>
<label for=m-enblog20190826service-test-check><a href=/en/blog/2019/08/26/service-test/ title="Dubbo Admin service test" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190826service-test><span>Service test in dubbo admin</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190811tracing-dubbo-service-with-apache-skywalking-li><input type=checkbox id=m-enblog20190811tracing-dubbo-service-with-apache-skywalking-check>
<label for=m-enblog20190811tracing-dubbo-service-with-apache-skywalking-check><a href=/en/blog/2019/08/11/tracing-dubbo-service-with-apache-skywalking/ title="Tracing Dubbo service with Apache Skywalking" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190811tracing-dubbo-service-with-apache-skywalking><span>Use apache skywalking in dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2-li><input type=checkbox id=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2-check>
<label for=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2-check><a href=/en/blog/2019/05/02/dubbo-extensible-mechanism-source-code-analysis-part-2/ title="Dubbo extensible mechanism source code analysis - part 2" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190502dubbo-extensible-mechanism-source-code-analysis-part-2><span>Dubbo extensible mechanism - part 2</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1-li><input type=checkbox id=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1-check>
<label for=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1-check><a href=/en/blog/2019/04/25/dubbo-extensible-mechanism-source-code-analysis-part-1/ title="Dubbo extensible mechanism source code analysis - part 1" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190425dubbo-extensible-mechanism-source-code-analysis-part-1><span>Dubbo extensible mechanism - part 1</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface-li><input type=checkbox id=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface-check>
<label for=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface-check><a href=/en/blog/2019/02/20/implementation-background-and-practice-of-dubbo-client-asynchronous-interface/ title="Implementation background and practice of Dubbo client asynchronous interface" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190220implementation-background-and-practice-of-dubbo-client-asynchronous-interface><span>Dubbo Async Client</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface-li><input type=checkbox id=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface-check>
<label for=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface-check><a href=/en/blog/2019/02/20/implementation-background-and-practice-of-dubbo-server-asynchronous-interface/ title="Implementation background and practice of Dubbo server asynchronous interface" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190220implementation-background-and-practice-of-dubbo-server-asynchronous-interface><span>Dubbo Async Server</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices-li><input type=checkbox id=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices-check>
<label for=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices-check><a href=/en/blog/2019/01/17/how-to-use-seata-to-ensure-consistency-between-dubbo-microservices/ title="How to use Seata to ensure consistency between Dubbo Microservices" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20190117how-to-use-seata-to-ensure-consistency-between-dubbo-microservices><span>Use Seata in Dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou-li><input type=checkbox id=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou-check>
<label for=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou-check><a href=/en/blog/2018/12/10/the-fifth-dubbo-meetup-has-been-held-in-hangzhou/ title="The fifth Dubbo meetup has been held in Hangzhou" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20181210the-fifth-dubbo-meetup-has-been-held-in-hangzhou><span>The fifth Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry-li><input type=checkbox id=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry-check>
<label for=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry-check><a href=/en/blog/2018/11/07/dubbo-integrates-with-nacos-to-become-a-registry/ title="Dubbo Integrates with Nacos to Become a Registry" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20181107dubbo-integrates-with-nacos-to-become-a-registry><span>Use Dubbo with Nacos</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20181005introduction-to-the-dubbo-protocol-li><input type=checkbox id=m-enblog20181005introduction-to-the-dubbo-protocol-check>
<label for=m-enblog20181005introduction-to-the-dubbo-protocol-check><a href=/en/blog/2018/10/05/introduction-to-the-dubbo-protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20181005introduction-to-the-dubbo-protocol><span>Introduction to the Dubbo protocol</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180930integrate-dubbo-with-kubernetes-li><input type=checkbox id=m-enblog20180930integrate-dubbo-with-kubernetes-check>
<label for=m-enblog20180930integrate-dubbo-with-kubernetes-check><a href=/en/blog/2018/09/30/integrate-dubbo-with-kubernetes/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180930integrate-dubbo-with-kubernetes><span>Integrate Dubbo with Kubernetes</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180902how-to-prepare-an-apache-release-li><input type=checkbox id=m-enblog20180902how-to-prepare-an-apache-release-check>
<label for=m-enblog20180902how-to-prepare-an-apache-release-check><a href=/en/blog/2018/09/02/how-to-prepare-an-apache-release/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180902how-to-prepare-an-apache-release><span>How to prepare an Apache Release</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-li><input type=checkbox id=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-check>
<label for=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo-check><a href=/en/blog/2018/09/02/how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo/ title="How to implement a fully asynchronous calls chain based on Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180902how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo><span>New Async Call</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu-li><input type=checkbox id=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu-check>
<label for=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu-check><a href=/en/blog/2018/08/26/the-fourth-dubbo-meetup-has-been-held-in-chengdu/ title="The fourth Dubbo meetup has been held in Chengdu" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180826the-fourth-dubbo-meetup-has-been-held-in-chengdu><span>The fourth Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration-li><input type=checkbox id=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration-check>
<label for=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration-check><a href=/en/blog/2018/08/14/dubbo-basic-usage-dubbo-consumer-configuration/ title=" Dubbo Basic Usage - Dubbo Consumer Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814dubbo-basic-usage-dubbo-consumer-configuration><span>Dubbo Consumer Configuration</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke-li><input type=checkbox id=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke-check>
<label for=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke-check><a href=/en/blog/2018/08/14/dubbo-several-ways-about-synchronous/asynchronous-invoke/ title="Dubbo: Several ways about synchronous/asynchronous invoke" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814dubbo-several-ways-about-synchronousasynchronous-invoke><span>Dubbo Invoke</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration-li><input type=checkbox id=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration-check>
<label for=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration-check><a href=/en/blog/2018/08/14/dubbo-basic-usage--dubbo-provider-configuration/ title="Dubbo Basic Usage -- Dubbo Provider Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814dubbo-basic-usage--dubbo-provider-configuration><span>Dubbo Provider Configuration</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814manipulating-services-dynamically-via-qos-li><input type=checkbox id=m-enblog20180814manipulating-services-dynamically-via-qos-check>
<label for=m-enblog20180814manipulating-services-dynamically-via-qos-check><a href=/en/blog/2018/08/14/manipulating-services-dynamically-via-qos/ title="Manipulating Services Dynamically via QoS" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814manipulating-services-dynamically-via-qos><span>Dubbo QoS Introduction</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop-li><input type=checkbox id=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop-check>
<label for=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop-check><a href=/en/blog/2018/08/14/source-code-analysis-of-spring-boot-dubbo-app-start-and-stop/ title="Source code analysis of spring-boot+Dubbo App start and stop" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814source-code-analysis-of-spring-boot-dubbo-app-start-and-stop><span>Dubbo start/stop in spring boot</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js-li><input type=checkbox id=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js-check>
<label for=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js-check><a href=/en/blog/2018/08/14/implementation-of-cross-language-calls-by-dubbo2.js/ title="Implementation of cross-language calls by Dubbo2.js" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814implementation-of-cross-language-calls-by-dubbo2js><span>dubbo2.js introduction</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814generic-invoke-of-dubbo-li><input type=checkbox id=m-enblog20180814generic-invoke-of-dubbo-check>
<label for=m-enblog20180814generic-invoke-of-dubbo-check><a href=/en/blog/2018/08/14/generic-invoke-of-dubbo/ title="Generic invoke of Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814generic-invoke-of-dubbo><span>Generic invoke</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180814native-image-using-graalvm-li><input type=checkbox id=m-enblog20180814native-image-using-graalvm-check>
<label for=m-enblog20180814native-image-using-graalvm-check><a href=/en/blog/2018/08/14/native-image-using-graalvm/ title="Native Image using GraalVM" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180814native-image-using-graalvm><span>Native Image</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180810dubbos-load-balance-li><input type=checkbox id=m-enblog20180810dubbos-load-balance-check>
<label for=m-enblog20180810dubbos-load-balance-check><a href=/en/blog/2018/08/10/dubbos-load-balance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180810dubbos-load-balance><span>Dubbo's Load Balance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180807use-annotations-in-dubbo-li><input type=checkbox id=m-enblog20180807use-annotations-in-dubbo-check>
<label for=m-enblog20180807use-annotations-in-dubbo-check><a href=/en/blog/2018/08/07/use-annotations-in-dubbo/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180807use-annotations-in-dubbo><span>Use Annotations In Dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180807using-zookeeper-in-dubbo-li><input type=checkbox id=m-enblog20180807using-zookeeper-in-dubbo-check>
<label for=m-enblog20180807using-zookeeper-in-dubbo-check><a href=/en/blog/2018/08/07/using-zookeeper-in-dubbo/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180807using-zookeeper-in-dubbo><span>Using Zookeeper in Dubbo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180807dubbo-101-li><input type=checkbox id=m-enblog20180807dubbo-101-check>
<label for=m-enblog20180807dubbo-101-check><a href=/en/blog/2018/08/07/dubbo-101/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180807dubbo-101><span>Your First Dubbo Demo</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen-li><input type=checkbox id=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen-check>
<label for=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen-check><a href=/en/blog/2018/07/30/the-third-dubbo-meetup-has-been-held-in-shenzhen/ title="The third Dubbo meetup has been held in Shenzhen" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180730the-third-dubbo-meetup-has-been-held-in-shenzhen><span>The third Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services-li><input type=checkbox id=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services-check>
<label for=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services-check><a href=/en/blog/2018/07/27/sentinel-the-flow-sentinel-of-dubbo-services/ title="Sentinel: The flow sentinel of Dubbo services" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180727sentinel-the-flow-sentinel-of-dubbo-services><span>Introduce sentinel</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180712tracking-with-pinpoint-li><input type=checkbox id=m-enblog20180712tracking-with-pinpoint-check>
<label for=m-enblog20180712tracking-with-pinpoint-check><a href=/en/blog/2018/07/12/tracking-with-pinpoint/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180712tracking-with-pinpoint><span>Tracking with Pinpoint</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180701your-first-dubbo-filter-li><input type=checkbox id=m-enblog20180701your-first-dubbo-filter-check>
<label for=m-enblog20180701your-first-dubbo-filter-check><a href=/en/blog/2018/07/01/your-first-dubbo-filter/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180701your-first-dubbo-filter><span>Your First Dubbo Filter</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully-li><input type=checkbox id=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully-check>
<label for=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully-check><a href=/en/blog/2018/06/23/the-second-dubbo-shanghai-meetup-has-been-held-successfully/ title="The second Dubbo Shanghai meetup has been held successfully" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180623the-second-dubbo-shanghai-meetup-has-been-held-successfully><span>The second Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing-li><input type=checkbox id=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing-check>
<label for=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing-check><a href=/en/blog/2018/05/12/the-first-dubbo-meetup-has-been-held-in-beijing/ title="The first Dubbo meetup has been held in Beijing" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180512the-first-dubbo-meetup-has-been-held-in-beijing><span>The first Dubbo meetup</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180502the-apachecon-na-schedule-has-been-announced-li><input type=checkbox id=m-enblog20180502the-apachecon-na-schedule-has-been-announced-check>
<label for=m-enblog20180502the-apachecon-na-schedule-has-been-announced-check><a href=/en/blog/2018/05/02/the-apachecon-na-schedule-has-been-announced/ title="The ApacheCon NA schedule has been announced" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180502the-apachecon-na-schedule-has-been-announced><span>ApacheCon NA</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180425the-gsocgoogle-summer-of-code-2018-li><input type=checkbox id=m-enblog20180425the-gsocgoogle-summer-of-code-2018-check>
<label for=m-enblog20180425the-gsocgoogle-summer-of-code-2018-check><a href=/en/blog/2018/04/25/the-gsocgoogle-summer-of-code-2018/ title="The GSoC(Google Summer of Code) 2018" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180425the-gsocgoogle-summer-of-code-2018><span>GSoC 2018</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018-li><input type=checkbox id=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018-check>
<label for=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018-check><a href=/en/blog/2018/04/22/dubbo-roadmap-is-announced-in-qcon-beijing-2018/ title="Dubbo roadmap is announced in QCon Beijing 2018" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20180422dubbo-roadmap-is-announced-in-qcon-beijing-2018><span>QCon Beijing 2018</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblogproposals-li><input type=checkbox id=m-enblogproposals-check>
<label for=m-enblogproposals-check><a href=/en/blog/proposals/ title="Proposals About Apache Dubbo" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-enblogproposals><span>Proposals</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog10101application-level-service-discovery-li><input type=checkbox id=m-enblog10101application-level-service-discovery-check>
<label for=m-enblog10101application-level-service-discovery-check><a href=/en/blog/1/01/01/application-level-service-discovery/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog10101application-level-service-discovery><span>Application-Level Service Discovery</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol-li><input type=checkbox id=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol-check>
<label for=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol-check><a href=/en/blog/1/01/01/enhanced-http-standard-capabilities-of-triple-protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog10101enhanced-http-standard-capabilities-of-triple-protocol><span>Enhanced HTTP Standard Capabilities of Triple Protocol</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-enblogreleases-li><input type=checkbox id=m-enblogreleases-check>
<label for=m-enblogreleases-check><a href=/en/blog/releases/ title="New Releases" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-enblogreleases><span>Releases</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog202109202714-release-note-li><input type=checkbox id=m-enblog202109202714-release-note-check>
<label for=m-enblog202109202714-release-note-check><a href=/en/blog/2021/09/20/2.7.14-release-note/ title="2.7.14 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog202109202714-release-note><span>2.7.14</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog202108233021-release-note-li><input type=checkbox id=m-enblog202108233021-release-note-check>
<label for=m-enblog202108233021-release-note-check><a href=/en/blog/2021/08/23/3.0.2.1-release-note/ title="3.0.2.1 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog202108233021-release-note><span>3.0.2.1</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20210818302-release-note-li><input type=checkbox id=m-enblog20210818302-release-note-check>
<label for=m-enblog20210818302-release-note-check><a href=/en/blog/2021/08/18/3.0.2-release-note/ title="3.0.2 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20210818302-release-note><span>3.0.2</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20210702301-release-note-li><input type=checkbox id=m-enblog20210702301-release-note-check>
<label for=m-enblog20210702301-release-note-check><a href=/en/blog/2021/07/02/3.0.1-release-note/ title="3.0.1 Release Note" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20210702301-release-note><span>3.0.1</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-enblog20200518past-releases-li><input type=checkbox id=m-enblog20200518past-releases-check>
<label for=m-enblog20200518past-releases-check><a href=/en/blog/2020/05/18/past-releases/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-enblog20200518past-releases><span>Past Releases</span></a></label></li></ul></li></ul></li></ul></nav></div></div><main class="col-12 col-md-9 col-xl-8 pl-md-5" role=main><nav aria-label=breadcrumb class=td-breadcrumbs><ol class=breadcrumb><li class=breadcrumb-item><a href=https://cn.dubbo.apache.org/en/blog/>Blog</a></li><li class=breadcrumb-item><a href=https://cn.dubbo.apache.org/en/blog/news/>Articles</a></li><li class="breadcrumb-item active" aria-current=page><a href=https://cn.dubbo.apache.org/en/blog/2018/09/02/how-to-implement-a-fully-asynchronous-calls-chain-based-on-dubbo/ aria-disabled=true class="btn-link disabled">New Async Call</a></li></ol></nav><section id=deprecation-warning><div class="content deprecation-warning pageinfo outdated-blog"><p>This article is more than one year old. Older articles may contain outdated content. Check that the information in the page has not become incorrect since its publication.</p></div></section><div class=td-content><h1>How to implement a fully asynchronous calls chain based on Dubbo</h1><div class=lead>This article recalls how asynchronous call is implemented in Dubbo 2.6.x, and introduces the new way based on CompletableFuture in 2.7.0.</div><div class="td-byline mb-4"><time datetime=2018-09-02 class=text-muted>Sunday, September 02, 2018</time></div><header class=article-meta></header><p>Implementing the full asynchronous programming based on Dubbo, which is a new feature introduced in version 2.7.0 after the enhancement of the existing asynchronous mode.This article first reviews the supported functions and existing problems of asynchronization in 2.6.x and earlier versions, and introduces the targeted enhancements based on CompletableFuture in version 2.7.0. Then, the use of enhanced asynchronous programming is elaborated through several examples. Finally, it summarizes the new problems brought by the introduction of asynchronous mode and corresponding solutions from Dubbo. By reading this article, it is easy to implement a fully asynchronous remote service call chain based on Dubbo 2.7.0+.</p><h2 id=asynchronous-mode-before-version-26x>Asynchronous mode before version 2.6.x</h2><p>Dubbo Provides some asynchronous programming capabilities in 2.6.x and earlier versions, including <a href=/en/docs/v2.7/user/examples/async-call/>Asynchronous Call</a>, <a href=/en/docs/v2.7/user/examples/callback-parameter/>Parameter Callback</a> and <a href=/en/docs/v2.7/user/examples/events-notify/>Event Notification</a> on Consumer side. There are some brief introductions to the usage and Demo in the above document links.</p><p>But the current asynchronous method has the following problems:</p><ul><li>Methods to access Future object are not direct enough.</li><li>Future interface cannot implement automatic callback. Customized ResponseFuture class could implement callback, however it only supports limited asynchronous scenes. For example, it does not support mutual coordination or combination between Future objects.</li><li>Asynchronization on Provider side is not supported.</li></ul><p>Take the asynchronous method of Consumer side as an example:</p><ol><li>Define a original synchronous interface and add the declaration to support asynchronous calls.</li></ol><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>FooService</span> {
</span></span><span style=display:flex><span> String <span style=color:#268bd2>findFoo</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:reference</span> id=<span style=color:#2aa198>&#34;fooService&#34;</span> interface=<span style=color:#2aa198>&#34;com.alibaba.foo.FooService&#34;</span><span style=color:#268bd2>&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;dubbo:method</span> name=<span style=color:#2aa198>&#34;findFoo&#34;</span> async=<span style=color:#2aa198>&#34;true&#34;</span> <span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/dubbo:reference&gt;</span>
</span></span></code></pre></div><ol start=2><li>Obtain Future object through RpcContext.</li></ol><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#586e75>// this call will return null immediately</span>
</span></span><span style=display:flex><span>fooService.findFoo(fooId);
</span></span><span style=display:flex><span><span style=color:#586e75>// Obtain the Future instance. When the result is returned, Future instance will be notified and the result will be set to Future instance.</span>
</span></span><span style=display:flex><span>Future<span style=color:#719e07>&lt;</span>Foo<span style=color:#719e07>&gt;</span> fooFuture <span style=color:#719e07>=</span> RpcContext.getContext().getFuture();
</span></span><span style=display:flex><span>fooFuture.get();
</span></span></code></pre></div><p>or</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#586e75>// this call will return null immediately</span>
</span></span><span style=display:flex><span>fooService.findFoo(fooId);
</span></span><span style=display:flex><span><span style=color:#586e75>// get Dubbo&#39;s built-in ResponseFuture, and set the callback</span>
</span></span><span style=display:flex><span>ResponseFuture future <span style=color:#719e07>=</span> ((FutureAdapter)RpcContext.getContext().getFuture()).getFuture();
</span></span><span style=display:flex><span>future.setCallback(<span style=color:#719e07>new</span> ResponseCallback() {
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>done</span>(Object response) {
</span></span><span style=display:flex><span> System.out.print(response);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>caught</span>(Throwable exception) {
</span></span><span style=display:flex><span> exception.printStackTrace();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>});
</span></span></code></pre></div><p>From this simple example, we can see there are some inconveniences in use:</p><ol><li>The synchronization interface of findFoo cannot directly return a Future object representing the asynchronous result, which is further obtained through RpcContext.</li><li>Future object can only be obtained from get method that will block until getting the result.</li><li>Callback can be set by getting the built-in ResponseFuture interface. However, the API to obtain ResponseFuture is not convenient enough to support other asynchronous scenes except callback. For example, it does not support the scene where multiple Future objects work together.</li></ol><h2 id=enhancement-based-on-completablefuture-in-version-270>Enhancement based on CompletableFuture in version 2.7.0</h2><p>People who understand the evolution history of Future in Java should know that the Future used in Dubbo 2.6.x and earlier versions is introduced in Java 5, so there are some problems in function design.The CompletableFuture introduced in Java 8 further enriches the Future interface and solves these problems well.</p><p>Support for Java 8 has been upgraded in Dubbo 2.7.0, and Dubbo has enhanced the current asynchronous functionality based on CompletableFuture.</p><ol><li><p>Now it supports direct definition of service interfaces that return CompletableFuture. Through these interfaces, we can implement asynchronous programming on both Consumer side and Provider side more naturally.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>AsyncService</span> {
</span></span><span style=display:flex><span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> <span style=color:#268bd2>sayHello</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div></li><li><p>If you don&rsquo;t want to define the return value of the interface as a Future object, or if there is a defined synchronization interface, you can additionally define an asynchronous interface and provide a method to return a Future object.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>AsyncService</span> {
</span></span><span style=display:flex><span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> <span style=color:#268bd2>sayHello</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>@AsyncFor</span>(AsyncService.class)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>GrettingServiceAsync</span> <span style=color:#268bd2>extends</span> GreetingsService {
</span></span><span style=display:flex><span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> <span style=color:#268bd2>sayHiAsync</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>In this way, Provider can only implement the sayHi method. The Consumer can get a Future instance by directly calling sayHiAsync, and Dubbo framework will convert it to a call to the sayHi method on the Provider side automatically.</p><p>Providing an asynchronous method definition for each synchronization method can be inconvenient. Further, using <a href=https://github.com/dubbo/dubbo-async-processor>Annotation Processor implementation</a> in the Dubbo ecosystem can automatically generate asynchronous method definitions for us.</p></li><li><p>Similarly, if your original interface definition doesn&rsquo;t return a Future object, the Provider side also provides a programming interface similar to the Async Servlet in Servlet 3.0 to support asynchronization : <code>RpcContext.startAsync()</code>.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>AsyncService</span> {
</span></span><span style=display:flex><span> String <span style=color:#268bd2>sayHello</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>AsyncServiceImpl</span> <span style=color:#268bd2>implements</span> AsyncService {
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> String <span style=color:#268bd2>sayHello</span>(String name) {
</span></span><span style=display:flex><span> <span style=color:#268bd2>final</span> AsyncContext asyncContext <span style=color:#719e07>=</span> RpcContext.startAsync();
</span></span><span style=display:flex><span> <span style=color:#719e07>new</span> Thread(() <span style=color:#719e07>-&gt;</span> {
</span></span><span style=display:flex><span> asyncContext.write(<span style=color:#2aa198>&#34;Hello &#34;</span> <span style=color:#719e07>+</span> name <span style=color:#719e07>+</span> <span style=color:#2aa198>&#34;, response from provider.&#34;</span>);
</span></span><span style=display:flex><span> }).start();
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> <span style=color:#cb4b16>null</span>;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>At the beginning of the method body, it starts asynchronization by running <code>RpcContext.startAsync()</code> , and it starts a new thread to execute the business logic asynchronously. After the time-consuming operation is completed, the result is written back by <code>asyncContext.write</code>.</p></li><li><p>RpcContext returns CompletableFuture directly.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span>CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> f <span style=color:#719e07>=</span> RpcContext.getContext().getCompletableFuture();
</span></span></code></pre></div></li></ol><p>All of the above enhancements are based on the compatibility with existing asynchronous programming, so asynchronous programs written based on 2.6.x versions can be successfully compiled without any modification.</p><p>Next, let&rsquo;s illustrate how to implement a fully asynchronous Dubbo service call chain through a few examples.</p><h2 id=example-1completablefuture-interface>example 1:CompletableFuture interface</h2><p>CompletableFuture interface can be used both for a synchronous call and for an asynchronous call on Consumer or Provider side. This example implements asynchronous calls between Consumer and Provider sides. Code link <a href=https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-async/dubbo-samples-async-original-future>dubbo-samples-async-original-future</a>.</p><ol><li><p>Interface definition</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>AsyncService</span> {
</span></span><span style=display:flex><span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> <span style=color:#268bd2>sayHello</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Note that the return type of this interface is <code>CompletableFuture&lt;String></code>.</p></li><li><p>Provider Side</p><ul><li><p>Implementation</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>AsyncServiceImpl</span> <span style=color:#268bd2>implements</span> AsyncService {
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> <span style=color:#268bd2>sayHello</span>(String name) {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> CompletableFuture.supplyAsync(() <span style=color:#719e07>-&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#719e07>try</span> {
</span></span><span style=display:flex><span> Thread.sleep(5000);
</span></span><span style=display:flex><span> } <span style=color:#719e07>catch</span> (InterruptedException e) {
</span></span><span style=display:flex><span> e.printStackTrace();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> <span style=color:#2aa198>&#34;async response from provider.&#34;</span>;
</span></span><span style=display:flex><span> });
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We can see that the business code is switched to be executed in the new thread by supplyAsync, so the Provider side is asynchronous.</p></li><li><p>Config</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;bean</span> id=<span style=color:#2aa198>&#34;asyncService&#34;</span> class=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.async.impl.AsyncServiceImpl&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:service</span> interface=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.async.api.AsyncService&#34;</span> ref=<span style=color:#2aa198>&#34;asyncService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>The Config is the same as the original interface.</p></li></ul></li><li><p>Consumer Side</p><ul><li>Config</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:reference</span> id=<span style=color:#2aa198>&#34;asyncService&#34;</span> timeout=<span style=color:#2aa198>&#34;10000&#34;</span> interface=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.async.api.AsyncService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>The Config is the same as the original interface.</p><ul><li>Call remote service</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>static</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>main</span>(String<span style=color:#719e07>[]</span> args) <span style=color:#268bd2>throws</span> Exception {
</span></span><span style=display:flex><span> ClassPathXmlApplicationContext context <span style=color:#719e07>=</span> <span style=color:#719e07>new</span> ClassPathXmlApplicationContext(<span style=color:#719e07>new</span> String<span style=color:#719e07>[]</span>{<span style=color:#2aa198>&#34;META-INF/spring/async-consumer.xml&#34;</span>});
</span></span><span style=display:flex><span> context.start();
</span></span><span style=display:flex><span> <span style=color:#268bd2>final</span> AsyncService asyncService <span style=color:#719e07>=</span> (AsyncService) context.getBean(<span style=color:#2aa198>&#34;asyncService&#34;</span>);
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> future <span style=color:#719e07>=</span> asyncService.sayHello(<span style=color:#2aa198>&#34;async call request&#34;</span>);
</span></span><span style=display:flex><span> future.whenComplete((v, t) <span style=color:#719e07>-&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#719e07>if</span> (t <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span>) {
</span></span><span style=display:flex><span> t.printStackTrace();
</span></span><span style=display:flex><span> } <span style=color:#719e07>else</span> {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Response: &#34;</span> <span style=color:#719e07>+</span> v);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> });
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Executed before response return.&#34;</span>);
</span></span><span style=display:flex><span> System.in.read();
</span></span><span style=display:flex><span> }
</span></span></code></pre></div><p><code>CompletableFuture&lt;String> future = asyncService.sayHello("async call request");</code>It is convenient to return the Future instance, which implements the asynchronous service call on the Consumer side.</p></li></ol><h2 id=example-2synchronous-interface-uses-annotation-processor>Example 2:Synchronous interface uses Annotation Processor</h2><p>This example demonstrates how to implement the Consumer-side asynchronous service call using the Annotation Processor based on the original synchronous interface. Code link <a href=https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-async/dubbo-samples-async-generated-future>dubbo-samples-async-generated-future</a>.</p><ol><li><p>Interface definition</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>@DubboAsync</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>GreetingsService</span> {
</span></span><span style=display:flex><span> String <span style=color:#268bd2>sayHi</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>This is a generic definition of the Dubbo service interface. Note that add the @DubboAsync annotation when using Annotation Processor.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;dependency&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;groupId&gt;</span>com.alibaba<span style=color:#268bd2>&lt;/groupId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;artifactId&gt;</span>dubbo-async-processer<span style=color:#268bd2>&lt;/artifactId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;version&gt;</span>1.0.0-SNAPSHOT<span style=color:#268bd2>&lt;/version&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/dependency&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;plugin&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;groupId&gt;</span>org.apache.maven.plugins<span style=color:#268bd2>&lt;/groupId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;artifactId&gt;</span>maven-compiler-plugin<span style=color:#268bd2>&lt;/artifactId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;version&gt;</span>3.7.0<span style=color:#268bd2>&lt;/version&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;configuration&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;source&gt;</span>1.8<span style=color:#268bd2>&lt;/source&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;target&gt;</span>1.8<span style=color:#268bd2>&lt;/target&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;annotationProcessorPaths&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;path&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;groupId&gt;</span>com.alibaba<span style=color:#268bd2>&lt;/groupId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;artifactId&gt;</span>dubbo-async-processer<span style=color:#268bd2>&lt;/artifactId&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;version&gt;</span>1.0.0-SNAPSHOT<span style=color:#268bd2>&lt;/version&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/path&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/annotationProcessorPaths&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/configuration&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/plugin&gt;</span>
</span></span></code></pre></div><p>The above config is the Maven dependency that imports dubbo-async-processer processor. Developers who define interfaces (providing APIs) usually add the above dependencies to the project, so that when doing API packaging, the following interface definitions will be automatically generated in APIs:</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#586e75>/**
</span></span></span><span style=display:flex><span><span style=color:#586e75>* Generated by dubbo-async-processer
</span></span></span><span style=display:flex><span><span style=color:#586e75>*/</span>
</span></span><span style=display:flex><span><span style=color:#719e07>package</span> com.alibaba.dubbo.samples.api;
</span></span><span style=display:flex><span><span style=color:#719e07>import</span> java.util.concurrent.CompletableFuture;
</span></span><span style=display:flex><span><span style=color:#268bd2>@javax.annotation.Generated</span>(<span style=color:#2aa198>&#34;com.alibaba.dubbo.async.processor.AsyncAnnotationProcessor&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>@org.apache.dubbo.common.config.AsyncFor</span>(com.alibaba.dubbo.samples.api.GreetingsService.class)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>GreetingsServiceAsync</span> <span style=color:#268bd2>extends</span> GreetingsService {
</span></span><span style=display:flex><span>CompletableFuture<span style=color:#719e07>&lt;</span>java.lang.String<span style=color:#719e07>&gt;</span> <span style=color:#268bd2>sayHiAsync</span>(java.lang.String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div></li><li><p>Provider side</p><ul><li>Config</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;bean</span> id=<span style=color:#2aa198>&#34;greetingsService&#34;</span> class=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.async.impl.GreetingsServiceImpl&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:service</span> interface=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.api.GreetingsService&#34;</span> ref=<span style=color:#2aa198>&#34;greetingsService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><ul><li>Service implementation</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>GreetingsServiceImpl</span> <span style=color:#268bd2>implements</span> GreetingsService {
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> String <span style=color:#268bd2>sayHi</span>(String name) {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> <span style=color:#2aa198>&#34;hi, &#34;</span> <span style=color:#719e07>+</span> name;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div></li><li><p>Consumer side</p><ul><li>Config</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span> <span style=color:#268bd2>&lt;dubbo:reference</span> id=<span style=color:#2aa198>&#34;greetingsService&#34;</span> interface=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.api.GreetingsServiceAsync&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>Note that the service interface uses <strong>GreetingsServiceAsync</strong></p><ul><li>Service call</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#268bd2>static</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>main</span>(String<span style=color:#719e07>[]</span> args) <span style=color:#268bd2>throws</span> Exception {
</span></span><span style=display:flex><span> ClassPathXmlApplicationContext context <span style=color:#719e07>=</span> <span style=color:#719e07>new</span> ClassPathXmlApplicationContext(<span style=color:#719e07>new</span> String<span style=color:#719e07>[]</span>{<span style=color:#2aa198>&#34;META-INF/spring/async-consumer.xml&#34;</span>});
</span></span><span style=display:flex><span> context.start();
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> GreetingsServiceAsync greetingsService <span style=color:#719e07>=</span> (GreetingsServiceAsync) context.getBean(<span style=color:#2aa198>&#34;greetingsService&#34;</span>);
</span></span><span style=display:flex><span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> future <span style=color:#719e07>=</span> greetingsService.sayHiAsync(<span style=color:#2aa198>&#34;async call reqeust&#34;</span>);
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;async call ret :&#34;</span> <span style=color:#719e07>+</span> future.get());
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> System.in.read();
</span></span><span style=display:flex><span> }
</span></span></code></pre></div><p>In this way, we can use <code>CompletableFuture&lt;String> future = greetingsService.sayHiAsync("async call reqeust");</code> directly,and return CompletableFuture.</p></li></ol><h2 id=example-3use-asynccontext>Example 3:Use AsyncContext</h2><p>This example demonstrates how to implement the Provider-side asynchronous execution through AsyncContext based on the original synchronous interface. Code link <a href=https://github.com/apache/dubbo-samples/tree/master/2-advanced/dubbo-samples-async/dubbo-samples-async-provider>dubbo-samples-async-provider</a>.</p><ol><li><p>Interface definition</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>AsyncService</span> {
</span></span><span style=display:flex><span> String <span style=color:#268bd2>sayHello</span>(String name);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div></li><li><p>Provider side</p><ul><li>Config</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;bean</span> id=<span style=color:#2aa198>&#34;asyncService&#34;</span> class=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.async.impl.AsyncServiceImpl&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:service</span> async=<span style=color:#2aa198>&#34;true&#34;</span> interface=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.async.api.AsyncService&#34;</span> ref=<span style=color:#2aa198>&#34;asyncService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>Note that adding <code>async="true"</code> indicates that this is a service that starts the Provider-side execution asynchronously.</p><ul><li>Asynchronous execution implementation</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>AsyncServiceImpl</span> <span style=color:#268bd2>implements</span> AsyncService {
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> String <span style=color:#268bd2>sayHello</span>(String name) {
</span></span><span style=display:flex><span> <span style=color:#268bd2>final</span> AsyncContext asyncContext <span style=color:#719e07>=</span> RpcContext.startAsync();
</span></span><span style=display:flex><span> <span style=color:#719e07>new</span> Thread(() <span style=color:#719e07>-&gt;</span> {
</span></span><span style=display:flex><span> asyncContext.signalContextSwitch();
</span></span><span style=display:flex><span> <span style=color:#719e07>try</span> {
</span></span><span style=display:flex><span> Thread.sleep(500);
</span></span><span style=display:flex><span> } <span style=color:#719e07>catch</span> (InterruptedException e) {
</span></span><span style=display:flex><span> e.printStackTrace();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> asyncContext.write(<span style=color:#2aa198>&#34;Hello &#34;</span> <span style=color:#719e07>+</span> name <span style=color:#719e07>+</span> <span style=color:#2aa198>&#34;, response from provider.&#34;</span>);
</span></span><span style=display:flex><span> }).start();
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> <span style=color:#cb4b16>null</span>;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div></li><li><p>Consumer side</p><ul><li>Config</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-xml data-lang=xml><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:reference</span> id=<span style=color:#2aa198>&#34;asyncService&#34;</span> interface=<span style=color:#2aa198>&#34;com.alibaba.dubbo.samples.async.api.AsyncService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><ul><li>Service call</li></ul><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#268bd2>static</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>main</span>(String<span style=color:#719e07>[]</span> args) <span style=color:#268bd2>throws</span> Exception {
</span></span><span style=display:flex><span> ClassPathXmlApplicationContext context <span style=color:#719e07>=</span> <span style=color:#719e07>new</span> ClassPathXmlApplicationContext(<span style=color:#719e07>new</span> String<span style=color:#719e07>[]</span>{<span style=color:#2aa198>&#34;META-INF/spring/async-consumer.xml&#34;</span>});
</span></span><span style=display:flex><span> context.start();
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> AsyncService asyncService <span style=color:#719e07>=</span> (AsyncService) context.getBean(<span style=color:#2aa198>&#34;asyncService&#34;</span>);
</span></span><span style=display:flex><span> System.out.println(asyncService.sayHello(<span style=color:#2aa198>&#34;async call request&#34;</span>));
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> System.in.read();
</span></span><span style=display:flex><span> }
</span></span></code></pre></div></li></ol><h2 id=new-problems-resulted-from-asynchronization>New problems resulted from asynchronization</h2><h3 id=filter-chain>Filter Chain</h3><p>The following is a complete Filter chain for a normal Dubbo call.</p><p>After using the asynchronous call, since the asynchronous result is executed separately in the asynchronous thread, the Result passed through the second half of the Filter chain is null, and the real result cannot be processed by the Filter chain when it is returned.</p><p>In order to solve this problem, PostProcessFilter and AbstractPostProcessFilter were introduced in Dubbo 2.7.0. The PostProcessFilter interface extends from the Filter interface, and AbstractPostProcessFilter is an abstract implementation of PostProcessFilter.</p><p>The following is an example of extending the Filter and supporting the asynchronous Filter chain.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>@Activate</span>(group <span style=color:#719e07>=</span> {Constants.PROVIDER, Constants.CONSUMER})
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>AsyncPostprocessFilter</span> <span style=color:#268bd2>extends</span> AbstractPostProcessFilter {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> Result <span style=color:#268bd2>invoke</span>(Invoker<span style=color:#719e07>&lt;?&gt;</span> invoker, Invocation invocation) <span style=color:#268bd2>throws</span> RpcException {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> postProcessResult(invoker.invoke(invocation), invoker, invocation);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Override</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>protected</span> Result <span style=color:#268bd2>doPostProcess</span>(Result result, Invoker<span style=color:#719e07>&lt;?&gt;</span> invoker, Invocation invocation) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Filter get the return value: &#34;</span> <span style=color:#719e07>+</span> result.getValue());
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> result;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><h3 id=context-passing>Context passing</h3><p>Currently, the context we are considering mainly refers to the data stored in the RpcContext. In most scenarios, the user needs to complete the passing of the Context before switching the service thread.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>AsyncServiceImpl</span> <span style=color:#268bd2>implements</span> AsyncService {
</span></span><span style=display:flex><span> <span style=color:#586e75>// Save the context of the current thread</span>
</span></span><span style=display:flex><span> RpcContext context <span style=color:#719e07>=</span> RpcContext.getContext();
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> CompletableFuture<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;</span> <span style=color:#268bd2>sayHello</span>(String name) {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> CompletableFuture.supplyAsync(() <span style=color:#719e07>-&gt;</span> {
</span></span><span style=display:flex><span> <span style=color:#586e75>// Set context into new thread</span>
</span></span><span style=display:flex><span> RpcContext.setContext(context);
</span></span><span style=display:flex><span> <span style=color:#719e07>try</span> {
</span></span><span style=display:flex><span> Thread.sleep(5000);
</span></span><span style=display:flex><span> } <span style=color:#719e07>catch</span> (InterruptedException e) {
</span></span><span style=display:flex><span> e.printStackTrace();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> <span style=color:#2aa198>&#34;async response from provider.&#34;</span>;
</span></span><span style=display:flex><span> });
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>However, AsyncContext also provides the signalContextSwitch() method for a convenient Context switch.</p><div class=highlight><pre tabindex=0 style=color:#93a1a1;background-color:#002b36;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-java data-lang=java><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>AsyncServiceImpl</span> <span style=color:#268bd2>implements</span> AsyncService {
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> String <span style=color:#268bd2>sayHello</span>(String name) {
</span></span><span style=display:flex><span> <span style=color:#268bd2>final</span> AsyncContext asyncContext <span style=color:#719e07>=</span> RpcContext.startAsync();
</span></span><span style=display:flex><span> <span style=color:#719e07>new</span> Thread(() <span style=color:#719e07>-&gt;</span> {
</span></span><span style=display:flex><span> asyncContext.signalContextSwitch();
</span></span><span style=display:flex><span> <span style=color:#719e07>try</span> {
</span></span><span style=display:flex><span> Thread.sleep(500);
</span></span><span style=display:flex><span> } <span style=color:#719e07>catch</span> (InterruptedException e) {
</span></span><span style=display:flex><span> e.printStackTrace();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> asyncContext.write(<span style=color:#2aa198>&#34;Hello &#34;</span> <span style=color:#719e07>+</span> name <span style=color:#719e07>+</span> <span style=color:#2aa198>&#34;, response from provider.&#34;</span>);
</span></span><span style=display:flex><span> }).start();
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> <span style=color:#cb4b16>null</span>;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><ul class="list-unstyled d-flex justify-content-between align-items-center mb-0 pt-5"><li><a href=/en/blog/2018/08/26/the-fourth-dubbo-meetup-has-been-held-in-chengdu/ aria-label="Previous - The fourth Dubbo meetup has been held in Chengdu" class="btn btn-primary"><span class=mr-1></span>Previous</a></li><li><a href=/en/blog/2018/09/02/how-to-prepare-an-apache-release/ aria-label="Next - How to prepare an Apache Release" class="btn btn-primary">Next<span class=ml-1></span></a></li></ul></div><div id=pre-footer><h2>Feedback</h2><p class=feedback--prompt>Was this page helpful?</p><button class="btn btn-primary mb-4 feedback--yes">Yes</button>
<button class="btn btn-primary mb-4 feedback--no">No</button></div><script>const yes=document.querySelector(".feedback--yes"),no=document.querySelector(".feedback--no");document.querySelectorAll(".feedback--link").forEach(e=>{e.href=e.href+window.location.pathname});const sendFeedback=e=>{gtag||console.log("!gtag"),gtag("event","click",{event_category:"Helpful",event_label:window.location.pathname,value:e})},disableButtons=()=>{yes.disabled=!0,yes.classList.add("feedback--button__disabled"),no.disabled=!0,no.classList.add("feedback--button__disabled")};yes.addEventListener("click",()=>{sendFeedback(1),disableButtons(),document.querySelector(".feedback--response").classList.remove("feedback--response__hidden")}),no.addEventListener("click",()=>{sendFeedback(0),disableButtons(),document.querySelector(".feedback--response").classList.remove("feedback--response__hidden")})</script></main><div class="d-none d-xl-block col-xl-2 td-toc d-print-none"><div class="td-page-meta ml-2 pb-1 pt-2 mb-0"><a href=https://github.com/apache/dubbo-website/edit/master/content/en/blog/news/dubbo-new-async.md target=_blank><i class="fa fa-edit fa-fw"></i> Edit this page</a>
<a href="https://github.com/apache/dubbo-website/new/master/content/en/blog/news/dubbo-new-async.md?filename=change-me.md&amp;value=---%0Atitle%3A+%22Long+Page+Title%22%0AlinkTitle%3A+%22Short+Nav+Title%22%0Aweight%3A+100%0Adescription%3A+%3E-%0A+++++Page+description+for+heading+and+indexes.%0A---%0A%0A%23%23+Heading%0A%0AEdit+this+template+to+create+your+new+page.%0A%0A%2A+Give+it+a+good+name%2C+ending+in+%60.md%60+-+e.g.+%60getting-started.md%60%0A%2A+Edit+the+%22front+matter%22+section+at+the+top+of+the+page+%28weight+controls+how+its+ordered+amongst+other+pages+in+the+same+directory%3B+lowest+number+first%29.%0A%2A+Add+a+good+commit+message+at+the+bottom+of+the+page+%28%3C80+characters%3B+use+the+extended+description+field+for+more+detail%29.%0A%2A+Create+a+new+branch+so+you+can+preview+your+new+file+and+request+a+review+via+Pull+Request.%0A" target=_blank><i class="fa fa-edit fa-fw"></i> Create child page</a>
<a href="https://github.com/apache/dubbo-website/issues/new?title=How%20to%20implement%20a%20fully%20asynchronous%20calls%20chain%20based%20on%20Dubbo" target=_blank><i class="fab fa-github fa-fw"></i> Create an issue</a>
<a href=https://github.com/apache/dubbo/issues/new target=_blank><i class="fas fa-tasks fa-fw"></i> Create project issue</a></div><nav id=TableOfContents><ul><li><a href=#asynchronous-mode-before-version-26x>Asynchronous mode before version 2.6.x</a></li><li><a href=#enhancement-based-on-completablefuture-in-version-270>Enhancement based on CompletableFuture in version 2.7.0</a></li><li><a href=#example-1completablefuture-interface>example 1:CompletableFuture interface</a></li><li><a href=#example-2synchronous-interface-uses-annotation-processor>Example 2:Synchronous interface uses Annotation Processor</a></li><li><a href=#example-3use-asynccontext>Example 3:Use AsyncContext</a></li><li><a href=#new-problems-resulted-from-asynchronization>New problems resulted from asynchronization</a><ul><li><a href=#filter-chain>Filter Chain</a></li><li><a href=#context-passing>Context passing</a></li></ul></li></ul></nav><div class="taxonomy taxonomy-terms-cloud taxo-tags"><h5 class=taxonomy-title>Tags</h5><ul class=taxonomy-terms><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/ecosystem/ data-taxonomy-term=ecosystem><span class=taxonomy-label>ecosystem</span><span class=taxonomy-count>1</span></a></li><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/news/ data-taxonomy-term=news><span class=taxonomy-label>news</span><span class=taxonomy-count>1</span></a></li><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/opentelemetry/ data-taxonomy-term=opentelemetry><span class=taxonomy-label>OpenTelemetry</span><span class=taxonomy-count>1</span></a></li><li><a class=taxonomy-term href=https://cn.dubbo.apache.org/en/tags/tracing/ data-taxonomy-term=tracing><span class=taxonomy-label>tracing</span><span class=taxonomy-count>1</span></a></li></ul></div></div></div></div></div><footer class="bg-dark py-5 row d-print-none footer-margin-0"><div class="container-fluid mx-sm-5"><div class=row><div class="col-6 col-sm-4 text-xs-center order-sm-2"><ul class="list-inline mb-0"><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title="Dubbo mailing list archive" aria-label="Dubbo mailing list archive"><a class=text-white target=_blank rel="noopener noreferrer" href=https://lists.apache.org/list.html?dev@dubbo.apache.org><i class="fa fa-envelope"></i></a></li></ul></div><div class="col-6 col-sm-4 text-right text-xs-center order-sm-3"><ul class="list-inline mb-0"><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title=GitHub aria-label=GitHub><a class=text-white target=_blank rel="noopener noreferrer" href=https://github.com/apache/dubbo><i class="fab fa-github"></i></a></li><li class="list-inline-item mx-2 h3" data-toggle=tooltip data-placement=top title="Subscribe to mailing list" aria-label="Subscribe to mailing list"><a class=text-white target=_blank rel="noopener noreferrer" href=mailto:dev-subscribe@dubbo.apache.org><i class="fa fa-envelope"></i></a></li></ul></div><div class="col-12 col-sm-4 text-center py-2 order-sm-2"><small class=text-white>&copy; 2024 The Apache Software Foundation. Apache and the Apache feather logo are trademarks of The Apache Software Foundation. All Rights Reserved</small></div></div></div></footer><div class="row pt-2 pb-2 footer-margin-0"><div class="container-fluid mx-sm-5"><div class=text-center id=my-footer><img alt=apache_logo src=/imgs/apache_logo.png><ul><li><a href=https://www.apache.org>Foundation</a></li><li><a href=https://www.apache.org/licenses/>License</a></li><li><a href=https://dubbo.apache.org/en/overview/notices/>Security</a></li><li><a href=https://www.apache.org/events/current-event>Events</a></li><li><a href=https://www.apache.org/foundation/sponsorship.html>Sponsorship</a></li><li><a href=https://privacy.apache.org/policies/privacy-policy-public.html>Privacy</a></li><li><a href=https://www.apache.org/foundation/thanks.html>Thanks</a></li></ul></div></div></div><script src=/js/popper.min.js integrity=sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49 crossorigin=anonymous></script><script src=/js/bootstrap.min.js integrity=sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy crossorigin=anonymous></script><script src=/js/main.min.b075178d232d3b0039b3cb6af2fc2e9d90071820167a60f4eea3a79169975ee8.js integrity="sha256-sHUXjSMtOwA5s8tq8vwunZAHGCAWemD07qOnkWmXXug=" crossorigin=anonymous></script><script async src=https://widget.kapa.ai/kapa-widget.bundle.js data-website-id=d763c4f2-f871-400b-aeca-d986c4af73c2 data-project-name="Apache Dubbo" data-project-color=#E8442E data-button-text="Ask AI" data-search-mode-enabled=true data-modal-open-on-command-k=true data-modal-disclaimer="The AI supports multiple languages, but it may not be accessible in China due to recaptcha, a proxy is required." data-project-logo=https://pbs.twimg.com/profile_images/1011849068283191302/FJbH5vbF_400x400.jpg data-modal-example-questions="What is Apache Dubbo?,How to run Apache Dubbo?" data-button-position-top data-button-position-right=20px data-button-position-bottom=200px data-button-position-left></script><script>(function(e,t,n,s){e[s]=e[s]||[];var a=t.getElementsByTagName(n)[0],i=t.createElement(n);i.async=!0,i.id="beacon-aplus",i.setAttribute("exparams","userid=&aplus&sidx=aplusSidex&ckx=aplusCkx"),i.src="//g.alicdn.com/alilog/mlog/aplus_v2.js",i.crossorigin="anonymous",a.parentNode.insertBefore(i,a)})(window,document,"script","aplus_queue"),function(e){var t=e.createElement("script");t.type="text/javascript",t.async=!0,t.src="//g.alicdn.com/aes/??tracker/3.3.4/index.js,tracker-plugin-pv/3.0.5/index.js,tracker-plugin-event/3.0.0/index.js,tracker-plugin-autolog/3.0.3/index.js,tracker-plugin-survey/3.0.3/index.js,tracker-plugin-jserror/3.0.3/index.js,tracker-plugin-resourceError/3.0.3/index.js",t.onload=function(){window.AES_CONFIG=window.AES_CONFIG||{env:"prod"},window.aes=new AES({pid:"zN245h",user_type:6}),window.AESPluginAutologConfig={exposure:"auto"},window.AEMPluginInstances=[aes.use(AESPluginPV,window.AESPluginPVConfig||{enableHistory:!0}),aes.use(AESPluginEvent,window.AESPluginEventConfig||{}),aes.use(AESPluginSurvey,window.AESPluginEventConfig||{}),aes.use(AESPluginAutolog,window.AESPluginAutologConfig||{}),aes.use(AESPluginJSError,window.AESPluginJSError||{}),aes.use(AESPluginResourceError,window.AESPluginResourceError||{})]},setTimeout(function(){e.getElementsByTagName("body")[0].appendChild(t)},800)}(document)</script></body></html>