<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.4-SNAPSHOT</li>
<li>Operating System version: macOS 10.14.5</li>
<li>Java version: 1.8.0_172</li>
</ul>
<h3 dir="auto">Steps to reproduce this issue</h3>
<p dir="auto">I see there is LRU cache implement in dubbo, and LFU is also a useful cache strategy. So, if it's necessary to impl LFU, I will try my best to work on it.</p>
<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/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/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</li>
<li>Java version: 1.8</li>
</ul>
<h3 dir="auto">Steps to reproduce this issue</h3>
<ol dir="auto">
<li>服务端打开dubbo协议，并监听8080端口</li>
<li>客户端通过dubbo作为代理，以直连的方式与服务端建立连接。</li>
</ol>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="String url=&quot;dubbo://127.0.0.1:20880&quot;
ReferenceConfig&lt;DemoService&gt; referenceConfig = new ReferenceConfig&lt;&gt;();
referenceConfig.setInterface(DemoService.class);
referenceConfig.setUrl(url);"><pre class="notranslate"><code class="notranslate">String url="dubbo://127.0.0.1:20880"
ReferenceConfig&lt;DemoService&gt; referenceConfig = new ReferenceConfig&lt;&gt;();
referenceConfig.setInterface(DemoService.class);
referenceConfig.setUrl(url);
</code></pre></div>
<ol start="3" dir="auto">
<li>客户端跟服务端的网络出现问题，请求无法到达服务端。</li>
</ol>
<p dir="auto">原因：<br>
为了避免并发请求重复创建线程，Netty在建连的时候时加锁的。<br>
org.apache.dubbo.remoting.transport.netty.NettyClient</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="@Override
protected void doConnect() throws Throwable {
    long start = System.currentTimeMillis();
    ChannelFuture future = bootstrap.connect(getConnectAddress());
    try {
        boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
        ...
    } finally {

    }
}"><pre class="notranslate"><code class="notranslate">@Override
protected void doConnect() throws Throwable {
    long start = System.currentTimeMillis();
    ChannelFuture future = bootstrap.connect(getConnectAddress());
    try {
        boolean ret = future.awaitUninterruptibly(getConnectTimeout(), TimeUnit.MILLISECONDS);
        ...
    } finally {

    }
}
</code></pre></div>
<p dir="auto">org.jboss.netty.channel.DefaultChannelFuture</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="private boolean await0(long timeoutNanos, boolean interruptable) throws InterruptedException {
    try {
        synchronized (this) {
            try {
                for (;;) {
                    try {
                        this.wait(waitTime / 1000000, (int) (waitTime % 1000000));
                    } catch (InterruptedException e) {
                       
                    }
                }
            } finally {
            }
        }
    } finally {
    }
}"><pre class="notranslate"><code class="notranslate">private boolean await0(long timeoutNanos, boolean interruptable) throws InterruptedException {
    try {
        synchronized (this) {
            try {
                for (;;) {
                    try {
                        this.wait(waitTime / 1000000, (int) (waitTime % 1000000));
                    } catch (InterruptedException e) {
                       
                    }
                }
            } finally {
            }
        }
    } finally {
    }
}
</code></pre></div>
<p dir="auto">从调用的堆栈中可以发现，在请求发送之前会检查当前连接是否可用，如果不可用就会重新建连。<br>
假设同时进来了100个请求，第一个请求发现连接不可用需要重新建连，由于服务端不可达，就会一直持有连接的锁，直到3s超时之后才会释放锁。那么，第100个请求等待的时候就是100*3=300s，会导致线程被大量阻塞。</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="at org.apache.dubbo.remoting.transport.netty.NettyClient.doConnect(NettyClient.java:130)
at org.apache.dubbo.remoting.transport.AbstractClient.connect(AbstractClient.java:189)
at org.apache.dubbo.remoting.transport.AbstractClient.&lt;init&gt;(AbstractClient.java:71)
at org.apache.dubbo.remoting.transport.netty.NettyClient.&lt;init&gt;(NettyClient.java:59)
at org.apache.dubbo.remoting.transport.netty.NettyTransporter.connect(NettyTransporter.java:37)
at com.ctrip.framework.cdubbo.internal.delegate.CDubboTransporterDelegate.connect(CDubboTransporterDelegate.java:25)
at org.apache.dubbo.remoting.Transporter$Adaptive.connect(Transporter$Adaptive.java)
at org.apache.dubbo.remoting.Transporters.connect(Transporters.java:75)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger.connect(HeaderExchanger.java:39)
at org.apache.dubbo.remoting.exchange.Exchangers.connect(Exchangers.java:109)
at org.apache.dubbo.rpc.protocol.dubbo.LazyConnectExchangeClient.initClient(LazyConnectExchangeClient.java:83)
at org.apache.dubbo.rpc.protocol.dubbo.LazyConnectExchangeClient.request(LazyConnectExchangeClient.java:127)"><pre class="notranslate"><code class="notranslate">at org.apache.dubbo.remoting.transport.netty.NettyClient.doConnect(NettyClient.java:130)
at org.apache.dubbo.remoting.transport.AbstractClient.connect(AbstractClient.java:189)
at org.apache.dubbo.remoting.transport.AbstractClient.&lt;init&gt;(AbstractClient.java:71)
at org.apache.dubbo.remoting.transport.netty.NettyClient.&lt;init&gt;(NettyClient.java:59)
at org.apache.dubbo.remoting.transport.netty.NettyTransporter.connect(NettyTransporter.java:37)
at com.ctrip.framework.cdubbo.internal.delegate.CDubboTransporterDelegate.connect(CDubboTransporterDelegate.java:25)
at org.apache.dubbo.remoting.Transporter$Adaptive.connect(Transporter$Adaptive.java)
at org.apache.dubbo.remoting.Transporters.connect(Transporters.java:75)
at org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger.connect(HeaderExchanger.java:39)
at org.apache.dubbo.remoting.exchange.Exchangers.connect(Exchangers.java:109)
at org.apache.dubbo.rpc.protocol.dubbo.LazyConnectExchangeClient.initClient(LazyConnectExchangeClient.java:83)
at org.apache.dubbo.rpc.protocol.dubbo.LazyConnectExchangeClient.request(LazyConnectExchangeClient.java:127)
</code></pre></div>
<p dir="auto">Pls. provide [GitHub address] to reproduce this issue.</p>
<h3 dir="auto">Expected Result</h3>
<p dir="auto">对于直连模式，在出现服务端连接不可用的情况下，能够支持快速失败。</p>
<h3 dir="auto">Actual Result</h3>
<p dir="auto">对于直连模式，在出现服务端连接不可用的情况下，会导致线程阻塞。</p>
<p dir="auto">If there is an exception, please attach the exception trace:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Just put your stack trace here!"><pre class="notranslate"><code class="notranslate">Just put your stack trace here!
</code></pre></div>