<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have searched the <a href="https://github.com/apache/incubator-dubbo/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox"> I have checked the <a href="https://github.com/apache/incubator-dubbo/blob/master/FAQ.md">FAQ</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>Dubbo version:  2.7.0-SNAPSHOT</li>
</ul>
<h3 dir="auto">Step to reproduce this issue</h3>
<ol dir="auto">
<li><a href="https://github.com/apache/incubator-dubbo/blob/master/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java">https://github.com/apache/incubator-dubbo/blob/master/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java</a></li>
</ol>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" private URL getRegisteredProviderUrl(final Invoker&lt;?&gt; originInvoker) {
        URL providerUrl = getProviderUrl(originInvoker);
        //The address you see at the registry
        return providerUrl.removeParameters(getFilteredKeys(providerUrl))
                .removeParameter(Constants.MONITOR_KEY)
                .removeParameter(Constants.BIND_IP_KEY)
                .removeParameter(Constants.BIND_PORT_KEY)
                .removeParameter(QOS_ENABLE)
                .removeParameter(QOS_PORT)
                .removeParameter(ACCEPT_FOREIGN_IP)
                .removeParameter(VALIDATION_KEY)
                .removeParameter(INTERFACES);
    }
TO
 private URL getRegisteredProviderUrl(final Invoker&lt;?&gt; originInvoker) {
        URL providerUrl = getProviderUrl(originInvoker);
       // 此处移除async标记，仅保留标记在provider端
        Set&lt;String&gt; keySet = providerUrl.getParameters().keySet();
        List&lt;String&gt; asyncKey = new ArrayList&lt;&gt;();
        for(String key : keySet) {
            if(key.endsWith(&quot;.&quot; + Constants.ASYNC_KEY) || key.equals(Constants.ASYNC_KEY)) {
                asyncKey.add(key);
            }
        }
        //The address you see at the registry
        return providerUrl.removeParameters(getFilteredKeys(providerUrl))
                .removeParameter(Constants.MONITOR_KEY)
                .removeParameter(Constants.BIND_IP_KEY)
                .removeParameter(Constants.BIND_PORT_KEY)
                .removeParameter(QOS_ENABLE)
                .removeParameter(QOS_PORT)
                .removeParameter(ACCEPT_FOREIGN_IP)
                .removeParameter(VALIDATION_KEY)
                .removeParameter(INTERFACES)
                .removeParameters(asyncKey);
    }"><pre class="notranslate"> <span class="pl-k">private</span> <span class="pl-smi">URL</span> <span class="pl-s1">getRegisteredProviderUrl</span>(<span class="pl-k">final</span> <span class="pl-smi">Invoker</span>&lt;?&gt; <span class="pl-s1">originInvoker</span>) {
        <span class="pl-smi">URL</span> <span class="pl-s1">providerUrl</span> = <span class="pl-en">getProviderUrl</span>(<span class="pl-s1">originInvoker</span>);
        <span class="pl-c">//The address you see at the registry</span>
        <span class="pl-k">return</span> <span class="pl-s1">providerUrl</span>.<span class="pl-en">removeParameters</span>(<span class="pl-en">getFilteredKeys</span>(<span class="pl-s1">providerUrl</span>))
                .<span class="pl-en">removeParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">MONITOR_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">BIND_IP_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">BIND_PORT_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">QOS_ENABLE</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">QOS_PORT</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">ACCEPT_FOREIGN_IP</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">VALIDATION_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">INTERFACES</span>);
    }
<span class="pl-smi">TO</span>
 <span class="pl-s1">private</span> <span class="pl-smi">URL</span> <span class="pl-s1">getRegisteredProviderUrl</span>(<span class="pl-k">final</span> <span class="pl-smi">Invoker</span>&lt;?&gt; <span class="pl-s1">originInvoker</span>) {
        <span class="pl-smi">URL</span> <span class="pl-s1">providerUrl</span> = <span class="pl-en">getProviderUrl</span>(<span class="pl-s1">originInvoker</span>);
       <span class="pl-c">// 此处移除async标记，仅保留标记在provider端</span>
        <span class="pl-smi">Set</span>&lt;<span class="pl-smi">String</span>&gt; <span class="pl-s1">keySet</span> = <span class="pl-s1">providerUrl</span>.<span class="pl-en">getParameters</span>().<span class="pl-en">keySet</span>();
        <span class="pl-smi">List</span>&lt;<span class="pl-smi">String</span>&gt; <span class="pl-s1">asyncKey</span> = <span class="pl-k">new</span> <span class="pl-smi">ArrayList</span>&lt;&gt;();
        <span class="pl-k">for</span>(<span class="pl-smi">String</span> <span class="pl-s1">key</span> : <span class="pl-s1">keySet</span>) {
            <span class="pl-k">if</span>(<span class="pl-s1">key</span>.<span class="pl-en">endsWith</span>(<span class="pl-s">"."</span> + <span class="pl-smi">Constants</span>.<span class="pl-c1">ASYNC_KEY</span>) || <span class="pl-s1">key</span>.<span class="pl-en">equals</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">ASYNC_KEY</span>)) {
                <span class="pl-s1">asyncKey</span>.<span class="pl-en">add</span>(<span class="pl-s1">key</span>);
            }
        }
        <span class="pl-c">//The address you see at the registry</span>
        <span class="pl-k">return</span> <span class="pl-s1">providerUrl</span>.<span class="pl-en">removeParameters</span>(<span class="pl-en">getFilteredKeys</span>(<span class="pl-s1">providerUrl</span>))
                .<span class="pl-en">removeParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">MONITOR_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">BIND_IP_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-smi">Constants</span>.<span class="pl-c1">BIND_PORT_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">QOS_ENABLE</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">QOS_PORT</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">ACCEPT_FOREIGN_IP</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">VALIDATION_KEY</span>)
                .<span class="pl-en">removeParameter</span>(<span class="pl-c1">INTERFACES</span>)
                .<span class="pl-en">removeParameters</span>(<span class="pl-s1">asyncKey</span>);
    }</pre></div>
<p dir="auto">that if Provider use "provider async" like this：</p>
<div class="highlight highlight-source-java notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content=" public String sayHello(String name) {
        System.out.println(&quot;Main sayHello() method start.&quot;);
        final AsyncContext asyncContext = RpcContext.startAsync();
        new Thread(() -&gt; {
            asyncContext.signalContextSwitch();
            System.out.println(&quot;Attachment from consumer: &quot; + RpcContext.getContext().getAttachment(&quot;consumer-key1&quot;));
            System.out.println(&quot;    -- Async start.&quot;);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            asyncContext.write(&quot;Hello &quot; + name + &quot;, response from provider.&quot;);
            System.out.println(&quot;    -- Async end.&quot;);
        }).start();
        System.out.println(&quot;Main sayHello() method end.&quot;);
        return &quot;hello, &quot; + name;
    }
 &lt;dubbo:method name=&quot;sayHello&quot; async=&quot;true&quot;/&gt;"><pre class="notranslate"> <span class="pl-k">public</span> <span class="pl-smi">String</span> <span class="pl-s1">sayHello</span>(<span class="pl-smi">String</span> <span class="pl-s1">name</span>) {
        <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"Main sayHello() method start."</span>);
        <span class="pl-k">final</span> <span class="pl-smi">AsyncContext</span> <span class="pl-s1">asyncContext</span> = <span class="pl-smi">RpcContext</span>.<span class="pl-en">startAsync</span>();
        <span class="pl-k">new</span> <span class="pl-smi">Thread</span>(() -&gt; {
            <span class="pl-s1">asyncContext</span>.<span class="pl-en">signalContextSwitch</span>();
            <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"Attachment from consumer: "</span> + <span class="pl-smi">RpcContext</span>.<span class="pl-en">getContext</span>().<span class="pl-en">getAttachment</span>(<span class="pl-s">"consumer-key1"</span>));
            <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"    -- Async start."</span>);
            <span class="pl-k">try</span> {
                <span class="pl-smi">Thread</span>.<span class="pl-en">sleep</span>(<span class="pl-c1">500</span>);
            } <span class="pl-k">catch</span> (<span class="pl-smi">InterruptedException</span> <span class="pl-s1">e</span>) {
                <span class="pl-s1">e</span>.<span class="pl-en">printStackTrace</span>();
            }
            <span class="pl-s1">asyncContext</span>.<span class="pl-en">write</span>(<span class="pl-s">"Hello "</span> + <span class="pl-s1">name</span> + <span class="pl-s">", response from provider."</span>);
            <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"    -- Async end."</span>);
        }).<span class="pl-en">start</span>();
        <span class="pl-smi">System</span>.<span class="pl-s1">out</span>.<span class="pl-en">println</span>(<span class="pl-s">"Main sayHello() method end."</span>);
        <span class="pl-k">return</span> <span class="pl-s">"hello, "</span> + <span class="pl-s1">name</span>;
    }
 &lt;<span class="pl-s1">dubbo</span>:<span class="pl-smi">method</span> <span class="pl-s1">name</span>=<span class="pl-s">"sayHello"</span> <span class="pl-s1">async</span>=<span class="pl-s">"true"</span>/&gt;</pre></div>
<p dir="auto">and consumer user dubbo version low than 2.7.0-SNAPSHOT,<br>
"async = true" will know from provider registed url, that need consumer use old async to invoke this method. But it is not what we expected, we think async should only be set by consumer itself.<br>
英文不太好，中文版：</p>
<ol dir="auto">
<li>Provider版本使用 2.7.0-SNAPSHOT版本，然后发布接口使用了"provider async"的方式（见上面第二段代码）,则需要在发布的时候添加<code class="notranslate"> &lt;dubbo:method name="sayHello" async="true"/&gt;</code>则会将 async=true 的标记注册到注册中心，这时候就会将标记透传到 Consumer 端，导致服务调用变成异步的，而出现返回值为 null 的情况。</li>
<li>根据我个人的理解，async 标记应该仅由 provider 或 consumer 自己指定，而不应该透传到对方感知。</li>
</ol>
<ul class="contains-task-list">
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have searched the <a href="https://github.com/apache/dubbo/issues">issues</a> of this repository and believe that this is not a duplicate.</li>
<li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> I have checked the <a href="https://github.com/apache/dubbo/blob/master/FAQ.md">FAQ</a> of this repository and believe that this is not a duplicate.</li>
</ul>
<h3 dir="auto">Environment</h3>
<ul dir="auto">
<li>Dubbo version: 2.7.3</li>
<li>Operating System version: MacOS Catalina 10.15 Beta</li>
<li>Java version: 1.8</li>
</ul>
<h3 dir="auto">project struct</h3>
<p dir="auto"><a target="_blank" rel="noopener noreferrer nofollow" href="https://user-images.githubusercontent.com/832040/62096991-240bf200-b2b8-11e9-8d4e-c9cee2802c06.png"><img src="https://user-images.githubusercontent.com/832040/62096991-240bf200-b2b8-11e9-8d4e-c9cee2802c06.png" alt="image" style="max-width: 100%;"></a></p>
<h3 dir="auto">DubboConfiguration</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@Configuration
@EnableDubbo(scanBasePackages = &quot;com.weiguang.www.dubboprovider.service&quot;)
@PropertySource(value = &quot;classpath:dubbo-provider.properties&quot;)
public class DubboConfiguration {

    @Bean
    public ProviderConfig providerConfig(){
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(3000);
        return providerConfig;
    }

}
"><pre class="notranslate"><code class="notranslate">@Configuration
@EnableDubbo(scanBasePackages = "com.weiguang.www.dubboprovider.service")
@PropertySource(value = "classpath:dubbo-provider.properties")
public class DubboConfiguration {

    @Bean
    public ProviderConfig providerConfig(){
        ProviderConfig providerConfig = new ProviderConfig();
        providerConfig.setTimeout(3000);
        return providerConfig;
    }

}

</code></pre></div>
<h3 dir="auto">log</h3>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[DUBBO] No Spring Bean annotating Dubbo's @Service was found under package[com.weiguang.www.dubboconsumer.config], dubbo version: 2.7.3, current host: 192.168.1.111"><pre class="notranslate"><code class="notranslate">[DUBBO] No Spring Bean annotating Dubbo's @Service was found under package[com.weiguang.www.dubboconsumer.config], dubbo version: 2.7.3, current host: 192.168.1.111
</code></pre></div>
<p dir="auto">搜索的是config文件所在的目录，并不是 <code class="notranslate">@EnableDubbo(scanBasePackages = "com.weiguang.www.dubboprovider.service")</code> 指定的目录。</p>
<p dir="auto">导致在zookeeper中,provider内容为空，</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="[zk: 127.0.0.1:2181(CONNECTED) 0] ls /
[dubbo, zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 1] ls /dubbo
[com.weiguang.www.dubbointerface.service.HelloService]
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /dubbo/com.weiguang.www.dubbointerface.service.HelloService
[configurators, consumers, providers, routers]
[zk: 127.0.0.1:2181(CONNECTED) 3] ls /dubbo/com.weiguang.www.dubbointerface.service.HelloService/providers
[]
[zk: 127.0.0.1:2181(CONNECTED) 4] "><pre class="notranslate"><code class="notranslate">[zk: 127.0.0.1:2181(CONNECTED) 0] ls /
[dubbo, zookeeper]
[zk: 127.0.0.1:2181(CONNECTED) 1] ls /dubbo
[com.weiguang.www.dubbointerface.service.HelloService]
[zk: 127.0.0.1:2181(CONNECTED) 2] ls /dubbo/com.weiguang.www.dubbointerface.service.HelloService
[configurators, consumers, providers, routers]
[zk: 127.0.0.1:2181(CONNECTED) 3] ls /dubbo/com.weiguang.www.dubbointerface.service.HelloService/providers
[]
[zk: 127.0.0.1:2181(CONNECTED) 4] 
</code></pre></div>
<p dir="auto">最终导致consumer 调用时出现 No provider availabe 错误:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="    &quot;timestamp&quot;: &quot;2019-07-30T02:39:07.740+0000&quot;,
    &quot;status&quot;: 500,
    &quot;error&quot;: &quot;Internal Server Error&quot;,
    &quot;message&quot;: &quot;No provider available from registry 127.0.0.1:2181 for service com.weiguang.www.dubbointerface.service.HelloService:1.0.0 on consumer 192.168.1.111 use dubbo version 2.7.3, please check status of providers(disabled, not registered or in blacklist).&quot;,
    &quot;path&quot;: &quot;/hello&quot;"><pre class="notranslate"><code class="notranslate">    "timestamp": "2019-07-30T02:39:07.740+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "No provider available from registry 127.0.0.1:2181 for service com.weiguang.www.dubbointerface.service.HelloService:1.0.0 on consumer 192.168.1.111 use dubbo version 2.7.3, please check status of providers(disabled, not registered or in blacklist).",
    "path": "/hello"
</code></pre></div>
<h3 dir="auto">解决方法：</h3>
<p dir="auto">需要在configuration类上加注解 <code class="notranslate">@DubboComponentScan(basePackages = "com.weiguang.www.dubboprovider.service") </code> ，service才会被注册。</p>