blob: 805ac079160fe27681ad5e19ce96cf21a8000ddd [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/docs/v2.7/user/rest/><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>REST support | Apache Dubbo</title><meta property="og:title" content="REST support">
<meta property="og:description" content="Develop RESTful application in Dubbo"><meta property="og:type" content="article"><meta property="og:url" content="https://cn.dubbo.apache.org/en/docs/v2.7/user/rest/"><meta property="article:section" content="docs"><meta property="article:modified_time" content="2022-08-07T00:02:07+08:00"><meta itemprop=name content="REST support"><meta itemprop=description content="Develop RESTful application in Dubbo"><meta itemprop=dateModified content="2022-08-07T00:02:07+08:00"><meta itemprop=wordCount content="8939"><meta itemprop=keywords content><meta name=twitter:card content="summary"><meta name=twitter:title content="REST support"><meta name=twitter:description content="Develop RESTful application in Dubbo"><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="Develop RESTful application in Dubbo"><meta property="og:description" content="Develop RESTful application in Dubbo"><meta name=twitter:description content="Develop RESTful application in Dubbo"><meta property="og:url" content="https://cn.dubbo.apache.org/en/docs/v2.7/user/rest/"><meta property="og:title" content="REST support"><meta name=twitter:title content="REST support"><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 href=/en/blog/><span>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-endocsv27userrest").addClass("active"),$("#td-section-nav #m-endocsv27userrest-li span").addClass("td-sidebar-nav-active-item"),$("#td-section-nav #m-endocsv27userrest").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-endocsv27userrest-li").siblings("li").addClass("show"),$("#td-section-nav #m-endocsv27userrest-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-endocs-li><ul class=ul-1><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27-li><input type=checkbox id=m-endocsv27-check>
<label for=m-endocsv27-check><a href=/en/docs/v2.7/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27><span>Dubbo 2.7</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27user-li><input type=checkbox id=m-endocsv27user-check>
<label for=m-endocsv27user-check><a href=/en/docs/v2.7/user/ title="User Documentation" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27user><span>User</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userpreface-li><input type=checkbox id=m-endocsv27userpreface-check>
<label for=m-endocsv27userpreface-check><a href=/en/docs/v2.7/user/preface/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userpreface><span>Preface</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userprefacebackground-li><input type=checkbox id=m-endocsv27userprefacebackground-check>
<label for=m-endocsv27userprefacebackground-check><a href=/en/docs/v2.7/user/preface/background/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userprefacebackground><span>Background</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userprefacerequirements-li><input type=checkbox id=m-endocsv27userprefacerequirements-check>
<label for=m-endocsv27userprefacerequirements-check><a href=/en/docs/v2.7/user/preface/requirements/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userprefacerequirements><span>Requirements</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userprefacearchitecture-li><input type=checkbox id=m-endocsv27userprefacearchitecture-check>
<label for=m-endocsv27userprefacearchitecture-check><a href=/en/docs/v2.7/user/preface/architecture/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userprefacearchitecture><span>Architecture</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userprefaceusage-li><input type=checkbox id=m-endocsv27userprefaceusage-check>
<label for=m-endocsv27userprefaceusage-check><a href=/en/docs/v2.7/user/preface/usage/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userprefaceusage><span>Usage</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userquick-start-li><input type=checkbox id=m-endocsv27userquick-start-check>
<label for=m-endocsv27userquick-start-check><a href=/en/docs/v2.7/user/quick-start/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userquick-start><span>Quick start</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userdependencies-li><input type=checkbox id=m-endocsv27userdependencies-check>
<label for=m-endocsv27userdependencies-check><a href=/en/docs/v2.7/user/dependencies/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userdependencies><span>Dependencies</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27usermaturity-li><input type=checkbox id=m-endocsv27usermaturity-check>
<label for=m-endocsv27usermaturity-check><a href=/en/docs/v2.7/user/maturity/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27usermaturity><span>Maturity</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userconfiguration-li><input type=checkbox id=m-endocsv27userconfiguration-check>
<label for=m-endocsv27userconfiguration-check><a href=/en/docs/v2.7/user/configuration/ title="Dubbo Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userconfiguration><span>Configuration</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userconfigurationxml-li><input type=checkbox id=m-endocsv27userconfigurationxml-check>
<label for=m-endocsv27userconfigurationxml-check><a href=/en/docs/v2.7/user/configuration/xml/ title="XML Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userconfigurationxml><span>XML</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userconfigurationproperties-li><input type=checkbox id=m-endocsv27userconfigurationproperties-check>
<label for=m-endocsv27userconfigurationproperties-check><a href=/en/docs/v2.7/user/configuration/properties/ title="Properties Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userconfigurationproperties><span>Properties</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userconfigurationapi-li><input type=checkbox id=m-endocsv27userconfigurationapi-check>
<label for=m-endocsv27userconfigurationapi-check><a href=/en/docs/v2.7/user/configuration/api/ title="API Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userconfigurationapi><span>API</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userconfigurationannotation-li><input type=checkbox id=m-endocsv27userconfigurationannotation-check>
<label for=m-endocsv27userconfigurationannotation-check><a href=/en/docs/v2.7/user/configuration/annotation/ title="Annotation Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userconfigurationannotation><span>Annotation</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userconfigurationconfiguration-load-process-li><input type=checkbox id=m-endocsv27userconfigurationconfiguration-load-process-check>
<label for=m-endocsv27userconfigurationconfiguration-load-process-check><a href=/en/docs/v2.7/user/configuration/configuration-load-process/ title="Configuration Loading Process" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userconfigurationconfiguration-load-process><span>Loading Process</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userexamples-li><input type=checkbox id=m-endocsv27userexamples-check>
<label for=m-endocsv27userexamples-check><a href=/en/docs/v2.7/user/examples/ title="Dubbo Examples" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userexamples><span>Examples</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplespreflight-check-li><input type=checkbox id=m-endocsv27userexamplespreflight-check-check>
<label for=m-endocsv27userexamplespreflight-check-check><a href=/en/docs/v2.7/user/examples/preflight-check/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplespreflight-check><span>Preflight Check</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesfault-tolerent-strategy-li><input type=checkbox id=m-endocsv27userexamplesfault-tolerent-strategy-check>
<label for=m-endocsv27userexamplesfault-tolerent-strategy-check><a href=/en/docs/v2.7/user/examples/fault-tolerent-strategy/ title="Fault Tolerance Strategy" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesfault-tolerent-strategy><span>Fault Tolerance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesloadbalance-li><input type=checkbox id=m-endocsv27userexamplesloadbalance-check>
<label for=m-endocsv27userexamplesloadbalance-check><a href=/en/docs/v2.7/user/examples/loadbalance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesloadbalance><span>Load Balance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesthread-model-li><input type=checkbox id=m-endocsv27userexamplesthread-model-check>
<label for=m-endocsv27userexamplesthread-model-check><a href=/en/docs/v2.7/user/examples/thread-model/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesthread-model><span>Thread Model</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesexplicit-target-li><input type=checkbox id=m-endocsv27userexamplesexplicit-target-check>
<label for=m-endocsv27userexamplesexplicit-target-check><a href=/en/docs/v2.7/user/examples/explicit-target/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesexplicit-target><span>Explicit Target</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplessubscribe-only-li><input type=checkbox id=m-endocsv27userexamplessubscribe-only-check>
<label for=m-endocsv27userexamplessubscribe-only-check><a href=/en/docs/v2.7/user/examples/subscribe-only/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplessubscribe-only><span>Subscribe Only</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesmulti-protocols-li><input type=checkbox id=m-endocsv27userexamplesmulti-protocols-check>
<label for=m-endocsv27userexamplesmulti-protocols-check><a href=/en/docs/v2.7/user/examples/multi-protocols/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesmulti-protocols><span>Multiple Protocols</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesmulti-registry-li><input type=checkbox id=m-endocsv27userexamplesmulti-registry-check>
<label for=m-endocsv27userexamplesmulti-registry-check><a href=/en/docs/v2.7/user/examples/multi-registry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesmulti-registry><span>Multiple Registries</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesservice-group-li><input type=checkbox id=m-endocsv27userexamplesservice-group-check>
<label for=m-endocsv27userexamplesservice-group-check><a href=/en/docs/v2.7/user/examples/service-group/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesservice-group><span>Service Group</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesstatic-service-li><input type=checkbox id=m-endocsv27userexamplesstatic-service-check>
<label for=m-endocsv27userexamplesstatic-service-check><a href=/en/docs/v2.7/user/examples/static-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesstatic-service><span>Static Service</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesmulti-versions-li><input type=checkbox id=m-endocsv27userexamplesmulti-versions-check>
<label for=m-endocsv27userexamplesmulti-versions-check><a href=/en/docs/v2.7/user/examples/multi-versions/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesmulti-versions><span>Multiple Versions</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesgroup-merger-li><input type=checkbox id=m-endocsv27userexamplesgroup-merger-check>
<label for=m-endocsv27userexamplesgroup-merger-check><a href=/en/docs/v2.7/user/examples/group-merger/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesgroup-merger><span>Group Merger</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesparameter-validation-li><input type=checkbox id=m-endocsv27userexamplesparameter-validation-check>
<label for=m-endocsv27userexamplesparameter-validation-check><a href=/en/docs/v2.7/user/examples/parameter-validation/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesparameter-validation><span>Parameter Validation</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesresult-cache-li><input type=checkbox id=m-endocsv27userexamplesresult-cache-check>
<label for=m-endocsv27userexamplesresult-cache-check><a href=/en/docs/v2.7/user/examples/result-cache/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesresult-cache><span>Cache Result</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesbroadcast-resp-collect-li><input type=checkbox id=m-endocsv27userexamplesbroadcast-resp-collect-check>
<label for=m-endocsv27userexamplesbroadcast-resp-collect-check><a href=/en/docs/v2.7/user/examples/broadcast-resp-collect/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesbroadcast-resp-collect><span>Collect Broadcast Responses</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesgeneric-invoke-with-json-li><input type=checkbox id=m-endocsv27userexamplesgeneric-invoke-with-json-check>
<label for=m-endocsv27userexamplesgeneric-invoke-with-json-check><a href=/en/docs/v2.7/user/examples/generic-invoke-with-json/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesgeneric-invoke-with-json><span>json generic invoke</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesmsgpack-serialization-li><input type=checkbox id=m-endocsv27userexamplesmsgpack-serialization-check>
<label for=m-endocsv27userexamplesmsgpack-serialization-check><a href=/en/docs/v2.7/user/examples/msgpack-serialization/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesmsgpack-serialization><span>msgpack serialization</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesprovider-timeout-release-li><input type=checkbox id=m-endocsv27userexamplesprovider-timeout-release-check>
<label for=m-endocsv27userexamplesprovider-timeout-release-check><a href=/en/docs/v2.7/user/examples/provider-timeout-release/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesprovider-timeout-release><span>provider timeout release</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesinvoke-with-specified-ip-li><input type=checkbox id=m-endocsv27userexamplesinvoke-with-specified-ip-check>
<label for=m-endocsv27userexamplesinvoke-with-specified-ip-check><a href=/en/docs/v2.7/user/examples/invoke-with-specified-ip/ title="Invoke provider with specified IP port" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesinvoke-with-specified-ip><span>Specified IP port</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesgeneric-reference-li><input type=checkbox id=m-endocsv27userexamplesgeneric-reference-check>
<label for=m-endocsv27userexamplesgeneric-reference-check><a href=/en/docs/v2.7/user/examples/generic-reference/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesgeneric-reference><span>Generic Reference</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesgeneric-service-li><input type=checkbox id=m-endocsv27userexamplesgeneric-service-check>
<label for=m-endocsv27userexamplesgeneric-service-check><a href=/en/docs/v2.7/user/examples/generic-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesgeneric-service><span>Generic Service</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesecho-service-li><input type=checkbox id=m-endocsv27userexamplesecho-service-check>
<label for=m-endocsv27userexamplesecho-service-check><a href=/en/docs/v2.7/user/examples/echo-service/ title="Echo Testing Service" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesecho-service><span>Echo Service</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplescontext-li><input type=checkbox id=m-endocsv27userexamplescontext-check>
<label for=m-endocsv27userexamplescontext-check><a href=/en/docs/v2.7/user/examples/context/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplescontext><span>Context</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesattachment-li><input type=checkbox id=m-endocsv27userexamplesattachment-check>
<label for=m-endocsv27userexamplesattachment-check><a href=/en/docs/v2.7/user/examples/attachment/ title="Implicit parameters" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesattachment><span>Attachment</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesasync-call-li><input type=checkbox id=m-endocsv27userexamplesasync-call-check>
<label for=m-endocsv27userexamplesasync-call-check><a href=/en/docs/v2.7/user/examples/async-call/ title="Asynchronous Call" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesasync-call><span>Async Call</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesasync-execute-on-provider-li><input type=checkbox id=m-endocsv27userexamplesasync-execute-on-provider-check>
<label for=m-endocsv27userexamplesasync-execute-on-provider-check><a href=/en/docs/v2.7/user/examples/async-execute-on-provider/ title="Asynchronous Execution" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesasync-execute-on-provider><span>Async Execution</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexampleslocal-call-li><input type=checkbox id=m-endocsv27userexampleslocal-call-check>
<label for=m-endocsv27userexampleslocal-call-check><a href=/en/docs/v2.7/user/examples/local-call/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexampleslocal-call><span>Local Call</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplescallback-parameter-li><input type=checkbox id=m-endocsv27userexamplescallback-parameter-check>
<label for=m-endocsv27userexamplescallback-parameter-check><a href=/en/docs/v2.7/user/examples/callback-parameter/ title="Callback parameter" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplescallback-parameter><span>Callback</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesevents-notify-li><input type=checkbox id=m-endocsv27userexamplesevents-notify-check>
<label for=m-endocsv27userexamplesevents-notify-check><a href=/en/docs/v2.7/user/examples/events-notify/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesevents-notify><span>Event Notification</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexampleslocal-stub-li><input type=checkbox id=m-endocsv27userexampleslocal-stub-check>
<label for=m-endocsv27userexampleslocal-stub-check><a href=/en/docs/v2.7/user/examples/local-stub/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexampleslocal-stub><span>Local Stub</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexampleslocal-mock-li><input type=checkbox id=m-endocsv27userexampleslocal-mock-check>
<label for=m-endocsv27userexampleslocal-mock-check><a href=/en/docs/v2.7/user/examples/local-mock/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexampleslocal-mock><span>Local Mock</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesdelay-publish-li><input type=checkbox id=m-endocsv27userexamplesdelay-publish-check>
<label for=m-endocsv27userexamplesdelay-publish-check><a href=/en/docs/v2.7/user/examples/delay-publish/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesdelay-publish><span>Delay Publish</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesconcurrency-control-li><input type=checkbox id=m-endocsv27userexamplesconcurrency-control-check>
<label for=m-endocsv27userexamplesconcurrency-control-check><a href=/en/docs/v2.7/user/examples/concurrency-control/ title="Concurrency Control" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesconcurrency-control><span>Concurrency</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesconfig-connections-li><input type=checkbox id=m-endocsv27userexamplesconfig-connections-check>
<label for=m-endocsv27userexamplesconfig-connections-check><a href=/en/docs/v2.7/user/examples/config-connections/ title="Config connections" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesconfig-connections><span>Connection</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexampleslazy-connect-li><input type=checkbox id=m-endocsv27userexampleslazy-connect-check>
<label for=m-endocsv27userexampleslazy-connect-check><a href=/en/docs/v2.7/user/examples/lazy-connect/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexampleslazy-connect><span>Lazy Connect</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesstickiness-li><input type=checkbox id=m-endocsv27userexamplesstickiness-check>
<label for=m-endocsv27userexamplesstickiness-check><a href=/en/docs/v2.7/user/examples/stickiness/ title="Stickiness Connection" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesstickiness><span>Stickiness</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplestoken-authorization-li><input type=checkbox id=m-endocsv27userexamplestoken-authorization-check>
<label for=m-endocsv27userexamplestoken-authorization-check><a href=/en/docs/v2.7/user/examples/token-authorization/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplestoken-authorization><span>Token Authorization</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesrouting-rule-li><input type=checkbox id=m-endocsv27userexamplesrouting-rule-check>
<label for=m-endocsv27userexamplesrouting-rule-check><a href=/en/docs/v2.7/user/examples/routing-rule/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesrouting-rule><span>Routing Rule</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesconfig-rule-li><input type=checkbox id=m-endocsv27userexamplesconfig-rule-check>
<label for=m-endocsv27userexamplesconfig-rule-check><a href=/en/docs/v2.7/user/examples/config-rule/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesconfig-rule><span>Configure rule</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesservice-downgrade-li><input type=checkbox id=m-endocsv27userexamplesservice-downgrade-check>
<label for=m-endocsv27userexamplesservice-downgrade-check><a href=/en/docs/v2.7/user/examples/service-downgrade/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesservice-downgrade><span>Service Downgrade</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesgraceful-shutdown-li><input type=checkbox id=m-endocsv27userexamplesgraceful-shutdown-check>
<label for=m-endocsv27userexamplesgraceful-shutdown-check><a href=/en/docs/v2.7/user/examples/graceful-shutdown/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesgraceful-shutdown><span>Graceful Shutdown</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexampleshostname-binding-li><input type=checkbox id=m-endocsv27userexampleshostname-binding-check>
<label for=m-endocsv27userexampleshostname-binding-check><a href=/en/docs/v2.7/user/examples/hostname-binding/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexampleshostname-binding><span>Hostname Binding</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexampleslogger-strategy-li><input type=checkbox id=m-endocsv27userexampleslogger-strategy-check>
<label for=m-endocsv27userexampleslogger-strategy-check><a href=/en/docs/v2.7/user/examples/logger-strategy/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexampleslogger-strategy><span>Logger Strategy</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesaccesslog-li><input type=checkbox id=m-endocsv27userexamplesaccesslog-check>
<label for=m-endocsv27userexamplesaccesslog-check><a href=/en/docs/v2.7/user/examples/accesslog/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesaccesslog><span>Access Log</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesservice-container-li><input type=checkbox id=m-endocsv27userexamplesservice-container-check>
<label for=m-endocsv27userexamplesservice-container-check><a href=/en/docs/v2.7/user/examples/service-container/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesservice-container><span>Service Container</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesreference-config-cache-li><input type=checkbox id=m-endocsv27userexamplesreference-config-cache-check>
<label for=m-endocsv27userexamplesreference-config-cache-check><a href=/en/docs/v2.7/user/examples/reference-config-cache/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesreference-config-cache><span>ReferenceConfig Cache</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesregistry-only-li><input type=checkbox id=m-endocsv27userexamplesregistry-only-check>
<label for=m-endocsv27userexamplesregistry-only-check><a href=/en/docs/v2.7/user/examples/registry-only/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesregistry-only><span>Register Only</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesdistributed-transaction-li><input type=checkbox id=m-endocsv27userexamplesdistributed-transaction-check>
<label for=m-endocsv27userexamplesdistributed-transaction-check><a href=/en/docs/v2.7/user/examples/distributed-transaction/ title="Distributed transaction" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesdistributed-transaction><span>Transaction</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesdump-li><input type=checkbox id=m-endocsv27userexamplesdump-check>
<label for=m-endocsv27userexamplesdump-check><a href=/en/docs/v2.7/user/examples/dump/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesdump><span>Thread Dump</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userexamplesnetty4-li><input type=checkbox id=m-endocsv27userexamplesnetty4-check>
<label for=m-endocsv27userexamplesnetty4-check><a href=/en/docs/v2.7/user/examples/netty4/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userexamplesnetty4><span>Netty4</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userreferences-li><input type=checkbox id=m-endocsv27userreferences-check>
<label for=m-endocsv27userreferences-check><a href=/en/docs/v2.7/user/references/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userreferences><span>References</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userreferencesxml-li><input type=checkbox id=m-endocsv27userreferencesxml-check>
<label for=m-endocsv27userreferencesxml-check><a href=/en/docs/v2.7/user/references/xml/ title="Schema Configuration Reference" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userreferencesxml><span>XML</span></a></label><ul class="ul-5 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-application-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-application-check>
<label for=m-endocsv27userreferencesxmldubbo-application-check><a href=/en/docs/v2.7/user/references/xml/dubbo-application/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-application><span>dubbo:application</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-argument-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-argument-check>
<label for=m-endocsv27userreferencesxmldubbo-argument-check><a href=/en/docs/v2.7/user/references/xml/dubbo-argument/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-argument><span>dubbo:argument</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-config-center-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-config-center-check>
<label for=m-endocsv27userreferencesxmldubbo-config-center-check><a href=/en/docs/v2.7/user/references/xml/dubbo-config-center/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-config-center><span>dubbo:config-center</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-consumer-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-consumer-check>
<label for=m-endocsv27userreferencesxmldubbo-consumer-check><a href=/en/docs/v2.7/user/references/xml/dubbo-consumer/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-consumer><span>dubbo:consumer</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-method-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-method-check>
<label for=m-endocsv27userreferencesxmldubbo-method-check><a href=/en/docs/v2.7/user/references/xml/dubbo-method/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-method><span>dubbo:method</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-module-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-module-check>
<label for=m-endocsv27userreferencesxmldubbo-module-check><a href=/en/docs/v2.7/user/references/xml/dubbo-module/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-module><span>dubbo:module</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-monitor-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-monitor-check>
<label for=m-endocsv27userreferencesxmldubbo-monitor-check><a href=/en/docs/v2.7/user/references/xml/dubbo-monitor/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-monitor><span>dubbo:monitor</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-parameter-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-parameter-check>
<label for=m-endocsv27userreferencesxmldubbo-parameter-check><a href=/en/docs/v2.7/user/references/xml/dubbo-parameter/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-parameter><span>dubbo:parameter</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-protocol-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-protocol-check>
<label for=m-endocsv27userreferencesxmldubbo-protocol-check><a href=/en/docs/v2.7/user/references/xml/dubbo-protocol/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-protocol><span>dubbo:protocol</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-provider-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-provider-check>
<label for=m-endocsv27userreferencesxmldubbo-provider-check><a href=/en/docs/v2.7/user/references/xml/dubbo-provider/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-provider><span>dubbo:provider</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-reference-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-reference-check>
<label for=m-endocsv27userreferencesxmldubbo-reference-check><a href=/en/docs/v2.7/user/references/xml/dubbo-reference/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-reference><span>dubbo:reference</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-registry-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-registry-check>
<label for=m-endocsv27userreferencesxmldubbo-registry-check><a href=/en/docs/v2.7/user/references/xml/dubbo-registry/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-registry><span>dubbo:registry</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesxmldubbo-service-li><input type=checkbox id=m-endocsv27userreferencesxmldubbo-service-check>
<label for=m-endocsv27userreferencesxmldubbo-service-check><a href=/en/docs/v2.7/user/references/xml/dubbo-service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesxmldubbo-service><span>dubbo:service</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userreferencesprotocol-li><input type=checkbox id=m-endocsv27userreferencesprotocol-check>
<label for=m-endocsv27userreferencesprotocol-check><a href=/en/docs/v2.7/user/references/protocol/ title="Protocol References" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userreferencesprotocol><span>Protocol</span></a></label><ul class="ul-5 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocoldubbo-li><input type=checkbox id=m-endocsv27userreferencesprotocoldubbo-check>
<label for=m-endocsv27userreferencesprotocoldubbo-check><a href=/en/docs/v2.7/user/references/protocol/dubbo/ title="dubbo protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocoldubbo><span>dubbo://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolrest-li><input type=checkbox id=m-endocsv27userreferencesprotocolrest-check>
<label for=m-endocsv27userreferencesprotocolrest-check><a href=/en/docs/v2.7/user/references/protocol/rest/ title="rest protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolrest><span>rest://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolhttp-li><input type=checkbox id=m-endocsv27userreferencesprotocolhttp-check>
<label for=m-endocsv27userreferencesprotocolhttp-check><a href=/en/docs/v2.7/user/references/protocol/http/ title="http protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolhttp><span>http://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolhessian-li><input type=checkbox id=m-endocsv27userreferencesprotocolhessian-check>
<label for=m-endocsv27userreferencesprotocolhessian-check><a href=/en/docs/v2.7/user/references/protocol/hessian/ title="hessian protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolhessian><span>hessian://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolredis-li><input type=checkbox id=m-endocsv27userreferencesprotocolredis-check>
<label for=m-endocsv27userreferencesprotocolredis-check><a href=/en/docs/v2.7/user/references/protocol/redis/ title="redis protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolredis><span>redis://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolthrift-li><input type=checkbox id=m-endocsv27userreferencesprotocolthrift-check>
<label for=m-endocsv27userreferencesprotocolthrift-check><a href=/en/docs/v2.7/user/references/protocol/thrift/ title="thrift protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolthrift><span>thrift://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolmemcached-li><input type=checkbox id=m-endocsv27userreferencesprotocolmemcached-check>
<label for=m-endocsv27userreferencesprotocolmemcached-check><a href=/en/docs/v2.7/user/references/protocol/memcached/ title="memcached protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolmemcached><span>memcached://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolrmi-li><input type=checkbox id=m-endocsv27userreferencesprotocolrmi-check>
<label for=m-endocsv27userreferencesprotocolrmi-check><a href=/en/docs/v2.7/user/references/protocol/rmi/ title="rmi protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolrmi><span>rmi://</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesprotocolwebservice-li><input type=checkbox id=m-endocsv27userreferencesprotocolwebservice-check>
<label for=m-endocsv27userreferencesprotocolwebservice-check><a href=/en/docs/v2.7/user/references/protocol/webservice/ title="webservice protocol" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesprotocolwebservice><span>webservice://</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userreferencesregistry-li><input type=checkbox id=m-endocsv27userreferencesregistry-check>
<label for=m-endocsv27userreferencesregistry-check><a href=/en/docs/v2.7/user/references/registry/ title="Registry Server References" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userreferencesregistry><span>Registry Server</span></a></label><ul class="ul-5 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesregistrynacos-li><input type=checkbox id=m-endocsv27userreferencesregistrynacos-check>
<label for=m-endocsv27userreferencesregistrynacos-check><a href=/en/docs/v2.7/user/references/registry/nacos/ title="Nacos Registry Center" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesregistrynacos><span>Nacos</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesregistryzookeeper-li><input type=checkbox id=m-endocsv27userreferencesregistryzookeeper-check>
<label for=m-endocsv27userreferencesregistryzookeeper-check><a href=/en/docs/v2.7/user/references/registry/zookeeper/ title="Zookeeper Registry Server" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesregistryzookeeper><span>Zookeeper</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesregistrymulticast-li><input type=checkbox id=m-endocsv27userreferencesregistrymulticast-check>
<label for=m-endocsv27userreferencesregistrymulticast-check><a href=/en/docs/v2.7/user/references/registry/multicast/ title="Multicast Registry" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesregistrymulticast><span>Multicast</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesregistryredis-li><input type=checkbox id=m-endocsv27userreferencesregistryredis-check>
<label for=m-endocsv27userreferencesregistryredis-check><a href=/en/docs/v2.7/user/references/registry/redis/ title="Redis Registry Server" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesregistryredis><span>Redis</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesregistrysimple-li><input type=checkbox id=m-endocsv27userreferencesregistrysimple-check>
<label for=m-endocsv27userreferencesregistrysimple-check><a href=/en/docs/v2.7/user/references/registry/simple/ title="Simple Registry Server" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesregistrysimple><span>Simple</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesmetadata-li><input type=checkbox id=m-endocsv27userreferencesmetadata-check>
<label for=m-endocsv27userreferencesmetadata-check><a href=/en/docs/v2.7/user/references/metadata/ title="Metadata Reference" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesmetadata><span>Metadata</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesapi-li><input type=checkbox id=m-endocsv27userreferencesapi-check>
<label for=m-endocsv27userreferencesapi-check><a href=/en/docs/v2.7/user/references/api/ title="API Reference" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesapi><span>API</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesqos-li><input type=checkbox id=m-endocsv27userreferencesqos-check>
<label for=m-endocsv27userreferencesqos-check><a href=/en/docs/v2.7/user/references/qos/ title="Qos Command Usage " class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesqos><span>Qos</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencestelnet-li><input type=checkbox id=m-endocsv27userreferencestelnet-check>
<label for=m-endocsv27userreferencestelnet-check><a href=/en/docs/v2.7/user/references/telnet/ title="Telnet Command Reference" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencestelnet><span>Telnet</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userreferencesmaven-li><input type=checkbox id=m-endocsv27userreferencesmaven-check>
<label for=m-endocsv27userreferencesmaven-check><a href=/en/docs/v2.7/user/references/maven/ title="Maven Plugin Reference" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userreferencesmaven><span>Maven</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userbest-practice-li><input type=checkbox id=m-endocsv27userbest-practice-check>
<label for=m-endocsv27userbest-practice-check><a href=/en/docs/v2.7/user/best-practice/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userbest-practice><span>Best practice</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userrecommend-li><input type=checkbox id=m-endocsv27userrecommend-check>
<label for=m-endocsv27userrecommend-check><a href=/en/docs/v2.7/user/recommend/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userrecommend><span>Recommended usage</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27usercapacity-plan-li><input type=checkbox id=m-endocsv27usercapacity-plan-check>
<label for=m-endocsv27usercapacity-plan-check><a href=/en/docs/v2.7/user/capacity-plan/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27usercapacity-plan><span>Capacity plan</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userperf-test-li><input type=checkbox id=m-endocsv27userperf-test-check>
<label for=m-endocsv27userperf-test-check><a href=/en/docs/v2.7/user/perf-test/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userperf-test><span>Performance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27usercoveragence-li><input type=checkbox id=m-endocsv27usercoveragence-check>
<label for=m-endocsv27usercoveragence-check><a href=/en/docs/v2.7/user/coveragence/ title="Test coverage report" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27usercoveragence><span>Test coverage</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userbenchmark-tool-li><input type=checkbox id=m-endocsv27userbenchmark-tool-check>
<label for=m-endocsv27userbenchmark-tool-check><a href=/en/docs/v2.7/user/benchmark-tool/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userbenchmark-tool><span>Benchmark Suite</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userrest-li><input type=checkbox id=m-endocsv27userrest-check>
<label for=m-endocsv27userrest-check><a href=/en/docs/v2.7/user/rest/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userrest><span>REST support</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27usersimple-monitor-li><input type=checkbox id=m-endocsv27usersimple-monitor-check>
<label for=m-endocsv27usersimple-monitor-check><a href=/en/docs/v2.7/user/simple-monitor/ title="Simple Monitor" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27usersimple-monitor><span>Simple monitor</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userlanguages-li><input type=checkbox id=m-endocsv27userlanguages-check>
<label for=m-endocsv27userlanguages-check><a href=/en/docs/v2.7/user/languages/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userlanguages><span>Other Languages</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27userlanguageserlang-li><input type=checkbox id=m-endocsv27userlanguageserlang-check>
<label for=m-endocsv27userlanguageserlang-check><a href=/en/docs/v2.7/user/languages/erlang/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27userlanguageserlang><span>Erlang</span></a></label><ul class="ul-5 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userlanguageserlangquick-start-li><input type=checkbox id=m-endocsv27userlanguageserlangquick-start-check>
<label for=m-endocsv27userlanguageserlangquick-start-check><a href=/en/docs/v2.7/user/languages/erlang/quick-start/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userlanguageserlangquick-start><span>Quick Start</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userlanguageserlangreference-li><input type=checkbox id=m-endocsv27userlanguageserlangreference-check>
<label for=m-endocsv27userlanguageserlangreference-check><a href=/en/docs/v2.7/user/languages/erlang/reference/ title="Consumer Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userlanguageserlangreference><span>Consumer</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userlanguageserlangservice-li><input type=checkbox id=m-endocsv27userlanguageserlangservice-check>
<label for=m-endocsv27userlanguageserlangservice-check><a href=/en/docs/v2.7/user/languages/erlang/service/ title="Provider Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userlanguageserlangservice><span>Provider</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27userlanguageserlangserialization-li><input type=checkbox id=m-endocsv27userlanguageserlangserialization-check>
<label for=m-endocsv27userlanguageserlangserialization-check><a href=/en/docs/v2.7/user/languages/erlang/serialization/ title="Protocol Configuration" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27userlanguageserlangserialization><span>Protocol</span></a></label></li></ul></li></ul></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27dev-li><input type=checkbox id=m-endocsv27dev-check>
<label for=m-endocsv27dev-check><a href=/en/docs/v2.7/dev/ title="Dubbo Developer Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27dev><span>Developer</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devbuild-li><input type=checkbox id=m-endocsv27devbuild-check>
<label for=m-endocsv27devbuild-check><a href=/en/docs/v2.7/dev/build/ title="Source Code Build" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devbuild><span>Build</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devdesign-li><input type=checkbox id=m-endocsv27devdesign-check>
<label for=m-endocsv27devdesign-check><a href=/en/docs/v2.7/dev/design/ title="Framework Design" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devdesign><span>Design</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devspi-li><input type=checkbox id=m-endocsv27devspi-check>
<label for=m-endocsv27devspi-check><a href=/en/docs/v2.7/dev/spi/ title="SPI Loading" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devspi><span>SPI</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplementation-li><input type=checkbox id=m-endocsv27devimplementation-check>
<label for=m-endocsv27devimplementation-check><a href=/en/docs/v2.7/dev/implementation/ title="Implementation details" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplementation><span>Implementation</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27devprincipals-li><input type=checkbox id=m-endocsv27devprincipals-check>
<label for=m-endocsv27devprincipals-check><a href=/en/docs/v2.7/dev/principals/ title="Dubbo Design Principals" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27devprincipals><span>Design Principals</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devprincipalscode-detail-li><input type=checkbox id=m-endocsv27devprincipalscode-detail-check>
<label for=m-endocsv27devprincipalscode-detail-check><a href=/en/docs/v2.7/dev/principals/code-detail/ title="The Devil Is In The Details" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devprincipalscode-detail><span>Details</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devprincipalsconfiguration-li><input type=checkbox id=m-endocsv27devprincipalsconfiguration-check>
<label for=m-endocsv27devprincipalsconfiguration-check><a href=/en/docs/v2.7/dev/principals/configuration/ title="The Configuration Design" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devprincipalsconfiguration><span>Configuration</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devprincipalsdummy-li><input type=checkbox id=m-endocsv27devprincipalsdummy-check>
<label for=m-endocsv27devprincipalsdummy-check><a href=/en/docs/v2.7/dev/principals/dummy/ title=' "Fool-proof" Design' class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devprincipalsdummy><span>Fool-proof</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devprincipalsexpansibility-li><input type=checkbox id=m-endocsv27devprincipalsexpansibility-check>
<label for=m-endocsv27devprincipalsexpansibility-check><a href=/en/docs/v2.7/dev/principals/expansibility/ title="Talk About Expansion Of Extension And Incremental Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devprincipalsexpansibility><span>Extensibility</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devprincipalsextension-li><input type=checkbox id=m-endocsv27devprincipalsextension-check>
<label for=m-endocsv27devprincipalsextension-check><a href=/en/docs/v2.7/dev/principals/extension/ title="Extension Points To Reconstruct" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devprincipalsextension><span>Extension</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devprincipalsgeneral-knowledge-li><input type=checkbox id=m-endocsv27devprincipalsgeneral-knowledge-check>
<label for=m-endocsv27devprincipalsgeneral-knowledge-check><a href=/en/docs/v2.7/dev/principals/general-knowledge/ title="Some In The Design Of The Basic Common Sense" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devprincipalsgeneral-knowledge><span>General Rule</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devprincipalsrobustness-li><input type=checkbox id=m-endocsv27devprincipalsrobustness-check>
<label for=m-endocsv27devprincipalsrobustness-check><a href=/en/docs/v2.7/dev/principals/robustness/ title="The Robustness Of The Design Implementation" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devprincipalsrobustness><span>Robustness</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27devimpls-li><input type=checkbox id=m-endocsv27devimpls-check>
<label for=m-endocsv27devimpls-check><a href=/en/docs/v2.7/dev/impls/ title="SPI Extension Implementations" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27devimpls><span>SPI Impls</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsprotocol-li><input type=checkbox id=m-endocsv27devimplsprotocol-check>
<label for=m-endocsv27devimplsprotocol-check><a href=/en/docs/v2.7/dev/impls/protocol/ title="Protocol Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsprotocol><span>Protocol</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsfilter-li><input type=checkbox id=m-endocsv27devimplsfilter-check>
<label for=m-endocsv27devimplsfilter-check><a href=/en/docs/v2.7/dev/impls/filter/ title="Filter Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsfilter><span>Filter</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsinvoker-listener-li><input type=checkbox id=m-endocsv27devimplsinvoker-listener-check>
<label for=m-endocsv27devimplsinvoker-listener-check><a href=/en/docs/v2.7/dev/impls/invoker-listener/ title="InvokerListener Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsinvoker-listener><span>InvokerListener</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsexporter-listener-li><input type=checkbox id=m-endocsv27devimplsexporter-listener-check>
<label for=m-endocsv27devimplsexporter-listener-check><a href=/en/docs/v2.7/dev/impls/exporter-listener/ title="ExporterListener Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsexporter-listener><span>ExporterListener</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplscluster-li><input type=checkbox id=m-endocsv27devimplscluster-check>
<label for=m-endocsv27devimplscluster-check><a href=/en/docs/v2.7/dev/impls/cluster/ title="Cluster Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplscluster><span>Cluster</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsrouter-li><input type=checkbox id=m-endocsv27devimplsrouter-check>
<label for=m-endocsv27devimplsrouter-check><a href=/en/docs/v2.7/dev/impls/router/ title="Router Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsrouter><span>Router</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsload-balance-li><input type=checkbox id=m-endocsv27devimplsload-balance-check>
<label for=m-endocsv27devimplsload-balance-check><a href=/en/docs/v2.7/dev/impls/load-balance/ title="LoadBalance Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsload-balance><span>LoadBalance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsmerger-li><input type=checkbox id=m-endocsv27devimplsmerger-check>
<label for=m-endocsv27devimplsmerger-check><a href=/en/docs/v2.7/dev/impls/merger/ title="Merger Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsmerger><span>Merger</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsregistry-li><input type=checkbox id=m-endocsv27devimplsregistry-check>
<label for=m-endocsv27devimplsregistry-check><a href=/en/docs/v2.7/dev/impls/registry/ title="Registry Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsregistry><span>Registry</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsmonitor-li><input type=checkbox id=m-endocsv27devimplsmonitor-check>
<label for=m-endocsv27devimplsmonitor-check><a href=/en/docs/v2.7/dev/impls/monitor/ title="Monitor Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsmonitor><span>Monitor</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsextension-factory-li><input type=checkbox id=m-endocsv27devimplsextension-factory-check>
<label for=m-endocsv27devimplsextension-factory-check><a href=/en/docs/v2.7/dev/impls/extension-factory/ title="ExtensionFactory Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsextension-factory><span>ExtensionFactory</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsproxy-factory-li><input type=checkbox id=m-endocsv27devimplsproxy-factory-check>
<label for=m-endocsv27devimplsproxy-factory-check><a href=/en/docs/v2.7/dev/impls/proxy-factory/ title="ProxyFactory Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsproxy-factory><span>ProxyFactory</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplscompiler-li><input type=checkbox id=m-endocsv27devimplscompiler-check>
<label for=m-endocsv27devimplscompiler-check><a href=/en/docs/v2.7/dev/impls/compiler/ title="Compiler Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplscompiler><span>Compiler</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsconfig-center-li><input type=checkbox id=m-endocsv27devimplsconfig-center-check>
<label for=m-endocsv27devimplsconfig-center-check><a href=/en/docs/v2.7/dev/impls/config-center/ title="Dubbo Configuration Center Extensions" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsconfig-center><span>Config Center</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsdispatcher-li><input type=checkbox id=m-endocsv27devimplsdispatcher-check>
<label for=m-endocsv27devimplsdispatcher-check><a href=/en/docs/v2.7/dev/impls/dispatcher/ title="Dispatcher Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsdispatcher><span>Dispatcher</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsthreadpool-li><input type=checkbox id=m-endocsv27devimplsthreadpool-check>
<label for=m-endocsv27devimplsthreadpool-check><a href=/en/docs/v2.7/dev/impls/threadpool/ title="ThreadPool Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsthreadpool><span>ThreadPool</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsserialize-li><input type=checkbox id=m-endocsv27devimplsserialize-check>
<label for=m-endocsv27devimplsserialize-check><a href=/en/docs/v2.7/dev/impls/serialize/ title="Serialization Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsserialize><span>Serialization</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsremoting-li><input type=checkbox id=m-endocsv27devimplsremoting-check>
<label for=m-endocsv27devimplsremoting-check><a href=/en/docs/v2.7/dev/impls/remoting/ title="Transporter Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsremoting><span>Transporter</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsexchanger-li><input type=checkbox id=m-endocsv27devimplsexchanger-check>
<label for=m-endocsv27devimplsexchanger-check><a href=/en/docs/v2.7/dev/impls/exchanger/ title="Exchanger Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsexchanger><span>Exchanger</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsnetworker-li><input type=checkbox id=m-endocsv27devimplsnetworker-check>
<label for=m-endocsv27devimplsnetworker-check><a href=/en/docs/v2.7/dev/impls/networker/ title="Networker Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsnetworker><span>Networker</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplstelnet-handler-li><input type=checkbox id=m-endocsv27devimplstelnet-handler-check>
<label for=m-endocsv27devimplstelnet-handler-check><a href=/en/docs/v2.7/dev/impls/telnet-handler/ title="TelnetHandler Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplstelnet-handler><span>TelnetHandler</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsstatus-checker-li><input type=checkbox id=m-endocsv27devimplsstatus-checker-check>
<label for=m-endocsv27devimplsstatus-checker-check><a href=/en/docs/v2.7/dev/impls/status-checker/ title="StatusChecker Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsstatus-checker><span>StatusChecker</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplscontainer-li><input type=checkbox id=m-endocsv27devimplscontainer-check>
<label for=m-endocsv27devimplscontainer-check><a href=/en/docs/v2.7/dev/impls/container/ title="Container Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplscontainer><span>Container</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplspage-li><input type=checkbox id=m-endocsv27devimplspage-check>
<label for=m-endocsv27devimplspage-check><a href=/en/docs/v2.7/dev/impls/page/ title="PageHandler Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplspage><span>PageHandler</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplscache-li><input type=checkbox id=m-endocsv27devimplscache-check>
<label for=m-endocsv27devimplscache-check><a href=/en/docs/v2.7/dev/impls/cache/ title="Cache Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplscache><span>Cache</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplsvalidation-li><input type=checkbox id=m-endocsv27devimplsvalidation-check>
<label for=m-endocsv27devimplsvalidation-check><a href=/en/docs/v2.7/dev/impls/validation/ title="Validation Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplsvalidation><span>Validation</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devimplslogger-adapter-li><input type=checkbox id=m-endocsv27devimplslogger-adapter-check>
<label for=m-endocsv27devimplslogger-adapter-check><a href=/en/docs/v2.7/dev/impls/logger-adapter/ title="LoggerAdapter Extension" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devimplslogger-adapter><span>LoggerAdapter</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devcontract-li><input type=checkbox id=m-endocsv27devcontract-check>
<label for=m-endocsv27devcontract-check><a href=/en/docs/v2.7/dev/contract/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devcontract><span>Public Agreement</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devrelease-li><input type=checkbox id=m-endocsv27devrelease-check>
<label for=m-endocsv27devrelease-check><a href=/en/docs/v2.7/dev/release/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devrelease><span>Versions</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devchecklist-li><input type=checkbox id=m-endocsv27devchecklist-check>
<label for=m-endocsv27devchecklist-check><a href=/en/docs/v2.7/dev/checklist/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devchecklist><span>Checklist</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devcode-smell-li><input type=checkbox id=m-endocsv27devcode-smell-check>
<label for=m-endocsv27devcode-smell-check><a href=/en/docs/v2.7/dev/code-smell/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devcode-smell><span>Bad Smell</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devcoding-li><input type=checkbox id=m-endocsv27devcoding-check>
<label for=m-endocsv27devcoding-check><a href=/en/docs/v2.7/dev/coding/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devcoding><span>Coding Convention</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27devtck-li><input type=checkbox id=m-endocsv27devtck-check>
<label for=m-endocsv27devtck-check><a href=/en/docs/v2.7/dev/tck/ title="Compatibility Test" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27devtck><span>TCK</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27admin-li><input type=checkbox id=m-endocsv27admin-check>
<label for=m-endocsv27admin-check><a href=/en/docs/v2.7/admin/ title="Admin Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27admin><span>Admin</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27adminops-li><input type=checkbox id=m-endocsv27adminops-check>
<label for=m-endocsv27adminops-check><a href=/en/docs/v2.7/admin/ops/ title="Dubbo Admin Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27adminops><span>Dubbo Admin</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopsfunctions-li><input type=checkbox id=m-endocsv27adminopsfunctions-check>
<label for=m-endocsv27adminopsfunctions-check><a href=/en/docs/v2.7/admin/ops/functions/ title="Dubbo Admin Functions" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopsfunctions><span>Functions</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopsintroduction-li><input type=checkbox id=m-endocsv27adminopsintroduction-check>
<label for=m-endocsv27adminopsintroduction-check><a href=/en/docs/v2.7/admin/ops/introduction/ title="Dubbo Admin Introductions" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopsintroduction><span>Introductions</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopssearch-li><input type=checkbox id=m-endocsv27adminopssearch-check>
<label for=m-endocsv27adminopssearch-check><a href=/en/docs/v2.7/admin/ops/search/ title="Service Search And Service Detail" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopssearch><span>Search</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopstest-li><input type=checkbox id=m-endocsv27adminopstest-check>
<label for=m-endocsv27adminopstest-check><a href=/en/docs/v2.7/admin/ops/test/ title="Service Test" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopstest><span>Test</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopsapidocs-li><input type=checkbox id=m-endocsv27adminopsapidocs-check>
<label for=m-endocsv27adminopsapidocs-check><a href=/en/docs/v2.7/admin/ops/apidocs/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopsapidocs><span>API Docs&amp;Test</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopsgovernance-li><input type=checkbox id=m-endocsv27adminopsgovernance-check>
<label for=m-endocsv27adminopsgovernance-check><a href=/en/docs/v2.7/admin/ops/governance/ title="Service Governance And Configuration Management" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopsgovernance><span>Governance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopspinpoint-li><input type=checkbox id=m-endocsv27adminopspinpoint-check>
<label for=m-endocsv27adminopspinpoint-check><a href=/en/docs/v2.7/admin/ops/pinpoint/ title="Tracking with Pinpoint" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopspinpoint><span>Pinpoint</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27adminopsskywalking-li><input type=checkbox id=m-endocsv27adminopsskywalking-check>
<label for=m-endocsv27adminopsskywalking-check><a href=/en/docs/v2.7/admin/ops/skywalking/ title="Tracing Dubbo service with Apache Skywalking" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27adminopsskywalking><span>Skywalking</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv27admininstall-li><input type=checkbox id=m-endocsv27admininstall-check>
<label for=m-endocsv27admininstall-check><a href=/en/docs/v2.7/admin/install/ title="Dubbo Installation Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv27admininstall><span>Installation</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27admininstalladmin-console-li><input type=checkbox id=m-endocsv27admininstalladmin-console-check>
<label for=m-endocsv27admininstalladmin-console-check><a href=/en/docs/v2.7/admin/install/admin-console/ title="Install Admin Console" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27admininstalladmin-console><span>Admin Console</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27admininstallprovider-demo-li><input type=checkbox id=m-endocsv27admininstallprovider-demo-check>
<label for=m-endocsv27admininstallprovider-demo-check><a href=/en/docs/v2.7/admin/install/provider-demo/ title="Install Demo Provider" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27admininstallprovider-demo><span>Demo Provider</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27admininstallconsumer-demo-li><input type=checkbox id=m-endocsv27admininstallconsumer-demo-check>
<label for=m-endocsv27admininstallconsumer-demo-check><a href=/en/docs/v2.7/admin/install/consumer-demo/ title="Install Demo Consumer" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27admininstallconsumer-demo><span>Demo Consumer</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27admininstallzookeeper-li><input type=checkbox id=m-endocsv27admininstallzookeeper-check>
<label for=m-endocsv27admininstallzookeeper-check><a href=/en/docs/v2.7/admin/install/zookeeper/ title="install Zookeeper Configuration Center" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27admininstallzookeeper><span>Config Center</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27admininstallredis-li><input type=checkbox id=m-endocsv27admininstallredis-check>
<label for=m-endocsv27admininstallredis-check><a href=/en/docs/v2.7/admin/install/redis/ title="Install Redis Register Center" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27admininstallredis><span>Register Center</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv27admininstallmonitor-center-li><input type=checkbox id=m-endocsv27admininstallmonitor-center-check>
<label for=m-endocsv27admininstallmonitor-center-check><a href=/en/docs/v2.7/admin/install/monitor-center/ title="Install Simple monitor center" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv27admininstallmonitor-center><span>Monitor Center</span></a></label></li></ul></li></ul></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv30-li><input type=checkbox id=m-endocsv30-check>
<label for=m-endocsv30-check><a href=/en/docs/v3.0/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30><span>Dubbo 3.0</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30loadbalance-li><input type=checkbox id=m-endocsv30loadbalance-check>
<label for=m-endocsv30loadbalance-check><a href=/en/docs/v3.0/loadbalance/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30loadbalance><span>Load Balance</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30whats-new-in-dubbo3-li><input type=checkbox id=m-endocsv30whats-new-in-dubbo3-check>
<label for=m-endocsv30whats-new-in-dubbo3-check><a href=/en/docs/v3.0/whats-new-in-dubbo3/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30whats-new-in-dubbo3><span>What's new in Apache Dubbo 3.x?</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv30references-li><input type=checkbox id=m-endocsv30references-check>
<label for=m-endocsv30references-check><a href=/en/docs/v3.0/references/ title="Function Reference Manual" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30references><span>Reference</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv30referenceslifecycle-li><input type=checkbox id=m-endocsv30referenceslifecycle-check>
<label for=m-endocsv30referenceslifecycle-check><a href=/en/docs/v3.0/references/lifecycle/ title="Align with Kubernetes Lifecycle" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30referenceslifecycle><span>Probe</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30referenceslifecyclebrief-li><input type=checkbox id=m-endocsv30referenceslifecyclebrief-check>
<label for=m-endocsv30referenceslifecyclebrief-check><a href=/en/docs/v3.0/references/lifecycle/brief/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30referenceslifecyclebrief><span>Brief</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30referenceslifecycleliveness-li><input type=checkbox id=m-endocsv30referenceslifecycleliveness-check>
<label for=m-endocsv30referenceslifecycleliveness-check><a href=/en/docs/v3.0/references/lifecycle/liveness/ title="Liveness Probe" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30referenceslifecycleliveness><span>Liveness</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30referenceslifecyclereadiness-li><input type=checkbox id=m-endocsv30referenceslifecyclereadiness-check>
<label for=m-endocsv30referenceslifecyclereadiness-check><a href=/en/docs/v3.0/references/lifecycle/readiness/ title="Readiness Probe" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30referenceslifecyclereadiness><span>Readiness</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30referenceslifecyclestartup-li><input type=checkbox id=m-endocsv30referenceslifecyclestartup-check>
<label for=m-endocsv30referenceslifecyclestartup-check><a href=/en/docs/v3.0/references/lifecycle/startup/ title="Startup Probe" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30referenceslifecyclestartup><span>Startup</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv30referencesgraalvm-li><input type=checkbox id=m-endocsv30referencesgraalvm-check>
<label for=m-endocsv30referencesgraalvm-check><a href=/en/docs/v3.0/references/graalvm/ title="graalvm support" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30referencesgraalvm><span>support graalvm</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30referencesgraalvmsupport-graalvm-li><input type=checkbox id=m-endocsv30referencesgraalvmsupport-graalvm-check>
<label for=m-endocsv30referencesgraalvmsupport-graalvm-check><a href=/en/docs/v3.0/references/graalvm/support-graalvm/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30referencesgraalvmsupport-graalvm><span></span></a></label></li></ul></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv30languages-li><input type=checkbox id=m-endocsv30languages-check>
<label for=m-endocsv30languages-check><a href=/en/docs/v3.0/languages/ title="Multi-language implementation" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30languages><span>multi-language</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv30languageserlang-li><input type=checkbox id=m-endocsv30languageserlang-check>
<label for=m-endocsv30languageserlang-check><a href=/en/docs/v3.0/languages/erlang/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30languageserlang><span>Erlang</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30languageserlangquick-start-li><input type=checkbox id=m-endocsv30languageserlangquick-start-check>
<label for=m-endocsv30languageserlangquick-start-check><a href=/en/docs/v3.0/languages/erlang/quick-start/ title="Quick start " class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30languageserlangquick-start><span>Quick start</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30languageserlangreference-li><input type=checkbox id=m-endocsv30languageserlangreference-check>
<label for=m-endocsv30languageserlangreference-check><a href=/en/docs/v3.0/languages/erlang/reference/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30languageserlangreference><span>Consumer configuration</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30languageserlangservice-li><input type=checkbox id=m-endocsv30languageserlangservice-check>
<label for=m-endocsv30languageserlangservice-check><a href=/en/docs/v3.0/languages/erlang/service/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30languageserlangservice><span>Provider configuration</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30languageserlangserialization-li><input type=checkbox id=m-endocsv30languageserlangserialization-check>
<label for=m-endocsv30languageserlangserialization-check><a href=/en/docs/v3.0/languages/erlang/serialization/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30languageserlangserialization><span>Serialized configuration items</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocsv30languagesgolang-li><input type=checkbox id=m-endocsv30languagesgolang-check>
<label for=m-endocsv30languagesgolang-check><a href=/en/docs/v3.0/languages/golang/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30languagesgolang><span>golang</span></a></label><ul class="ul-4 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30languagesgolanggo-specific-li><input type=checkbox id=m-endocsv30languagesgolanggo-specific-check>
<label for=m-endocsv30languagesgolanggo-specific-check><a href=/en/docs/v3.0/languages/golang/go-specific/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30languagesgolanggo-specific><span>Go language definition service</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30languagesgolangquick-start-li><input type=checkbox id=m-endocsv30languagesgolangquick-start-check>
<label for=m-endocsv30languagesgolangquick-start-check><a href=/en/docs/v3.0/languages/golang/quick-start/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocsv30languagesgolangquick-start><span>Go quick start</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsv30languagesrust-li><input type=checkbox id=m-endocsv30languagesrust-check>
<label for=m-endocsv30languagesrust-check><a href=/en/docs3-v2/rust-sdk/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsv30languagesrust><span>Rust</span></a></label></li></ul></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocscontribution-guidelines-li><input type=checkbox id=m-endocscontribution-guidelines-check>
<label for=m-endocscontribution-guidelines-check><a href=/en/docs/contribution-guidelines/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocscontribution-guidelines><span>Contribution Guideline</span></a></label><ul class="ul-2 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocscontribution-guidelinescontributor-li><input type=checkbox id=m-endocscontribution-guidelinescontributor-check>
<label for=m-endocscontribution-guidelinescontributor-check><a href=/en/docs/contribution-guidelines/contributor/ title="Contributor Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocscontribution-guidelinescontributor><span>Contributor</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributorbecome-a-committer_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributorbecome-a-committer_dev-check>
<label for=m-endocscontribution-guidelinescontributorbecome-a-committer_dev-check><a href=/en/docs/contribution-guidelines/contributor/become-a-committer_dev/ title="How to become a Dubbo committer" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributorbecome-a-committer_dev><span>How To</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributorcla-signing-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributorcla-signing-guide_dev-check>
<label for=m-endocscontribution-guidelinescontributorcla-signing-guide_dev-check><a href=/en/docs/contribution-guidelines/contributor/cla-signing-guide_dev/ title="CLA Signing Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributorcla-signing-guide_dev><span>CLA</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributornew-contributor-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributornew-contributor-guide_dev-check>
<label for=m-endocscontribution-guidelinescontributornew-contributor-guide_dev-check><a href=/en/docs/contribution-guidelines/contributor/new-contributor-guide_dev/ title="New Contributor Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributornew-contributor-guide_dev><span>New Contributor</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributormailing-list-subscription-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributormailing-list-subscription-guide_dev-check>
<label for=m-endocscontribution-guidelinescontributormailing-list-subscription-guide_dev-check><a href=/en/docs/contribution-guidelines/contributor/mailing-list-subscription-guide_dev/ title="Mailing List Subscription Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributormailing-list-subscription-guide_dev><span>Mailing List</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributorsoftware-donation-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributorsoftware-donation-guide_dev-check>
<label for=m-endocscontribution-guidelinescontributorsoftware-donation-guide_dev-check><a href=/en/docs/contribution-guidelines/contributor/software-donation-guide_dev/ title="Software Donation Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributorsoftware-donation-guide_dev><span>Donation</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributorreporting-security-issues_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributorreporting-security-issues_dev-check>
<label for=m-endocscontribution-guidelinescontributorreporting-security-issues_dev-check><a href=/en/docs/contribution-guidelines/contributor/reporting-security-issues_dev/ title="Reporting Security Issues" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributorreporting-security-issues_dev><span>Security Issue</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributordubbo-extension-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributordubbo-extension-guide_dev-check>
<label for=m-endocscontribution-guidelinescontributordubbo-extension-guide_dev-check><a href=/en/docs/contribution-guidelines/contributor/dubbo-extension-guide_dev/ title="Extension Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributordubbo-extension-guide_dev><span>Developing Extension</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescontributortest-coverage-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescontributortest-coverage-guide_dev-check>
<label for=m-endocscontribution-guidelinescontributortest-coverage-guide_dev-check><a href=/en/docs/contribution-guidelines/contributor/test-coverage-guide_dev/ title="Test Coverage Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescontributortest-coverage-guide_dev><span>Test Coverage</span></a></label></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section with-child" id=m-endocscontribution-guidelinescommitter-li><input type=checkbox id=m-endocscontribution-guidelinescommitter-check>
<label for=m-endocscontribution-guidelinescommitter-check><a href=/en/docs/contribution-guidelines/committer/ title="Committer Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocscontribution-guidelinescommitter><span>Committer</span></a></label><ul class="ul-3 foldable"><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescommitternew-committer-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescommitternew-committer-guide_dev-check>
<label for=m-endocscontribution-guidelinescommitternew-committer-guide_dev-check><a href=/en/docs/contribution-guidelines/committer/new-committer-guide_dev/ title="Apache Committer Guide" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescommitternew-committer-guide_dev><span>Committer Guide</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescommitterrelease-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescommitterrelease-guide_dev-check>
<label for=m-endocscontribution-guidelinescommitterrelease-guide_dev-check><a href=/en/docs/contribution-guidelines/committer/release-guide_dev/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescommitterrelease-guide_dev><span>Release Guide</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescommitterlabel-an-issue-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescommitterlabel-an-issue-guide_dev-check>
<label for=m-endocscontribution-guidelinescommitterlabel-an-issue-guide_dev-check><a href=/en/docs/contribution-guidelines/committer/label-an-issue-guide_dev/ title="Label an Issue" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescommitterlabel-an-issue-guide_dev><span>Issue Guide</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescommitterwebsite-guide_dev-li><input type=checkbox id=m-endocscontribution-guidelinescommitterwebsite-guide_dev-check>
<label for=m-endocscontribution-guidelinescommitterwebsite-guide_dev-check><a href=/en/docs/contribution-guidelines/committer/website-guide_dev/ class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescommitterwebsite-guide_dev><span>Website Guide</span></a></label></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocscontribution-guidelinescommitterapache-dubbo-page_dev-li><input type=checkbox id=m-endocscontribution-guidelinescommitterapache-dubbo-page_dev-check>
<label for=m-endocscontribution-guidelinescommitterapache-dubbo-page_dev-check><a href=/en/docs/contribution-guidelines/committer/apache-dubbo-page_dev/ title="Apache Official Dubbo Page Maintenance" class="align-left pl-0 td-sidebar-link td-sidebar-link__page" id=m-endocscontribution-guidelinescommitterapache-dubbo-page_dev><span>Official Page</span></a></label></li></ul></li></ul></li><li class="td-sidebar-nav__section-title td-sidebar-nav__section without-child" id=m-endocsfaq-li><input type=checkbox id=m-endocsfaq-check>
<label for=m-endocsfaq-check><a href=/en/docs/faq/ class="align-left pl-0 td-sidebar-link td-sidebar-link__section" id=m-endocsfaq><span>FAQ - Frequently Asked Questions</span></a></label></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/docs/>Documentation</a></li><li class=breadcrumb-item><a href=https://cn.dubbo.apache.org/en/docs/v2.7/>Dubbo 2.7</a></li><li class=breadcrumb-item><a href=https://cn.dubbo.apache.org/en/docs/v2.7/user/>User</a></li><li class="breadcrumb-item active" aria-current=page><a href=https://cn.dubbo.apache.org/en/docs/v2.7/user/rest/ aria-disabled=true class="btn-link disabled">REST support</a></li></ol></nav><div class=td-content><h1>REST support</h1><div class=lead>Develop RESTful application in Dubbo</div><header class=article-meta></header><div class="pageinfo pageinfo-primary"><p>Original author: Li Shen
Document copyright: <a href=http://www.apache.org/licenses/LICENSE-2.0>Apache 2.0license Signature - No interpretation</a></p><p>Working in progress &mldr;</p></div><blockquote><p>This article is lengthy since REST involves many aspects. Besides, it refers to the document style of Spring and so on. Not only limited to usage of the framework but also strives to present the design concept of the framework and the architectural idea of an excellent application.
For people who only want to get a glimpse of Dubbo and REST, all they need is to browse through the <code>Overview</code> to <code>Introduction to Standard Java REST API: JAX-RS</code>.</p></blockquote><h2 id=content>CONTENT</h2><ul><li>Overview</li><li>Advantages of REST</li><li>Application Scenarios</li><li>Quick Start</li><li>Introduction to Standard Java REST API: JAX-RS</li><li>Details of REST Service Provider<ul><li>Implementation of HTTP POST/GET</li><li>Should Annotation be Placed in the Interface or Implementation</li><li>Support for Multiple Data Formats (JSON, XML, etc.)</li><li>Support for Chinese Characters</li><li>Additional Requirements for XML Format</li><li>Custom Serialization</li><li>Configure the Implementation of REST Server</li><li>Access Context Data</li><li>Configure the Port Number and Context Path</li><li>Configure Number of Threads and IO Threads</li><li>Configure Persistent Connection</li><li>Configure Maximum Number of HTTP Connections</li><li>Configure Timeout and HTTP Connections Per Consumer</li><li>Gzip Data Compression</li><li>Replace Part of Spring XML Configuration With Annotation</li><li>Add Custom Filter, Interceptor, etc.</li><li>Add Custom Exception Handler</li><li>Configure HTTP Log Output</li><li>Verification of Input Parameters</li><li>Should REST Services be Published Transparently</li><li>Get Headers In Dubbo Rest Provider</li></ul></li><li>Details of REST Service Consumer<ul><li>Scenario 1: Non-Dubbo Consumer Calls Dubbo REST Service</li><li>Scenario 2: Dubbo Consumer Calls Dubbo REST Service</li><li>Scenario 3: Dubbo Consumer Calls Non-Dubbo REST Service</li><li>Custom Header By Dubbo Consumer while Calling REST Service</li></ul></li><li>JAX-RS Restrictions in Dubbo</li><li>REST FAQ<ul><li>Can Dubbo REST Services be Integrated With Dubbo Registration Center and Monitoring Center?</li><li>How to Implement Load Balancing and Failover in Dubbo REST?</li><li>Can Overloaded Methods in JAX-RS Map to Single URL?</li><li>Can a Method in JAX-RS Receive Multiple Parameters Via POST?</li></ul></li><li>Possible shortcomings of Current Dubbo System (Related to REST)<ul><li>Invasiveness of Rpc Context</li><li>Limitations of Protocol Configuration</li><li>XML Naming Does Not Conform to the Convention of Spring</li></ul></li><li>REST Best Practices</li><li>Performance Benchmark<ul><li>Test Environment</li><li>Test Script</li><li>Test Result</li></ul></li><li>Extended Discussion<ul><li>Comparison of REST, Thrift, Protobuf, etc.</li><li>Comparison Between REST and Traditional Web Services</li><li>Comparison Between JAX-RS and Spring MVC</li></ul></li><li>Future</li></ul><h2 id=overview>Overview</h2><p>Dubbo supports a variety of remote calling methods, such as Dubbo RPC (Binary Serialization + TCP), HTTP Invoker (Binary Serialization + HTTP, at least there is no support for Text Serialization in the open source version), Hessian (Binary Serialization + HTTP), Web Services (Text Serialization + HTTP), etc., but lacks support for trending RESTful Remote Calls (Text Serialization + HTTP).</p><p>Therefore, based on the standard Java REST API: JAX-RS 2.0 (Abbreviation of Java API for RESTful Web Services), we provide a mostly transparent REST Call support for Dubbo. Since it is fully compatible with the Standard Java API, all REST services developed for Dubbo may normally work without Dubbo or any specific underlying REST implementation.</p><p>It is particularly worth noting that we do not need to strictly adhere to the original definition and architectural style of REST. Even the famous Twitter REST API will make modest adjustments according to the situations, rather than mechanically follow the original REST style.</p><blockquote><p>Note: We call this feature RESTful Remoting (abstracted remote process or call) rather than a RESTful RPC (specific remote &ldquo;procedure&rdquo; call) because REST and RPC can be thought of two different styles. In Dubbo&rsquo;s REST implementation, there are two aspects, one is to provide or consume regular REST services, the other is to make REST a protocol implementation in the Dubbo RPC system, and RESTful Remoting covers both aspects.</p></blockquote><h2 id=advantages-of-rest>Advantages of REST</h2><p>The following is quoted from Wikipedia:</p><ul><li>REST can use cache to improve response speed more efficiently.</li><li>The stateless nature of the communication allows a set of servers to handle different requests in series, resulting in the increment of server scalability.</li><li>Browser can be used as a client to simplify software requirements.</li><li>REST software dependency is smaller than other mechanisms superimposed on HTTP.</li><li>REST does not require additional resource discovery mechanism.</li><li>REST&rsquo;s long-term compatibility is better in software technology evolution.</li></ul><p>Here I also want to add a particular advantage of REST: REST bases on simple text format messages and universal HTTP. Therefore, it has a broad applicability and is supported by almost all languages and platforms, together with a lower threshold in using and learning.</p><h2 id=application-scenarios>Application scenarios</h2><p>Because of the advantages of REST in applicability, supporting REST in Dubbo can bring (significant) benefits to most of current mainstream remoting call scenarios:</p><ol><li><p>Significantly simplify (cross-language) calls between heterogeneous systems within the enterprise. This is mainly for the following scene: Dubbo acts as a service provider, and systems that are written by other languages (including some java systems that do not base on Dubbo) works as service consumers. The two systems communicate through HTTP and text messages. REST has its unique advantages even comparing to binary cross-language RPC frameworks such as Thrift and ProtoBuf. (See discussion below)</p></li><li><p>Significantly simplify the development of the external Open API (Open Platform). You can use Dubbo to develop a specific Open API application, or you can directly publish the internal Dubbo service as a &ldquo;transparent&rdquo; REST API (Of course, it&rsquo;s better for Dubbo itself to provide more features transparently, for example, permission control, frequency control, billing and so on).</p></li><li><p>Significantly simplify the development of mobile (tablet) apps or desktop clients. Similar to point 2, you can use Dubbo to develop a specialized server for the applications, or transparently expose the internal Dubbo service. Of course in some projects, mobile or desktop applications can directly access the Open API described in point 2.</p></li><li><p>Significantly simplify the development of AJAX applications on the browser. Similar to point 2, you can use Dubbo to develop a specialized server for AJAX, or transparently expose the internal Dubbo service directly to JavaScript in the browser. Of course, many AJAX applications work better with web frameworks, so direct access to the Dubbo service may not be an exquisite architecture in many web projects.</p></li><li><p>Provide a text-based, easy-to-read remote call method for Dubbo systems within the enterprise (that is, both the service provider and the consumer are Dubbo-based systems).</p></li><li><p>Simplify the call from the Dubbo system to other heterogeneous systems. You can use a simple way like Dubbo to &ldquo;transparently&rdquo; call REST services provided by Non-Dubbo systems (regardless of whether the service provider is inside or outside the enterprise)</p></li></ol><p>It should be pointed out that I think that 1~3 are the most valuable application scenarios for Dubbo&rsquo;s REST call. And the main purpose why we add REST calls for Dubbo is to provide a service-oriented provider. In other words, to develop REST services for Non-Dubbo (heterogeneous) consumers.</p><p>To sum up, all application scenarios are shown below:
<img src=/imgs/user/rest.jpg alt=rest.jpg></p><p>Borrowing the most famous slogan of Java in the past, by adding REST calls to Dubbo, you can implement the &ldquo;Write once, access everywhere&rdquo; service, which can theoretically be accessed all over the world, thus truly achieving an idealized Service-oriented Architecture (SOA).</p><p>Of course, traditional Web Services (WSDL/SOAP) can meet the requirements (even those that require enterprise-level features) of the above scenarios (except for scenario 4). But due to the complexity and other issues, they are less and less used.</p><h2 id=quick-start>Quick Start</h2><p>Developing a RESTful service in Dubbo is relatively straightforward. Let&rsquo;s take a simple user registration service for example.</p><p>The function to be implemented by this service is to provide the following URL (Note: This URL is not entirely RESTful, but more straightforward and more practical):</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-fallback data-lang=fallback><span style=display:flex><span>http://localhost:8080/users/register
</span></span></code></pre></div><p>Any client can POST a JSON string containing the user&rsquo;s information to the above URL to complete the user registration.</p><p>First, implement the interface of the service:</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>UserService</span> {
</span></span><span style=display:flex><span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Then, implement the service:</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>@Path</span>(<span style=color:#2aa198>&#34;users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@POST</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;register&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// save the user...</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The above implementation code for the service is very simple, but since the REST service is to be published to a specific HTTP URL so they can be accessed by clients written by any language or even a browser, there are a few additional JAX-RS standard annotations to be added for the relevant configuration:</p><p>@Path(&ldquo;users&rdquo;): Specify that the relative path for <code>UserService</code> is <code>/users</code>, standing for http://localhost:8080/users</p><p>@Path(&ldquo;register&rdquo;): Specify that the relative path for <code>registerUser()</code> is <code>/register</code>. Combining the previous @Path specified for <code>UserService</code>, the URL to call <code>UserService.register()</code> is HTTP://localhost:8080/users/register</p><p>@POST: Specify that <code>registerUser()</code> should be accessed with HTTP POST method</p><p>@Consumes({MediaType.APPLICATION_JSON}): Specify that <code>registerUser()</code> receives data in JSON format. The REST framework will automatically deserialize JSON data into a User object.</p><p>Finally, add this service to the spring configuration file and finish all service development work:</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:#586e75>&lt;!-- Exposure service on port 8080 with rest protocol --&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;Dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8080&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#586e75>&lt;!-- Declare the service interface that needs to be exposed --&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;Dubbo:service</span> interface=<span style=color:#2aa198>&#34;xxx.UserService&#34;</span> ref=<span style=color:#2aa198>&#34;userService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#586e75>&lt;!-- Implement the service like the local bean --&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;bean</span> id=<span style=color:#2aa198>&#34;userService&#34;</span> class=<span style=color:#2aa198>&#34;xxx.UserServiceImpl&#34;</span> <span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h2 id=introduction-to-standard-java-rest-api-jax-rs>Introduction to Standard Java REST API: JAX-RS</h2><p>JAX-RS is a standard Java REST API that has been widely supported and applied in the industry. There are many well-known open source implementations, including Oracle&rsquo;s Jersey, RedHat&rsquo;s RestEasy, Apache&rsquo;s CXF and Wink, restlet, etc. In addition, all commercial JavaEE application servers that support the JavaEE 6.0 specifications or above support JAX-RS. Therefore, JAX-RS is a very mature solution, and it does not have any so-called vendor lock-in problems.</p><p>JAX-RS has a wealth of information on the web, such as the following introductory tutorial:</p><ul><li>Oracle official tutorial: <a href=https://www.oracle.com/technical-resources/articles/java/jax-rs.html>https://www.oracle.com/technical-resources/articles/java/jax-rs.html</a></li><li>Article on IBM developerWorks China: <a href=http://www.ibm.com/developerworks/cn/java/j-lo-jaxrs/>http://www.ibm.com/developerworks/cn/java/j-lo-jaxrs/</a></li></ul><p>For more information, please feel free to Google or Baidu. As far as learning JAX-RS is concerned, it is generally enough to master the usage of various annotations.</p><blockquote><p>Note: Dubbo is based on the JAX-RS 2.0, and sometimes you need to pay attention to the version of the reference material or REST implementation.</p></blockquote><h2 id=rest-service-provider-details>REST Service Provider Details</h2><p>In this section, we will expand the <code>UserService</code> in the &ldquo;Quick Start&rdquo; to further demonstrate the development points of the REST service provider in Dubbo.</p><h3 id=implementation-of-http-postget>Implementation of HTTP POST/GET</h3><p>Although it&rsquo;s recommended to use the four standard methods (POST, DELETE, PUT and GET) in the HTTP protocol to implement common CRUD in REST services, but in practice, we generally use POST to implement create and update, and use GET to implement delete and read (DELETE and PUT will even be blocked by some firewalls).</p><p>The implementation of POST has already been briefly demonstrated. Here, we will add a function to get the registered user data to <code>UserService</code>, in order to demonstrate the implementation of GET.</p><p>This function is to enable the client to obtain user data of different IDs by accessing different URLs as follows:</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-fallback data-lang=fallback><span style=display:flex><span>http://localhost:8080/users/1001
</span></span><span style=display:flex><span>http://localhost:8080/users/1002
</span></span><span style=display:flex><span>http://localhost:8080/users/1003
</span></span></code></pre></div><p>Of course, you can use other forms of URLs to access user data of different IDs, for example:</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-gdscript3 data-lang=gdscript3><span style=display:flex><span>http:<span style=color:#719e07>//</span>localhost:<span style=color:#2aa198>8080</span><span style=color:#719e07>/</span>users<span style=color:#719e07>/</span><span style=color:#b58900>load</span>?id<span style=color:#719e07>=</span><span style=color:#2aa198>1001</span>
</span></span></code></pre></div><p>JAX-RS itself can support all of these forms. However, the first form of including query parameters in the URL path (http://localhost:8080/users/1001) is more in line with the general habit of REST, so it is recommended to use. Below we will add a <code>getUser()</code> method to the <code>UserService</code> to implement this form of URL access:</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>@GET</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;{id : \\d+}&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// ...</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>@GET: Specify that the method shoule be accessed with HTTP GET method</p><p>@Path("{id : \d+}"): According to the above functional requirements, the URL to access <code>getUser()</code> should be &ldquo;http://localhost:8080/users/ + any number&rdquo;, and this number should passed to <code>getUser()</code> method as parameter passed to the getUser() method. In the annotation here, the {id: xxx} in @Path specifies that the relative path contains the id parameter, and its value will be automatically passed to the method parameter <code>id</code> annotated with @PathParam(&ldquo;id&rdquo;). <code>\d+</code> following <code>{id:</code> is a regular expression specifies that the id parameter must be a number.</p><p>@Produces({MediaType.APPLICATION_JSON}): Specify that <code>getUser()</code> outputs data in JSON format. The REST framework automatically serializes the User object into JSON data.</p><h3 id=is-annotation-put-in-interface-class-or-implementation-class>Is annotation put in interface class or implementation class?</h3><p>The development of REST services based on Dubbo is mainly configured through JAX-RS annotations. In the above example, we put the annotation in the implementation class of the service. But in fact, we can completely put the annotation in the interface of the service. These two methods are completely equivalent, for example:</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>@Path</span>(<span style=color:#2aa198>&#34;users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>UserService</span> {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@GET</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;{id : \\d+}&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>In a typical application, we recommend put the annotation in the service implementation class. Then, annotations are closer to Java implementation code and easier to develop and maintain. More importantly, we generally tend to avoid contamination of the interface, maintaining the purity and wide applicability of the interface.</p><p>However, as will be described later, if we access this service by using the consumer directly developed by Dubbo, the annotation must be put in the interface.</p><p>If the interface and the implementation class are both added annotation at the same time, the implementation configuration of the implementation class will take effect, and the annotation on the interface will be ignored.</p><h3 id=support-for-json-xml-and-other-data-formats>Support for JSON, XML and other data formats</h3><p>The dubbo REST services can support the transmission of data in multiple formats to provide maximum flexibility to the client. And we add extra functions to the JSON and XML formats which is most commonly used.</p><p>For example, we want the <code>getUser()</code> method in the above example support returning JSON and XML format data separately, just need to include two formats in the annotation:</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>@Produces</span>({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><p>Or you can directly represent a MediaType with a string (also supports wildcards):</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>@Produces</span>({<span style=color:#2aa198>&#34;application/json&#34;</span>, <span style=color:#2aa198>&#34;text/xml&#34;</span>})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><p>If all methods support the same type of input and output data format, then we do not need to make configure on each method, just add annotation to the service class:</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>@Path</span>(<span style=color:#2aa198>&#34;users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
</span></span><span style=display:flex><span><span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</span></span><span style=display:flex><span> <span style=color:#586e75>// ...</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>In the case where a REST service supports multiple data formats, according to the JAX-RS standard, the MIME header (content-type and accept) in HTTP is generally used to specify which format data is currently used.</p><p>But in dubbo, we also automatically support the current common use of the industry, that is, use a URL suffix (.json and .xml) to specify the data format you want to use. For example, after adding the above annotation, directly accessing <code>http://localhost:8888/users/1001.json</code> means using the json format, and directly accessing <code>http://localhost:8888/users/1002.xml</code> means using the xml format. It&rsquo;s simpler and more intuitive than using HTTP Header. This way is used by the REST APIs of Twitter, Weibo, etc.</p><p>If you don&rsquo;t add HTTP header or suffix, the REST of dubbo will give priority to enable the top ranked data format in the above definition of annotation.</p><blockquote><p>Note: To support XML format data, you can use either <code>MediaType.TEXT_XML</code> or <code>MediaType.APPLICATION_XML</code> in annotation, but TEXT_XML is more commonly used, and if you want to use the above URL suffix to specify the data format, you can only configure it as TEXT_XML to take effect.</p></blockquote><h3 id=chinese-character-support>Chinese character support</h3><p>In order to output Chinese characters normally in dubbo REST, as with the usual Java web applications, we need to set the contentType of the HTTP response to UTF-8 encoding.</p><p>Based on the standard usage of JAX-RS, we only need to do the following annotation configuration:</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>@Produces</span>({<span style=color:#2aa198>&#34;application/json; charset=UTF-8&#34;</span>, <span style=color:#2aa198>&#34;text/xml; charset=UTF-8&#34;</span>})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><p>For the convenience of users, we add a support class directly in dubbo REST to define the above constants, which can be used directly and reduce the possibility of error.</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>@Produces</span>({ContentType.APPLICATION_JSON_UTF_8, ContentType.TEXT_XML_UTF_8})
</span></span><span style=display:flex><span>User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span></code></pre></div><h3 id=additional-requirements-for-xml-data-format>Additional requirements for XML data format</h3><p>Because the implementation of JAX-RS generally use standard JAXB (Java API for XML Binding) to serialize and deserialize XML format data, we need to add a class-level JAXB annotation for each object to be transferred in XML. Otherwise serialization will report an error. For example, add follows to the User returned in <code>getUser()</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>@XmlRootElement</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>User</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span> <span style=color:#586e75>// ...</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>In addition, if the return value in the service method is Java primitive type (such as int, long, float, double, etc.), it is best to add a wrapper object to them, because JAXB can not directly serialize the primitive type.</p><p>For example, we want the above <code>registerUser()</code> method to return the ID number generated by the server for the user:</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:#dc322f>long</span> <span style=color:#268bd2>registerUser</span>(User user);
</span></span></code></pre></div><p>Because the primitive type is not supported by JAXB serialization, add a wrapper 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>@XmlRootElement</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>RegistrationResult</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> Long id;
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#268bd2>RegistrationResult</span>() {
</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>public</span> <span style=color:#268bd2>RegistrationResult</span>(Long id) {
</span></span><span style=display:flex><span> <span style=color:#719e07>this</span>.id <span style=color:#719e07>=</span> id;
</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>public</span> Long <span style=color:#268bd2>getId</span>() {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> id;
</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>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>setId</span>(Long id) {
</span></span><span style=display:flex><span> <span style=color:#719e07>this</span>.id <span style=color:#719e07>=</span> id;
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>And modify the service method:</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>RegistrationResult <span style=color:#268bd2>registerUser</span>(User user);
</span></span></code></pre></div><p>This not only solves the problem of XML serialization, but also makes the returned data conform to the specifications of XML and JSON. For example, in JSON, the returned form would be as follows:</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-javascript data-lang=javascript><span style=display:flex><span>{<span style=color:#2aa198>&#34;id&#34;</span><span style=color:#719e07>:</span> <span style=color:#2aa198>1001</span>}
</span></span></code></pre></div><p>If you do not add a wrapper, the JSON return value will be 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-fallback data-lang=fallback><span style=display:flex><span>1001
</span></span></code></pre></div><p>In XML, the return value after adding wrapper will be:</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;registrationResult&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;id&gt;</span>1002<span style=color:#268bd2>&lt;/id&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/registrationResult&gt;</span>
</span></span></code></pre></div><p>This wrapper object actually uses the so-called Data Transfer Object (DTO) mode, and DTO can also make more useful customizations for transferring data.
While in XML, after adding wrapper, the return value will be</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;registrationResult&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;id&gt;</span>1002<span style=color:#268bd2>&lt;/id&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/registrationResult&gt;</span>
</span></span></code></pre></div><p>In fact, this wrapper object uses the so-called Data Transfer Object (DTO) mode. DTO can also be used to make more useful customizations to transfer data.</p><h3 id=custom-serialization>Custom Serialization</h3><p>As mentioned above, the underlying implementation of REST will automatically serialize/deserialize between the service object and the JSON/XML data format.</p><p>The REST implementation in Dubbo uses JAXB for XML serialization and Jackson for JSON serialization,so you can customize the mapping by adding JAXB or Jackson&rsquo;s annotation to the object.</p><p>For example, customizing the object properties to map to the names of the XML elements:</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>@XmlRootElement</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>@XmlAccessorType</span>(XmlAccessType.FIELD)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>User</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@XmlElement</span>(name<span style=color:#719e07>=</span><span style=color:#2aa198>&#34;username&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> String name;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Customizing the object properties to map to the names of the JSON field:</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>User</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@JsonProperty</span>(<span style=color:#2aa198>&#34;username&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> String name;
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>For more information, please refer to the official documentation of JAXB and Jackson, or google yourself.</p><h3 id=configuring-rest-server-implementation>Configuring REST Server implementation</h3><p>Currently in dubbo, we support the implementation of five embedded rest servers. The implementation of the rest server is selected by the following XML attribute of the server:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;jetty&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>The above configuration uses the embedded jetty to do the rest server. At the same time, if you do not configure the server attribute, the rest protocol also uses jetty by default. jetty is a very mature java servlet container and has a good integration with dubbob (Among the five embedded servers, Only jetty and later tomcat、tjws, complete seamless integration with Dubbo monitoring system.), so, if your dubbo system is a separate process, you can use jetty by default.</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;tomcat&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>The above configuration uses the embedded tomcat to do the rest server.On embedded tomcat, REST performance is much better than jetty (See the benchmark below). It is recommended that Tomcat is used in scenarios where high performance is required.</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;netty&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>The above configuration uses embedded netty to do the rest server. (TODO more contents to add)</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;tjws&#34;</span><span style=color:#268bd2>/&gt;</span> (tjws is now deprecated)
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;sunhttp&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>The above configuration uses embedded tjws or Sun HTTP server to do the rest server. These two server implementations are very lightweight, it is very convenient for quick start-up in integration testing, of course, it can also be used in a production environment with low load. Note: tjws is currently deprecated because it does not work well with the servlet 3.1 API.</p><p>If your dubbo system is not a separate process,
instead of deploying to a Java application server, we recommend the following configuration:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> server=<span style=color:#2aa198>&#34;servlet&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>By setting the server as the servlet, dubbo will use the servlet container of the external application server to do the rest server. At the same time, add the following configuration to the web.xml of the dubbo system:</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;web-app&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;context-param&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;param-name&gt;</span>contextConfigLocation<span style=color:#268bd2>&lt;/param-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;param-value&gt;</span>/WEB-INF/classes/META-INF/spring/dubbo-demo-provider.xml<span style=color:#268bd2>&lt;/param-value&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/context-param&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener-class&gt;</span>org.apache.dubbo.remoting.http.servlet.BootstrapListener<span style=color:#268bd2>&lt;/listener-class&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/listener&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;listener-class&gt;</span>org.springframework.web.context.ContextLoaderListener<span style=color:#268bd2>&lt;/listener-class&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/listener&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-name&gt;</span>dispatcher<span style=color:#268bd2>&lt;/servlet-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-class&gt;</span>org.apache.dubbo.remoting.http.servlet.DispatcherServlet<span style=color:#268bd2>&lt;/servlet-class&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;load-on-startup&gt;</span>1<span style=color:#268bd2>&lt;/load-on-startup&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/servlet&gt;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-mapping&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-name&gt;</span>dispatcher<span style=color:#268bd2>&lt;/servlet-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;url-pattern&gt;</span>/*<span style=color:#268bd2>&lt;/url-pattern&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/servlet-mapping&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/web-app&gt;</span>
</span></span></code></pre></div><p>In other words, you must add dubbo&rsquo;s BootstrapListener and DispatherServlet to web.xml to complete the integration of dubbo&rsquo;s REST functionality with the external servlet container.</p><blockquote><p>Note:If you are using spring&rsquo;s ContextLoaderListener to load spring, you must ensure that the BootstrapListener is configured before the ContextLoaderListener, otherwise the dubbo initialization will fail.</p></blockquote><p>In fact, you can still stick to the embedded server in this scenario, but the servlet container of the external application server is often more powerful than the embedded server(Especially if you are deploying to a more robust and scalable WebLogic, WebSphere, etc.). In addition, it is sometimes convenient to do unified management, monitoring, and so on in the application server.</p><h3 id=get-context-information>Get Context Information</h3><p>Varieties of context information are valuable when calling procedures remotely. For instance, the IP address from the Client.</p><p>We provide two methods to get the Client&rsquo;s IP in dubbo.</p><p>The first one is using @Context annotation from JAX-RS:</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> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id, <span style=color:#268bd2>@Context</span> HttpServletRequest request) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> request.getRemoteAddr());
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>After decorating a parameter of <code>getUser()</code> with Context, we can inject the current HttpServletRequest and then call the servlet api to get the IP.</p><blockquote><p>Notice: This method can only be used when the server is one of the followings: twjs, tomecat, jetty or servlet. All of them provide servlet container. In addition, standard JAX-RS also allow us to get HttpServletRequest using an instance field in service Class decorated by <code>@Context</code>.</p></blockquote><p>The second method is to use RpcContext, which is commonly seen in dubbo:</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> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getRemoteAddressString());
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><blockquote><p>Notice: Similarly, this method only works in the jetty, tomcat, servlet or tjws server. In dubbo, the usage of RpcContext is rather invasive. We are likely to refactor it in the future.</p></blockquote><p>The first method is suggested when your project may run without dubbo and need the compatibility with JAX-RS. But if you want a more elegant service interface definition, the second method would be the better choice.</p><p>What&rsquo;s more, in the newest version of dubbo REST service, RpcContext could be used to get HttpServletRequest and HttpServletResponse, providing great flexibility for users to implement some complex functions. The following is an example:</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:#719e07>if</span> (RpcContext.getContext().getRequest() <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span> <span style=color:#719e07>&amp;&amp;</span> RpcContext.getContext().getRequest() <span style=color:#719e07>instanceof</span> HttpServletRequest) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> ((HttpServletRequest) RpcContext.getContext().getRequest()).getRemoteAddr());
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#719e07>if</span> (RpcContext.getContext().getResponse() <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span> <span style=color:#719e07>&amp;&amp;</span> RpcContext.getContext().getResponse() <span style=color:#719e07>instanceof</span> HttpServletResponse) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Response object from RpcContext: &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getResponse());
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><blockquote><p>Notice:
In order to maintain the neutrality of the protocol, <code>RpcContext.getRequest()</code> and <code>RpcContext.getResponse()</code> only return an Object which could be null. Therefore, you have to check the type on your own.</p></blockquote><blockquote><p>Notice: only when you use jetty, tomcat, servlet as the server can you get the HttpServletRequest and HttpServletResponse as expected. Because only these server
implemented the servlet container.</p></blockquote><p>To simplify the programme, you can also use generic to get a specific type of request/response:</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:#719e07>if</span> (RpcContext.getContext().getRequest(HttpServletRequest.class) <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span>) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Client address is &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getRequest(HttpServletRequest.class).getRemoteAddr());
</span></span><span style=display:flex><span>}
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#719e07>if</span> (RpcContext.getContext().getResponse(HttpServletResponse.class) <span style=color:#719e07>!=</span> <span style=color:#cb4b16>null</span>) {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;Response object from RpcContext: &#34;</span> <span style=color:#719e07>+</span> RpcContext.getContext().getResponse(HttpServletResponse.class));
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>If request/response does not correspond to the specific type, it would return null.</p><h3 id=configure-the-port-number-and-context-path>Configure The Port Number and Context Path</h3><p>The REST protocol in dubbo use 80 as the default port. But you are also allowed to modify it:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>As what have been metioned before, we can use <code>@Path</code> to configure relative URL path in single REST service. In fact, we can also set a basic relative path which is known as context path for all REST service.</p><p>All we need to do is to add the contextpath property:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> contextpath=<span style=color:#2aa198>&#34;services&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>Let&rsquo;s have a look at the previous 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>@Path</span>(<span style=color:#2aa198>&#34;users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@POST</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;register&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// save the user...</span>
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Now the complete path would be:</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-fallback data-lang=fallback><span style=display:flex><span>http://localhost:8888/services/users/register
</span></span></code></pre></div><p>Notice: If you use external server as REST server, you should configure as followings,</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> contextpath=<span style=color:#2aa198>&#34;services&#34;</span> server=<span style=color:#2aa198>&#34;servlet&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>meaning that you should keep the config of port and contextpath are the same with the port and DispatcherServlet&rsquo;s context path (webapp path + servlet url pattern) in external server. For example, when we are configuring the application on tomcat Root path, we need to make sure the contextpath here is totally the same with the <code>&lt;url-pattern/></code> of DispacherServlet in web.xml:</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;servlet-mapping&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;servlet-name&gt;</span>dispatcher<span style=color:#268bd2>&lt;/servlet-name&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;url-pattern&gt;</span>/services/*<span style=color:#268bd2>&lt;/url-pattern&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/servlet-mapping&gt;</span>
</span></span></code></pre></div><h3 id=configure-the-number-of-threads-and-io-threads>Configure the number of threads and IO threads</h3><p>We can set the number of threads of rest service:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> threads=<span style=color:#2aa198>&#34;500&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><blockquote><p>Notice: Currently, the setting only works when the server is netty, jetty or tomcat. If you use servlet as the server, you are using the external server as the REST server which is out of dubboes&rsquo; control, so the setting would not work expectedly.</p></blockquote><p>You can also set threads number of IO worker of netty server:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> iothreads=<span style=color:#2aa198>&#34;5&#34;</span> threads=<span style=color:#2aa198>&#34;100&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h3 id=configure-long-connections>Configure long connections</h3><p>The REST service in Dubbo is accessed by default with http long connection, if you want to switch to short connection, you can configure it as below:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> keepalive=<span style=color:#2aa198>&#34;false&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><blockquote><p>Notice: This configuration only works in netty and tomcat.</p></blockquote><h3 id=configure-the-maximum-number-of-http-connections>Configure the maximum number of HTTP connections</h3><p>Configuring the maximum number of HTTP connections can prevent REST server from
overload as the basic self-protection mechanism.</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> accepts=<span style=color:#2aa198>&#34;500&#34;</span> server=<span style=color:#2aa198>&#34;tomcat/</span><span style=color:#268bd2>&gt;</span>
</span></span></code></pre></div><blockquote><p>Notice: Currently, it only works in tomcat.</p></blockquote><h3 id=configuring-the-timeout-and-http-connections-for-each-consumer>Configuring the timeout and HTTP connections for each consumer</h3><p>If the consumer of the rest service is also a dubbo system, you can configure the maximum timeout for the consumer to call the rest service, and the maximum number of HTTP connections that each consumer can initiate, just like other dubbo RPC mechanisms.</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;dubbo:service</span> interface=<span style=color:#2aa198>&#34;xxx&#34;</span> ref=<span style=color:#2aa198>&#34;xxx&#34;</span> protocol=<span style=color:#2aa198>&#34;rest&#34;</span> timeout=<span style=color:#2aa198>&#34;2000&#34;</span> connections=<span style=color:#2aa198>&#34;10&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>Of course, since this configuration is valid for the consumer, it can also be configured on the consumer side:</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;dubbo:reference</span> id=<span style=color:#2aa198>&#34;xxx&#34;</span> interface=<span style=color:#2aa198>&#34;xxx&#34;</span> timeout=<span style=color:#2aa198>&#34;2000&#34;</span> connections=<span style=color:#2aa198>&#34;10&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>However, we generally recommend configuring the service provider to provide such a configuration. According to the official dubbo documentation, “Provider should configure the properties of the Consumer side as much as possible.
Let the Provider implementer think about the service features and service quality of the Provider from the beginning.”</p><blockquote><p>Note: If dubbo REST service is released to non-dubbo clients, the configuration on <code>&lt;dubbo:service/></code> is completely invalid because the client is not under dubbo control.</p></blockquote><h3 id=gzip-data-compresssion>GZIP data compresssion</h3><p>Dubbo RESTful Remoting supports the use of Gzip to compress request and response data to reduce network transmission time and bandwidth consumption, but this will also increase CPU overhead.</p><p>TODO more contents to add.</p><h3 id=replacing-part-of-the-spring-xml-configuration-with-annotation>Replacing part of the spring XML configuration with annotation</h3><p>Above discussions are based on the XML configuration of Dubbo in spring.
However, dubbo/spring itself supports the use of annotation for configuration, so we can also follow the steps in the Dubbo document and add the relevant annotation to the REST service implementation, replacing some XML configurations, such as:</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>@Service</span>(protocol <span style=color:#719e07>=</span> <span style=color:#2aa198>&#34;rest&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>class</span> <span style=color:#268bd2>UserServiceImpl</span> <span style=color:#268bd2>implements</span> UserService {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Autowired</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> UserRepository userRepository;
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@POST</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;register&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Consumes</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>registerUser</span>(User user) {
</span></span><span style=display:flex><span> <span style=color:#586e75>// save the user</span>
</span></span><span style=display:flex><span> userRepository.save(user);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Annotation-based configuration is more concise and precise, and often easier to maintain (modern IDE can support such things as class name refactoring in XML, and therefore the maintenance of XML is good for specific use cases here). XML is less intrusive to code, especially for dynamically modifying configurations, especially when you want to modify the timeout for connection of a single service configuration, the maximum number of connections per client, cluster policy, weights, and so on. In addition, for complex applications or modules, XML provides a central point to cover all the components and configurations. It is at a glance, and generally more convenient for long term maintenance of the project.</p><p>Of course, there&rsquo;s no right or wrong of different choices of configuration method. Sometimes it&rsquo;s just personal preference.</p><h3 id=adding-a-custom-filter-interceptor-etc>Adding a custom Filter, Interceptor, etc</h3><p>Dubbo RESTful Remoting also supports JAX-RS standard Filter and Interceptor to facilitate customized interception of REST request and response processes.</p><p>Here, Filter is mainly used to access and set parameters, URIs for HTTP request and response, and so on, for example, setting the cache header for HTTP response:</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>CacheControlFilter</span> <span style=color:#268bd2>implements</span> ContainerResponseFilter {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>filter</span>(ContainerRequestContext req, ContainerResponseContext res) {
</span></span><span style=display:flex><span> <span style=color:#719e07>if</span> (req.getMethod().equals(<span style=color:#2aa198>&#34;GET&#34;</span>)) {
</span></span><span style=display:flex><span> res.getHeaders().add(<span style=color:#2aa198>&#34;Cache-Control&#34;</span>, <span style=color:#2aa198>&#34;someValue&#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>Interceptor is mainly used to access and modify the input and output byte streams, for example, manually adding GZIP compression:</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>GZIPWriterInterceptor</span> <span style=color:#268bd2>implements</span> WriterInterceptor {
</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>aroundWriteTo</span>(WriterInterceptorContext context)
</span></span><span style=display:flex><span> <span style=color:#268bd2>throws</span> IOException, WebApplicationException {
</span></span><span style=display:flex><span> OutputStream outputStream <span style=color:#719e07>=</span> context.getOutputStream();
</span></span><span style=display:flex><span> context.setOutputStream(<span style=color:#719e07>new</span> GZIPOutputStream(outputStream));
</span></span><span style=display:flex><span> context.proceed();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>In standard JAX-RS applications, we generally add @Provider annotations to Filter and Interceptor, and JAX-RS runtime will automatically discover and enable them. In Dubbo, we register Filter and Interceptor by adding an XML configuration:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;xxx.TraceInterceptor, xxx.TraceFilter&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>Here, we can add these three types of objects, Filter, Interceptor and DynamicFeature, to the <code>extension</code> attributes, separated by commas. (DynamicFeature is another interface that allows us to enable Filter and Interceptor more dynamically. Please feel free to google.)</p><p>Of course, Dubbo itself also supports Filter, but the Filter and Interceptor we discuss here are more like the bottom of the protocol implementation. Compared to Dubbo&rsquo;s filter, you can do a lower level of customization here.</p><blockquote><p>Note: The XML attribute here is called extension, not interceptor or filter. That is because we will add more extension types in addition to Interceptor and Filter in the future.</p></blockquote><p>If the REST consumer is also a Dubbo system (see discussion below), you can also configure the Interceptor and Filter for the consumer in a similar way.</p><p>However, it should be noted that the consumer-side Filter and the provider-side Filter in JAX-RS are two different interfaces. For example, in the previous example, the server is the ContainerResponseFilter interface, and the consumer side corresponds to the ClientResponseFilter:</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>LoggingFilter</span> <span style=color:#268bd2>implements</span> ClientResponseFilter {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> <span style=color:#dc322f>void</span> <span style=color:#268bd2>filter</span>(ClientRequestContext reqCtx, ClientResponseContext resCtx) <span style=color:#268bd2>throws</span> IOException {
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;status: &#34;</span> <span style=color:#719e07>+</span> resCtx.getStatus());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;date: &#34;</span> <span style=color:#719e07>+</span> resCtx.getDate());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;last-modified: &#34;</span> <span style=color:#719e07>+</span> resCtx.getLastModified());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;location: &#34;</span> <span style=color:#719e07>+</span> resCtx.getLocation());
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;headers:&#34;</span>);
</span></span><span style=display:flex><span> <span style=color:#719e07>for</span> (Entry<span style=color:#719e07>&lt;</span>String, List<span style=color:#719e07>&lt;</span>String<span style=color:#719e07>&gt;&gt;</span> header : resCtx.getHeaders().entrySet()) {
</span></span><span style=display:flex><span> System.out.print(<span style=color:#2aa198>&#34;\t&#34;</span> <span style=color:#719e07>+</span> header.getKey() <span style=color:#719e07>+</span> <span style=color:#2aa198>&#34; :&#34;</span>);
</span></span><span style=display:flex><span> <span style=color:#719e07>for</span> (String value : header.getValue()) {
</span></span><span style=display:flex><span> System.out.print(value <span style=color:#719e07>+</span> <span style=color:#2aa198>&#34;, &#34;</span>);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> System.out.print(<span style=color:#2aa198>&#34;\n&#34;</span>);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;media-type: &#34;</span> <span style=color:#719e07>+</span> resCtx.getMediaType().getType());
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><h3 id=adding-custom-exception-handler>Adding custom Exception handler</h3><p>Dubbo RESTful Remoting also supports JAX-RS standard ExceptionMapper, which can be used to customize the HTTP response after a particular exception occurs.</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>CustomExceptionMapper</span> <span style=color:#268bd2>implements</span> ExceptionMapper<span style=color:#719e07>&lt;</span>NotFoundException<span style=color:#719e07>&gt;</span> {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>public</span> Response <span style=color:#268bd2>toResponse</span>(NotFoundException e) {
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> Response.status(Response.Status.NOT_FOUND).entity(<span style=color:#2aa198>&#34;Oops! the requested resource is not found!&#34;</span>).type(<span style=color:#2aa198>&#34;text/plain&#34;</span>).build();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Similar to Interceptor and Filter, it can be enabled by adding it to an XML configuration file:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;xxx.CustomExceptiionMapper&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h3 id=configuring-http-log-output>Configuring HTTP log output</h3><p>Dubbo RESTful Remoting supports outputting the header and body in all HTTP requests/responses.</p><p>Add the following REST filter to the XML configuration:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;org.apache.dubbo.rpc.protocol.rest.support.LoggingFilter&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p><strong>Then turn on at least INFO level log output for org.apache.dubbo.rpc.protocol.rest.support in the logging configuration</strong>,for example,in log4j.xml:</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;logger</span> name=<span style=color:#2aa198>&#34;org.apache.dubbo.rpc.protocol.rest.support&#34;</span><span style=color:#268bd2>&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;level</span> value=<span style=color:#2aa198>&#34;INFO&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;appender-ref</span> ref=<span style=color:#2aa198>&#34;CONSOLE&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/logger&gt;</span>
</span></span></code></pre></div><p>Of course, you can also turn on INFO level log output directly in the ROOT logger:</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;root&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;level</span> value=<span style=color:#2aa198>&#34;INFO&#34;</span> <span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;appender-ref</span> ref=<span style=color:#2aa198>&#34;CONSOLE&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/root&gt;</span>
</span></span></code></pre></div><p>Then there will be something like the following output in the log:</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-fallback data-lang=fallback><span style=display:flex><span>The HTTP headers are:
</span></span><span style=display:flex><span>accept: application/json;charset=UTF-8
</span></span><span style=display:flex><span>accept-encoding: gzip, deflate
</span></span><span style=display:flex><span>connection: Keep-Alive
</span></span><span style=display:flex><span>content-length: 22
</span></span><span style=display:flex><span>content-type: application/json
</span></span><span style=display:flex><span>host: 192.168.1.100:8888
</span></span><span style=display:flex><span>user-agent: Apache-HttpClient/4.2.1 (java 1.5)
</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-fallback data-lang=fallback><span style=display:flex><span>The contents of request body is:
</span></span><span style=display:flex><span>{&#34;id&#34;:1,&#34;name&#34;:&#34;dang&#34;}
</span></span></code></pre></div><p>After the HTTP log output is turned on, in addition to the performance overhead of the normal log output, additional overhead is generated in, for example, HTTP request parsing, because an additional memory buffer needs to be allocated to prepare the data for the log output.</p><h3 id=inputing-parameter-validation>Inputing parameter validation</h3><p>Dubbo RESTful Remoting supports the use of the Java standard bean validation annotation(JSR 303) for input validation <a href=http://beanvalidation.org/>http://beanvalidation.org/</a>.</p><p>In order to be consistent with other Dubbo remote invocation protocols, the annotations that are checked for rest must be placed on the interface of the service, for example:</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>UserService</span> {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@Min</span>(value<span style=color:#719e07>=</span>1L, message<span style=color:#719e07>=</span><span style=color:#2aa198>&#34;User ID must be greater than 1&#34;</span>) Long id);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Of course, in many other bean validation scenarios, annotations are placed on implementation classes rather than interfaces. At least one advantage of placing an annotation on an interface is that the Dubbo client can share information about the interface. The input validation can be done locally even without RPC.</p><p>Then turn on the validation in the XML configuration in the same way as Dubbo:</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;dubbo:service</span> interface=<span style=color:#2aa198>xxx.UserService&#34;</span> ref=<span style=color:#2aa198>&#34;userService&#34;</span> protocol=<span style=color:#2aa198>&#34;rest&#34;</span> validation=<span style=color:#2aa198>&#34;true&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>In many other RPC protocols of Dubbo, if the input validation error occurs, the <code>RpcException</code> is directly thrown to the client, but in the rest, since the client is often non-Dubbo or even non-Java system, it is inconvenient to directly throw a Java exception. Therefore, at present we will return the validation error in XML format:</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;violationReport&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;constraintViolations&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;path&gt;</span>getUserArgument0<span style=color:#268bd2>&lt;/path&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;message&gt;</span>User ID must be greater than 1<span style=color:#268bd2>&lt;/message&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;value&gt;</span>0<span style=color:#268bd2>&lt;/value&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;/constraintViolations&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/violationReport&gt;</span>
</span></span></code></pre></div><p>The return values of other data formats will also be supported later. As for how to internationalize the verification error message, refer directly to the relevant documentation of the bean validation.</p><p>If you think that the default validation error return format does not meet your requirements, you can add custom ExceptionMapper to custom error return format freely as described in the previous section. It should be noted that this ExceptionMapper must use the generic declaration to capture the RpcException of Dubbo in order to successfully override the default exception handling strategy of Dubbo rest. In order to simplify the operation, the easiest way to do this is to directly inherit the RpcExceptionMapper of Dubbo rest and override the method that handles the validation exception:</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>MyValidationExceptionMapper</span> <span style=color:#268bd2>extends</span> RpcExceptionMapper {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>protected</span> Response <span style=color:#268bd2>handleConstraintViolationException</span>(ConstraintViolationException cve) {
</span></span><span style=display:flex><span> ViolationReport report <span style=color:#719e07>=</span> <span style=color:#719e07>new</span> ViolationReport();
</span></span><span style=display:flex><span> <span style=color:#719e07>for</span> (ConstraintViolation cv : cve.getConstraintViolations()) {
</span></span><span style=display:flex><span> report.addConstraintViolation(<span style=color:#719e07>new</span> RestConstraintViolation(
</span></span><span style=display:flex><span> cv.getPropertyPath().toString(),
</span></span><span style=display:flex><span> cv.getMessage(),
</span></span><span style=display:flex><span> cv.getInvalidValue() <span style=color:#719e07>==</span> <span style=color:#cb4b16>null</span> <span style=color:#719e07>?</span> <span style=color:#2aa198>&#34;null&#34;</span> : cv.getInvalidValue().toString()));
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> <span style=color:#586e75>// Use json output instead of xml output</span>
</span></span><span style=display:flex><span> <span style=color:#719e07>return</span> Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(report).type(ContentType.APPLICATION_JSON_UTF_8).build();
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Then add this ExceptionMapper to the XML configuration:</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;dubbo:protocol</span> name=<span style=color:#2aa198>&#34;rest&#34;</span> port=<span style=color:#2aa198>&#34;8888&#34;</span> extension=<span style=color:#2aa198>&#34;xxx.MyValidationExceptionMapper&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h3 id=whether-to-transparently-publish-rest-service>Whether to transparently publish REST service</h3><p>Dubbo RESTful Remoting differs from some other RPCs in Dubbo in that you need to add JAX-RS annotations (and JAXB, Jackson&rsquo;s annotation) to your service code. If you think these annotations &ldquo;pollute&rdquo; your service code to a certain extent,you can consider writing additional Facade and DTO classes, adding annotations to that, and Facade forwards the calls to the real service implementation class. Of course, adding annotations directly to the service code basically has no negative effects, and this is itself a standard usage in Java EE. In addition, JAX-RS and JAXB annotations belong to the Java standard. Compared with spring, Dubbo, etc., which we often use, annotations have no problem with vendor lock-in, so there is usually no need to introduce additional objects.</p><p>In addition,when you want to use the @Context annotation mentioned above, injecting HttpServletRequest through method parameters (such as <code>public User getUser(@PathParam("id") Long id, @Context HttpServletRequest request)</code>), the method signature of service is changed and HttpServletRequest is a REST-specific parameter, you should introduce additional Facade classes if your service supports multiple RPC mechanisms.</p><p>Of course, your service code may already act as a Facade and DTO before adding RESTful Remoting (as to why some scenarios require these roles, and if you are interested, you can refer to [Micro-SOA: Service Design Principles and Practices] Http://www.infoq.com/cn/articles/micro-soa-1). In this case, after adding REST, if you add additional REST-related Facade and DTO, it is equivalent to wrapping the original code again, which forms the following call chain:</p><p><code>RestFacade/RestDTO -> Facade/DTO -> Service</code></p><p>This kind of system is cumbersome, and the workload of data conversion is not small, so it should be avoided if possible.</p><h3 id=get-headers-in-dubbo-rest-provider>Get Headers In Dubbo Rest Provider</h3><p>Dubbo take out and split headers by RpcContextFilter and put them into attachments of RpcContext, so provider can get headers from RpcContext attachments like:</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-fallback data-lang=fallback><span style=display:flex><span> String header-value1 = RpcContext.getContext().getAttachment(header-key1)
</span></span><span style=display:flex><span> String header-value2 = RpcContext.getContext().getAttachment(header-key2)
</span></span></code></pre></div><h3 id=consumer-of-restful-remoting>Consumer of RESTful Remoting</h3><p>Here we use three scenarios:</p><ol><li>The non-Dubbo consumer calls Dubbo REST service (non-Dubbo &ndash;> Dubbo)</li><li>The Dubbo consumer calls Dubbo REST service (Dubbo &ndash;> Dubbo)</li><li>The consumer of Dubbo calls the non-Dubbo REST service (Dubbo &ndash;> non-Dubbo)</li></ol><h3 id=scenario-1-non-dubbo-consumer-calls-dubbo-rest-service>Scenario 1: Non-Dubbo consumer calls Dubbo REST Service</h3><p>The client of this scenario has nothing to do with Dubbo itself, and it can be directly selected in the appropriate language and framework.</p><p>If it is still a Java client (but not using Dubbo), consider using the standard JAX-RS Client API or a specific REST-implemented Client API to invoke the REST service. The following is the registerUser() that uses the JAX-RS Client API to access the above UserService:</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>User user <span style=color:#719e07>=</span> <span style=color:#719e07>new</span> User();
</span></span><span style=display:flex><span>user.setName(<span style=color:#2aa198>&#34;Larry&#34;</span>);
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Client client <span style=color:#719e07>=</span> ClientBuilder.newClient();
</span></span><span style=display:flex><span>WebTarget target <span style=color:#719e07>=</span> client.target(<span style=color:#2aa198>&#34;http://localhost:8080/services/users/register.json&#34;</span>);
</span></span><span style=display:flex><span>Response response <span style=color:#719e07>=</span> target.request().post(Entity.entity(user, MediaType.APPLICATION_JSON_TYPE));
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#719e07>try</span> {
</span></span><span style=display:flex><span> <span style=color:#719e07>if</span> (response.getStatus() <span style=color:#719e07>!=</span> 200) {
</span></span><span style=display:flex><span> <span style=color:#719e07>throw</span> <span style=color:#719e07>new</span> RuntimeException(<span style=color:#2aa198>&#34;Failed with HTTP error code : &#34;</span> <span style=color:#719e07>+</span> response.getStatus());
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> System.out.println(<span style=color:#2aa198>&#34;The generated id is &#34;</span> <span style=color:#719e07>+</span> response.readEntity(RegistrationResult.class).getId());
</span></span><span style=display:flex><span>} <span style=color:#719e07>finally</span> {
</span></span><span style=display:flex><span> response.close();
</span></span><span style=display:flex><span> client.close(); <span style=color:#586e75>//Do not close the client every time in real development, such as HTTP long connection is held by the client</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>The User and RegistrationResult classes in the code snippet above are written by the consumer itself, and the JAX-RS Client API automatically serializes/deserializes them.</p><p>Of course, in Java, you can also use the familiar technologies such as HttpClient, FastJson, XStream, etc. to implement the REST client, which will not be detailed here.</p><h3 id=scenario-2-dubbo-consumer-calls-dubbo-restful-remoting>Scenario 2: Dubbo consumer calls Dubbo RESTful Remoting</h3><p>In this scenario, same as other Dubbo remote calling methods, the Java service interface is shared directly between the service provider and the service consumer, and the Spring XML configuration is added (of course, the Spring/Dubbo annotation configuration can also be used),the remote REST service can be called transparently:</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;dubbo:reference</span> id=<span style=color:#2aa198>&#34;userService&#34;</span> interface=<span style=color:#2aa198>&#34;xxx.UserService&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>As mentioned earlier, in this scenario, JAX-RS annotations must be added to the service interface, so that the corresponding REST configuration information can be shared on the consumer side of Dubbo and remotely called accordingly:</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>@Path</span>(<span style=color:#2aa198>&#34;users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>UserService</span> {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@GET</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;{id : \\d+}&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
</span></span><span style=display:flex><span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>If a variety of data formats are configured in the annotation of the service interface, since both ends are Dubbo systems, a lot of details of REST are blocked, so there is no possibility to select a data format using the aforementioned URL suffix. Currently in this case, the top ranked data format will be used directly.</p><p>Therefore, we recommend that you put the most appropriate data format in front of defining an annotation. For example, we put JSON in front of XML because JSON&rsquo;s transmission performance is better than XML.</p><h3 id=scenario-3-the-consumer-of-dubbo-calls-a-non-dubbo-restful-remoting>Scenario 3: The consumer of Dubbo calls a non-Dubbo RESTful Remoting</h3><p>In this scenario, the REST service can be called directly using the Java method described in Scenario 1. But in fact, you can also use the way described in Scenario 2, that is, calling the REST service more transparently, even if this service is not provided by Dubbo.</p><p>If the scenario 2 is used, since the REST service is not provided by Dubbo, there is generally no shared Java service interface mentioned above, so we need to write the Java interface and the corresponding parameter class according to the external REST service. Add JAX-RS, JAXB, Jackson and other annotations, Dubbo&rsquo;s REST underlying implementation will automatically generate request messages, automatically parse response messages, etc., so as to transparently make remote calls. Or this way can also be understood as, we try to use JAX-RS to copy the implementation of the external REST service provider, and then put the written service interface to the client to use directly, Dubbo REST underlying implementation can call other REST services as it calls Dubbo&rsquo;s REST service .</p><p>For example, we want to call the following external service.</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-fallback data-lang=fallback><span style=display:flex><span>http://api.foo.com/services/users/1001
</span></span><span style=display:flex><span>http://api.foo.com/services/users/1002
</span></span></code></pre></div><p>Get user data of different IDs, the return format is JSON</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></span><span style=display:flex><span> <span style=color:#2aa198>&#34;id&#34;</span>: 1001,
</span></span><span style=display:flex><span> <span style=color:#2aa198>&#34;name&#34;</span>: <span style=color:#2aa198>&#34;Larry&#34;</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>We can write service interfaces and parameter classes based on this information:</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>@Path</span>(<span style=color:#2aa198>&#34;users&#34;</span>)
</span></span><span style=display:flex><span><span style=color:#268bd2>public</span> <span style=color:#268bd2>interface</span> <span style=color:#268bd2>UserService</span> {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@GET</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Path</span>(<span style=color:#2aa198>&#34;{id : \\d+}&#34;</span>)
</span></span><span style=display:flex><span> <span style=color:#268bd2>@Produces</span>({MediaType.APPLICATION_JSON})
</span></span><span style=display:flex><span> User <span style=color:#268bd2>getUser</span>(<span style=color:#268bd2>@PathParam</span>(<span style=color:#2aa198>&#34;id&#34;</span>) Long id);
</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>User</span> <span style=color:#268bd2>implements</span> Serializable {
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> Long id;
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>private</span> String name;
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#586e75>// …</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>For the configuration in Spring, because the REST service is not provided by Dubbo, you can not use the Dubbo registry to directly configure the url address of the external REST service (such as multiple addresses separated by commas):</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;dubbo:reference</span> id=<span style=color:#2aa198>&#34;userService&#34;</span> interface=<span style=color:#2aa198>&#34;xxx.UserService&#34;</span> url=<span style=color:#2aa198>&#34;rest://api.foo.com/services/&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><blockquote><p>Note: The protocol here must use rest:// instead of http://. If the external REST service has a context path, it must also be added to the url (unless you have a context path in the @Path annotation for each service interface), such as /services/ above. At the same time, the services here must be followed by /, in order to make Dubbo work properly.</p><p>In addition, you can still configure the maximum number of connections and timeouts that the client can start:</p></blockquote><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;userService&#34;</span> interface=<span style=color:#2aa198>&#34;xxx.UserService&#34;</span> url=<span style=color:#2aa198>&#34;rest://api.foo.com/services/&#34;</span> timeout=<span style=color:#2aa198>&#34;2000&#34;</span> connections=<span style=color:#2aa198>&#34;10&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><h3 id=custom-header-by-dubbo-consumer-while-calls-rest-service>Custom Header By Dubbo Consumer while Calls REST Service</h3><p>When Dubbo calls rest, it uses the method of converting the attachments of RpcContext to header.</p><p>Therefore, you can set headers in the following ways:</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-fallback data-lang=fallback><span style=display:flex><span> RpcContext.getContext().setAttachment(&#34;header-key1&#34;, &#34;header-value1&#34;);
</span></span><span style=display:flex><span> RpcContext.getContext().setAttachment(&#34;header-key2&#34;, &#34;header-value2&#34;);
</span></span></code></pre></div><p>Then the headers will be looks like following:</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-fallback data-lang=fallback><span style=display:flex><span> header-key1 = header-value1
</span></span><span style=display:flex><span> header-key2 = header-value2
</span></span></code></pre></div><h3 id=jax-rs-restrictions-in-dubbo>JAX-RS restrictions in Dubbo</h3><p>The REST development in Dubbo is fully compatible with standard JAX-RS, but the features it supports are currently a subset of full JAX-RS, in part because it is limited to the specific architecture of Dubbo and Spring. The limitations of JAX-RS used in Dubbo include but are not limited to:</p><ol><li>Service implementation can only be singleton, and it can not support per-request scope and per-lookup scope</li><li>It is not supported to inject into ServletConfig, ServletContext, HttpServletRequest, HttpServletResponse, etc. with the @Context annotation for the instance field of the service, but it can support the injection of service method parameters. However, for certain REST server implementations (see the previous section), injection of service method parameters is not supported.</li></ol><h2 id=rest-faq>REST FAQ</h2><hr><h3 id=can-dubbo-rest-services-be-integrated-with-dubbo-registry-and-monitor>Can Dubbo REST services be integrated with Dubbo Registry and Monitor?</h3><p>Yes, and it will integrate automatically. That is, all the REST services you develop in Dubbo are automatically registered to the Registry and Monitor, by which you can managed your services.
However, many of the service governance operations in the Registry can only be fully functional when the REST consumer is based on Dubbo. If the consumer side is non-Dubbo, it is naturally not managed by the Registry, so that many of the operations will not work for the consumer.</p><h3 id=how-to-implement-load-balancing-and-failover-in-dubbo-rest>How to implement load balancing and failover in Dubbo REST?</h3><p>If the consumer side of Dubbo REST is based on Dubbo, then Dubbo REST is basically the same as other Dubbo remote call protocols: Dubbo framework transparently performs load balancing, failover, etc. on the consumer side.
If the consumer side of Dubbo REST is non-Dubbo or even non-Java, it is better to configure the soft load balancing mechanism on the service provider. Currently, you can consider LVS, HAProxy, Nginx, and so on to achieve load balancing for HTTP requests.</p><h3 id=can-overloaded-method-in-jax-rs-maps-to-the-same-url-address>Can overloaded method in JAX-RS maps to the same URL address?</h3><p><a href=http://stackoverflow.com/questions/17196766/can-resteasy-choose-method-based-on-query-params>http://stackoverflow.com/questions/17196766/can-resteasy-choose-method-based-on-query-params</a></p><h3 id=can-a-post-method-in-jax-rs-receive-multiple-parameters>Can a POST method in JAX-RS receive multiple parameters?</h3><p><a href=http://stackoverflow.com/questions/5553218/jax-rs-post-multiple-objects>http://stackoverflow.com/questions/5553218/jax-rs-post-multiple-objects</a></p><h2 id=the-shortcomings-of-dubbos-current-system-related-to-rest>The shortcomings of Dubbo&rsquo;s current system (related to REST)</h2><hr><p>I think there are obviously a lot of deficiencies in Dubbo&rsquo;s current system. Here are a few REST-related issues that affect users (not including internal implementation issues) for reference and comments, which can help prepare for the refactoring later.</p><h3 id=invasiveness-of-rpccontext>Invasiveness of RpcContext</h3><p>We have already mentioned the intrusiveness of RpcContext(See above). Because it uses a singleton to access context information, which is completely inconsistent with the general style of spring applications as well as not conducive to application extension and unit testing. In the future, we may inject an interface with dependency injection, and then use it to access the context information in ThreadLocal.</p><h3 id=limitations-of-protocol-configuration>limitations of Protocol configuration</h3><p>Dubbo supports multiple remote call methods, but all call methods are configured with <a href=Dubbo:protocol/>Dubbo:protocol/</a>, for example:</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;Dubbo:protocol</span> name=<span style=color:#2aa198>&#34;Dubbo&#34;</span> port=<span style=color:#2aa198>&#34;9090&#34;</span> server=<span style=color:#2aa198>&#34;netty&#34;</span> client=<span style=color:#2aa198>&#34;netty&#34;</span> codec=<span style=color:#2aa198>&#34;Dubbo&#34;</span> serialization=<span style=color:#2aa198>&#34;hessian2&#34;</span>
</span></span><span style=display:flex><span> charset=<span style=color:#2aa198>&#34;UTF-8&#34;</span> threadpool=<span style=color:#2aa198>&#34;fixed&#34;</span> threads=<span style=color:#2aa198>&#34;100&#34;</span> queues=<span style=color:#2aa198>&#34;0&#34;</span> iothreads=<span style=color:#2aa198>&#34;9&#34;</span> buffer=<span style=color:#2aa198>&#34;8192&#34;</span> accepts=<span style=color:#2aa198>&#34;1000&#34;</span> payload=<span style=color:#2aa198>&#34;8388608&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>Dubbo supports multiple remote call methods, but all call methods are configured with <a href=Dubbo:protocol/>Dubbo:protocol/</a>, for example:
In fact, many of the above properties are uniquely held by the Dubbo RPC remote call method and many other remote call methods in Dubbo do not support server, client, codec, iothreads, accepts, payload, etc. (of course, some are not supported because of limited conditions, some have no need to be supported at all). This adds a lot of confusions to users when they use Dubbo, and they actually do not know that some attributes (such as performance tuning) will not work after adding them.</p><p>On the other hand, various remote call methods often have a large number of unique configuration requirements, especially as we gradually add much richer and more advanced functions to each kind of remote call method, which cause the expands in <protocol>attributes inevitably (for example, we have added keepalive and extension two attributes in REST at the moment) and then lead to bloated <protocol>and user confusion.</p><p>Of course, there is a way to expand <protocol>in Dubbo by using <a href=Dubbo:parameter/>Dubbo:parameter/</a>, but this method is obviously very limited, the usage is complicated and the schema verification is lacking.
So that the best method is to set your own protocol elements for each remote call, such as <protocol-dubbo>, <protocol-rest>, etc. Each element specifies its own attributes using XML Schema. (Of course, it is best to use common attributes between a variety of remote call methods)
In this way, a freer way can be used when doing the extension configuration mentioned above, so that it can be much clearer and more extensible (the following is just an example, of course there may be a better way):</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;Dubbo:protocol-rest</span> port=<span style=color:#2aa198>&#34;8080&#34;</span><span style=color:#268bd2>&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;Dubbo:extension&gt;</span>someInterceptor<span style=color:#268bd2>&lt;/Dubbo:extension&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;Dubbo:extension&gt;</span>someFilter<span style=color:#268bd2>&lt;/Dubbo:extension&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;Dubbo:extension&gt;</span>someDynamicFeature<span style=color:#268bd2>&lt;/Dubbo:extension&gt;</span>
</span></span><span style=display:flex><span> <span style=color:#268bd2>&lt;Dubbo:extension&gt;</span>someEntityProvider<span style=color:#268bd2>&lt;/Dubbo:extension&gt;</span>
</span></span><span style=display:flex><span><span style=color:#268bd2>&lt;/Dubbo:protocol-rest&gt;</span>
</span></span></code></pre></div><h3 id=xml-naming-does-not-conform-to-the-spring-specification>XML naming does not conform to the spring specification</h3><p>A lot of naming in XML configuration of Dubbo dose not conform to the spring specification, such as:</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;Dubbo:protocol</span> name=<span style=color:#2aa198>&#34;Dubbo&#34;</span> port=<span style=color:#2aa198>&#34;9090&#34;</span> server=<span style=color:#2aa198>&#34;netty&#34;</span> client=<span style=color:#2aa198>&#34;netty&#34;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>codec=<span style=color:#2aa198>&#34;Dubbo&#34;</span> serialization=<span style=color:#2aa198>&#34;hessian2&#34;</span>
</span></span><span style=display:flex><span> charset=<span style=color:#2aa198>&#34;UTF-8&#34;</span> threadpool=<span style=color:#2aa198>&#34;fixed&#34;</span> threads=<span style=color:#2aa198>&#34;100&#34;</span> queues=<span style=color:#2aa198>&#34;0&#34;</span> iothreads=<span style=color:#2aa198>&#34;9&#34;</span> buffer=<span style=color:#2aa198>&#34;8192&#34;</span> accepts=<span style=color:#2aa198>&#34;1000&#34;</span> payload=<span style=color:#2aa198>&#34;8388608&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>The above threadpool should be changed to thread-pool, iothreads should be changed to io-threads, and words should be separated by &ldquo;-&rdquo;. While this may seem like a minor issue, it also involves readability, especially scalability, because sometimes we will inevitably use more words to describe XML elements and attributes.</p><p>In fact, Dubbo itself also recommended to follow the naming convention of spring to XML.</p><h2 id=best-practices-of-rest>Best practices of REST</h2><hr><p>TODO</p><h2 id=performance-benchmark>Performance benchmark</h2><hr><h3 id=test-environment>Test Environment</h3><p>Roughly as follows:</p><ul><li>4-core Intel(R) Xeon(R) CPU E5-2603 0 @ 1.80GHz</li><li>8G memory</li><li>The network between servers passes through a 100 Mbps switch</li><li>CentOS 5</li><li>JDK 7</li><li>Tomcat 7</li><li>JVM parameter -server -Xms1g -Xmx1g -XX:PermSize=64M -XX:+UseConcMarkSweepGC</li></ul><h3 id=test-script>Test Script</h3><p>Similar to Dubbo&rsquo;s own benchmarks:
10 concurrent clients send requests continuously:
• Pass in nested complex objects (single data is small), do nothing and return
• Pass in a 50K string, do nothing and return (TODO: the result is not listed yet)
Excute a five-minute performance test. (Reference to Dubbo&rsquo;s own test considerations: &ldquo;Mainly consider the serialization and performance of network IO, so that the server side does not have any business logic. Take 10 to run simultaneously because of the consideration that the bottleneck can be hit first when the high CPU usage rate is reached by HTTP protocol under the high concurrency situation.&rdquo;)</p><h3 id=test-result>Test Result</h3><p>The following results are mainly from the comparison between to the two remote call methods, REST and Dubbo RPC which are configured differently, for example:</p><ul><li>“REST: Jetty + XML + GZIP” means: Test REST, use jetty server and XML data format, and enable GZIP compression.</li><li>“Dubbo: hessian2” means: test Dubbo RPC and use hessian2 serialization.</li></ul><p>The results for complex objects are as follows (the smaller Response Time and the larger TPS, the better results):</p><table><thead><tr><th>Remote Call Mode</th><th>Average Response Time</th><th>Average TPS(Num of transactions per second)</th></tr></thead><tbody><tr><td>REST: Jetty + JSON</td><td>7.806</td><td>1280</td></tr><tr><td>REST: Jetty + JSON + GZIP</td><td>TODO</td><td>TODO</td></tr><tr><td>REST: Jetty + XML</td><td>TODO</td><td>TODO</td></tr><tr><td>REST: Jetty + XML + GZIP</td><td>TODO</td><td>TODO</td></tr><tr><td>REST: Tomcat + JSON</td><td>2.082</td><td>4796</td></tr><tr><td>REST: Netty + JSON</td><td>2.182</td><td>4576</td></tr><tr><td>Dubbo: FST</td><td>1.211</td><td>8244</td></tr><tr><td>Dubbo: kyro</td><td>1.182</td><td>8444</td></tr><tr><td>Dubbo: Dubbo serialization</td><td>1.43</td><td>6982</td></tr><tr><td>Dubbo: hessian2</td><td>1.49</td><td>6701</td></tr><tr><td>Dubbo: fastjson</td><td>1.572</td><td>6352</td></tr></tbody></table><p>Just a brief summary of the current results:</p><ul><li>Dubbo RPC (especially when based on efficient java serialization methods such as kryo and fst) has a significant advantage response time and throughput over REST. Dubbo RPC is preferred in the intranet Dubbo systems.</li><li>When choosinf REST implementation, tomcat7 and netty are optimal (of course, the current versions of jetty and netty are lower) currently only considering performance. Tjws and sun http server performed extremely poorly in performance tests, with an average response time of more than 200ms and an average tps of only about 50 (to avoid affecting the picture effect, the results are not listed above).</li><li>Performance of JSON data format is better than XML in REST (data is not listed above).</li><li>Enabling GZIP in REST has little to do with complex objects with small data volume in the intranet, but performance has declined (data is not listed above).</li></ul><h2 id=performance-optimization-recommendations>Performance Optimization Recommendations</h2><p>If you deploy Dubbo REST to an external Tomcat and configure server=&ldquo;servlet&rdquo;, that is, enable external tomcat as the underlying implementation of rest server, it is best to add the following configuration to tomcat:</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;Connector</span> port=<span style=color:#2aa198>&#34;8080&#34;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>protocol=<span style=color:#2aa198>&#34;org.apache.coyote.http11.Http11NioProtocol&#34;</span>
</span></span><span style=display:flex><span> connectionTimeout=<span style=color:#2aa198>&#34;20000&#34;</span>
</span></span><span style=display:flex><span> redirectPort=<span style=color:#2aa198>&#34;8443&#34;</span>
</span></span><span style=display:flex><span> minSpareThreads=<span style=color:#2aa198>&#34;20&#34;</span>
</span></span><span style=display:flex><span> enableLookups=<span style=color:#2aa198>&#34;false&#34;</span>
</span></span><span style=display:flex><span> maxThreads=<span style=color:#2aa198>&#34;100&#34;</span>
</span></span><span style=display:flex><span> maxKeepAliveRequests=<span style=color:#2aa198>&#34;-1&#34;</span>
</span></span><span style=display:flex><span> keepAliveTimeout=<span style=color:#2aa198>&#34;60000&#34;</span><span style=color:#268bd2>/&gt;</span>
</span></span></code></pre></div><p>Especially the configuration maxKeepAliveRequests="-1" ,which is mainly to ensure that tomcat always enables http long connection, in order to improve the performance of REST call. Note, however, that if the REST consumer side is not continuously call REST services, it is not always best to enable long connections all time. In addition, the way to always enable long connections is generally not suitable for ordinary webapps, but more suitable for such rpc-like scenarios. So that in order to get high performance, Dubbo REST applications and ordinary web applications are best not to be mixed deployment, but should use a separate instance in tomcat.</p><h2 id=extended-discussion>##Extended discussion</h2><h3 id=comparison-among-rest-thrift-protobuf-and-so-on>Comparison among Rest, Thrift, Protobuf and so on</h3><p>TODO</p><h3 id=comparison-between-rest-and-traditional-webservers>Comparison between REST and traditional Webservers</h3><p>TODO</p><h3 id=comparison-of-jax-rs-between-spring-mvc>Comparison of JAX-RS Between Spring MVC</h3><p>A preliminary view from <a href="http://www.infoq.com/cn/news/2014/10/Dubbox-open-source?utm_source=infoq&amp;utm_medium=popular_links_homepage#theCommentsSection">http://www.infoq.com/cn/news/2014/10/Dubbox-open-source?utm_source=infoq&amp;utm_medium=popular_links_homepage#theCommentsSection</a></p><blockquote><p>Thank you, in fact, for jax-rs and Spring MVC, I do not have a deep look at the rest support of Spring MVC. I would like to give you some preliminary ideas. Please correct me:</p></blockquote><blockquote><p>Spring MVC also supports configuration using annotation, which actually looks very similar to jax-rs.</p></blockquote><blockquote><p>Personally, I think Spring MVC is better suited to restful services of web applications, such as being invoked by AJAX, or possibly outputting HTML or something like page jump processes in applications. Spring MVC can handle both normal web page requests and rest requests at the same time. But in general, the restful service is implemented in the presentation layer or the web layer.</p></blockquote><blockquote><p>But Jax-rs is more suitable for pure service-oriented applications, that is, the middle-tier services in traditional Java EE, for example, it can publish traditional EJB as restful services. In a Spring application, the bean that acts as a service in the Spring is directly published as a restful service. In general, the restful service is at the business layer, application layer, or facade layer. And MVC hierarchies and concepts are often of little value in such (back-end) applications.</p></blockquote><blockquote><p>Of course, some implementations of jax-rs, such as jersey, also try to include MVC to better accommodate the web applications described above, but not as well as Spring MVC.</p></blockquote><blockquote><p>In Dubbo applications, I think a lot of people prefer to publish a local Spring service bean (or manager) as a remote service directly and transparently, so that it is more straightforward to use JAX-RS here, and there is no need to introduce the MVC concept. Of course, we do not discuss whether transparent publishing of remote services is a best practice or whether to add facade things here first.</p></blockquote><blockquote><p>Of course, I know that many people use Spring MVC restful to call Dubbo (spring) service to publish restful services under the situation that Dubbo does not support rest now. It’s a good method also in my opinion, but if you do not modify Spring MVC and integrate it deeply with Dubbo, restful services cannot enjoy many advanced services such as registering to the Dubbo Registry, monitoring the number of calls, TPS, response time through the Dubbo Monitor, controlling the size of the thread pool and the maximum number of connections through the unified configuration of Dubbo, and controlling the service flow, authority and frequency through Dubbo unified mode like other remote call protocol such as webservices, Dubbo rpc, hessian and so on in Dubbo system. In addition, Spring MVC only works in server side and Spring restTemplate are usually used on consumer side. If restTemplate is not integrated with Dubbo, the service can be downgraded by Dubbo client automatically or manually. If the server and consumer are all Dubbo system, you cannot use unified routing and other functions in Dubbo if the Spring rest is not deeply integrated into Dubbo through interaction of Spring and rest.</p></blockquote><blockquote><p>Of course, I personally think that these things are not necessarily to be one or the other. I heard that Rod Johnson, the founder of spring usually says ‘the customer is always right,’ In fact, it is better to support both ways at the same time rather than discuss which way is better, so that originally I wrote in the document that we plan to support Spring rest annotation, but the feasibility is unknown.</p></blockquote><h2 id=future>##Future</h2><p>Functions may be supported later:</p><ul><li>Rest annotation for Spring MVC</li><li>Safety System</li><li>OAuth</li><li>Asynchronous calls</li><li>Gzip</li><li>Payload maxsize</li></ul><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><br><div class="text-muted mt-5 pt-3 border-top">Last modified August 7, 2022: <a href=https://github.com/apache/dubbo-website/commit/dbbf5dfe9c153f9bca07aa51a8efe6f84f9ee3e0>Fix broken links & Add link checker (#1339) (dbbf5dfe9c1)</a></div></div></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/docs/v2.7/user/rest.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/docs/v2.7/user/rest.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=REST%20support" 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=#content>CONTENT</a></li><li><a href=#overview>Overview</a></li><li><a href=#advantages-of-rest>Advantages of REST</a></li><li><a href=#application-scenarios>Application scenarios</a></li><li><a href=#quick-start>Quick Start</a></li><li><a href=#introduction-to-standard-java-rest-api-jax-rs>Introduction to Standard Java REST API: JAX-RS</a></li><li><a href=#rest-service-provider-details>REST Service Provider Details</a><ul><li><a href=#implementation-of-http-postget>Implementation of HTTP POST/GET</a></li><li><a href=#is-annotation-put-in-interface-class-or-implementation-class>Is annotation put in interface class or implementation class?</a></li><li><a href=#support-for-json-xml-and-other-data-formats>Support for JSON, XML and other data formats</a></li><li><a href=#chinese-character-support>Chinese character support</a></li><li><a href=#additional-requirements-for-xml-data-format>Additional requirements for XML data format</a></li><li><a href=#custom-serialization>Custom Serialization</a></li><li><a href=#configuring-rest-server-implementation>Configuring REST Server implementation</a></li><li><a href=#get-context-information>Get Context Information</a></li><li><a href=#configure-the-port-number-and-context-path>Configure The Port Number and Context Path</a></li><li><a href=#configure-the-number-of-threads-and-io-threads>Configure the number of threads and IO threads</a></li><li><a href=#configure-long-connections>Configure long connections</a></li><li><a href=#configure-the-maximum-number-of-http-connections>Configure the maximum number of HTTP connections</a></li><li><a href=#configuring-the-timeout-and-http-connections-for-each-consumer>Configuring the timeout and HTTP connections for each consumer</a></li><li><a href=#gzip-data-compresssion>GZIP data compresssion</a></li><li><a href=#replacing-part-of-the-spring-xml-configuration-with-annotation>Replacing part of the spring XML configuration with annotation</a></li><li><a href=#adding-a-custom-filter-interceptor-etc>Adding a custom Filter, Interceptor, etc</a></li><li><a href=#adding-custom-exception-handler>Adding custom Exception handler</a></li><li><a href=#configuring-http-log-output>Configuring HTTP log output</a></li><li><a href=#inputing-parameter-validation>Inputing parameter validation</a></li><li><a href=#whether-to-transparently-publish-rest-service>Whether to transparently publish REST service</a></li><li><a href=#get-headers-in-dubbo-rest-provider>Get Headers In Dubbo Rest Provider</a></li><li><a href=#consumer-of-restful-remoting>Consumer of RESTful Remoting</a></li><li><a href=#scenario-1-non-dubbo-consumer-calls-dubbo-rest-service>Scenario 1: Non-Dubbo consumer calls Dubbo REST Service</a></li><li><a href=#scenario-2-dubbo-consumer-calls-dubbo-restful-remoting>Scenario 2: Dubbo consumer calls Dubbo RESTful Remoting</a></li><li><a href=#scenario-3-the-consumer-of-dubbo-calls-a-non-dubbo-restful-remoting>Scenario 3: The consumer of Dubbo calls a non-Dubbo RESTful Remoting</a></li><li><a href=#custom-header-by-dubbo-consumer-while-calls-rest-service>Custom Header By Dubbo Consumer while Calls REST Service</a></li><li><a href=#jax-rs-restrictions-in-dubbo>JAX-RS restrictions in Dubbo</a></li></ul></li><li><a href=#rest-faq>REST FAQ</a><ul><li><a href=#can-dubbo-rest-services-be-integrated-with-dubbo-registry-and-monitor>Can Dubbo REST services be integrated with Dubbo Registry and Monitor?</a></li><li><a href=#how-to-implement-load-balancing-and-failover-in-dubbo-rest>How to implement load balancing and failover in Dubbo REST?</a></li><li><a href=#can-overloaded-method-in-jax-rs-maps-to-the-same-url-address>Can overloaded method in JAX-RS maps to the same URL address?</a></li><li><a href=#can-a-post-method-in-jax-rs-receive-multiple-parameters>Can a POST method in JAX-RS receive multiple parameters?</a></li></ul></li><li><a href=#the-shortcomings-of-dubbos-current-system-related-to-rest>The shortcomings of Dubbo&rsquo;s current system (related to REST)</a><ul><li><a href=#invasiveness-of-rpccontext>Invasiveness of RpcContext</a></li><li><a href=#limitations-of-protocol-configuration>limitations of Protocol configuration</a></li><li><a href=#xml-naming-does-not-conform-to-the-spring-specification>XML naming does not conform to the spring specification</a></li></ul></li><li><a href=#best-practices-of-rest>Best practices of REST</a></li><li><a href=#performance-benchmark>Performance benchmark</a><ul><li><a href=#test-environment>Test Environment</a></li><li><a href=#test-script>Test Script</a></li><li><a href=#test-result>Test Result</a></li></ul></li><li><a href=#performance-optimization-recommendations>Performance Optimization Recommendations</a></li><li><a href=#extended-discussion>##Extended discussion</a><ul><li><a href=#comparison-among-rest-thrift-protobuf-and-so-on>Comparison among Rest, Thrift, Protobuf and so on</a></li><li><a href=#comparison-between-rest-and-traditional-webservers>Comparison between REST and traditional Webservers</a></li><li><a href=#comparison-of-jax-rs-between-spring-mvc>Comparison of JAX-RS Between Spring MVC</a></li></ul></li><li><a href=#future>##Future</a></li></ul></nav></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>