diff --git a/skywalking-sdk-plugin/dubbo-plugin/pom.xml b/skywalking-sdk-plugin/dubbo-plugin/pom.xml
index 5393deedc..411462c0a 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/pom.xml
+++ b/skywalking-sdk-plugin/dubbo-plugin/pom.xml
@@ -34,6 +34,12 @@
3.0.0.RELEASE
test
+
+ org.springframework
+ spring-aop
+ 3.0.0.RELEASE
+ test
+
org.jboss.resteasy
resteasy-jaxrs
@@ -88,20 +94,28 @@
0.7
test
-
-
+ -->
+
+
+ com.alibaba
+ dubbo
+ 2.5.3
+ compile
+
org.apache.httpcomponents
httpclient
@@ -140,12 +154,12 @@
-
+
-
- bintray-wu-sheng-sky-walking-repository
- wu-sheng-sky-walking-repository
- https://api.bintray.com/maven/wu-sheng/skywalking/com.ai.cloud.skywalking-dubbo-plugin/;publish=1
-
-
+
+ bintray-wu-sheng-sky-walking-repository
+ wu-sheng-sky-walking-repository
+ https://api.bintray.com/maven/wu-sheng/skywalking/com.ai.cloud.skywalking-dubbo-plugin/;publish=1
+
+
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/ai/cloud/skywalking/plugin/DubboFilterBuildInterceptor.java b/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/ai/cloud/skywalking/plugin/DubboFilterBuildInterceptor.java
new file mode 100644
index 000000000..5f32d323e
--- /dev/null
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/ai/cloud/skywalking/plugin/DubboFilterBuildInterceptor.java
@@ -0,0 +1,56 @@
+package com.ai.cloud.skywalking.plugin;
+
+import com.alibaba.dubbo.common.URL;
+import com.alibaba.dubbo.common.extension.ExtensionLoader;
+import com.alibaba.dubbo.rpc.*;
+import net.bytebuddy.implementation.bind.annotation.Argument;
+import net.bytebuddy.implementation.bind.annotation.RuntimeType;
+
+import java.util.List;
+
+public class DubboFilterBuildInterceptor {
+
+ @RuntimeType
+ public Object intercept(
+ @Argument(0) final Invoker invoker,
+ @Argument(1) final String key,
+ @Argument(2) final String group)
+ throws Exception {
+ final URL newURL = invoker.getUrl().addParameter(key, "skywalking$enhanceFilter");
+ Invoker last = invoker;
+ List filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(newURL, key, group);
+ if (filters.size() > 0) {
+ for (int i = filters.size() - 1; i >= 0; i--) {
+ final Filter filter = filters.get(i);
+ final Invoker next = last;
+ last = new Invoker() {
+ public Class getInterface() {
+ return invoker.getInterface();
+ }
+
+ public URL getUrl() {
+ return newURL;
+ }
+
+ public boolean isAvailable() {
+ return invoker.isAvailable();
+ }
+
+ public Result invoke(Invocation invocation) throws RpcException {
+ return filter.invoke(next, invocation);
+ }
+
+ public void destroy() {
+ invoker.destroy();
+ }
+
+ @Override
+ public String toString() {
+ return invoker.toString();
+ }
+ };
+ }
+ }
+ return last;
+ }
+}
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/ai/cloud/skywalking/plugin/DubboPluginDefine.java b/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/ai/cloud/skywalking/plugin/DubboPluginDefine.java
new file mode 100644
index 000000000..93ceb6490
--- /dev/null
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/main/java/com/ai/cloud/skywalking/plugin/DubboPluginDefine.java
@@ -0,0 +1,43 @@
+package com.ai.cloud.skywalking.plugin;
+
+import com.ai.cloud.skywalking.conf.AuthDesc;
+import com.ai.cloud.skywalking.plugin.boot.BootException;
+import com.ai.cloud.skywalking.plugin.boot.BootPluginDefine;
+import com.alibaba.dubbo.rpc.Invoker;
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.dynamic.ClassFileLocator;
+import net.bytebuddy.dynamic.DynamicType;
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+import net.bytebuddy.implementation.MethodDelegation;
+import net.bytebuddy.pool.TypePool;
+
+import static com.ai.cloud.skywalking.plugin.PluginBootstrap.CLASS_TYPE_POOL;
+import static net.bytebuddy.matcher.ElementMatchers.named;
+import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
+
+public class DubboPluginDefine extends BootPluginDefine {
+
+ private static final String interceptorClassName = "com.alibaba.dubbo.rpc.protocol.ProtocolFilterWrapper";
+
+ @Override
+ protected void boot() throws BootException {
+ if (!AuthDesc.isAuth()) {
+ return;
+ }
+
+ TypePool.Resolution resolution = CLASS_TYPE_POOL.describe(interceptorClassName);
+ DynamicType.Builder> newClassBuilder = new ByteBuddy()
+ .rebase(resolution.resolve(),
+ ClassFileLocator.ForClassLoader.ofClassPath());
+
+ newClassBuilder = newClassBuilder.method(named("buildInvokerChain")
+ .and(takesArguments(Invoker.class, String.class, String.class)))
+ .intercept(MethodDelegation.to(new DubboFilterBuildInterceptor()));
+
+ newClassBuilder
+ .name(interceptorClassName)
+ .make()
+ .load(ClassLoader.getSystemClassLoader(),
+ ClassLoadingStrategy.Default.INJECTION).getLoaded();
+ }
+}
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter b/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
index 55c08d1a3..459683129 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter
@@ -1 +1 @@
-swEnhanceFilter=com.ai.cloud.skywalking.plugin.dubbo.SWDubboEnhanceFilter
\ No newline at end of file
+skywalking$enhanceFilter=com.ai.cloud.skywalking.plugin.dubbo.SWDubboEnhanceFilter
\ No newline at end of file
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def b/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def
new file mode 100644
index 000000000..5ac0cb551
--- /dev/null
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/main/resources/skywalking-plugin.def
@@ -0,0 +1 @@
+com.ai.cloud.skywalking.plugin.DubboPluginDefine
\ No newline at end of file
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/consumer/DubboConsumer.java b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/consumer/DubboConsumer.java
index dfd9d0d34..614c9184e 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/consumer/DubboConsumer.java
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/consumer/DubboConsumer.java
@@ -1,15 +1,29 @@
package com.ai.cloud.skywalking.plugin.test.dubbo.consumer;
+import com.ai.cloud.skywalking.plugin.TracingBootstrap;
import com.ai.cloud.skywalking.plugin.test.dubbo.interfaces.IDubboInterA;
+import com.ai.skywalking.testframework.api.TraceTreeAssert;
+import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import java.lang.reflect.InvocationTargetException;
+
public class DubboConsumer {
+
+ @Test
+ public void test() throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException {
+ TracingBootstrap
+ .main(new String[]{"com.ai.cloud.skywalking.plugin.test.dubbo.consumer.DubboConsumer"});
+ }
+
public static void main(String[] args) throws InterruptedException {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:consumer/dubbo-consumer.xml");
IDubboInterA dubboInterA = context.getBean(IDubboInterA.class);
dubboInterA.doBusiness("AAAAA");
- Thread.sleep(10000000L);
+ TraceTreeAssert.assertEquals(new String[][]{
+ {"0", "dubbo://127.0.0.1:20880/com.ai.cloud.skywalking.plugin.test.dubbo.interfaces.IDubboInterA.doBusiness(String)", ""}
+ });
}
}
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/impl/DubboStart.java b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/impl/DubboStart.java
index bfa03f9dd..9f48f0781 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/impl/DubboStart.java
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbo/impl/DubboStart.java
@@ -1,9 +1,19 @@
package com.ai.cloud.skywalking.plugin.test.dubbo.impl;
+import com.ai.cloud.skywalking.plugin.TracingBootstrap;
+import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import java.lang.reflect.InvocationTargetException;
+
public class DubboStart {
+ @Test
+ public void test() throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException {
+ TracingBootstrap
+ .main(new String[]{"com.ai.cloud.skywalking.plugin.test.dubbo.impl.DubboStart"});
+ }
+
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new
ClassPathXmlApplicationContext("classpath*:provider/dubbo-provider.xml");
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestConsumer.java b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestConsumer.java
index 5b09502f2..739f7739b 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestConsumer.java
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestConsumer.java
@@ -1,24 +1,36 @@
package com.ai.cloud.skywalking.plugin.test.dubbox283.consumer;
+import com.ai.cloud.skywalking.plugin.TracingBootstrap;
import com.ai.cloud.skywalking.plugin.dubbox.bugfix.below283.BugFixAcitve;
import com.ai.cloud.skywalking.plugin.test.dubbox283.interfaces.IDubboxRestInterA;
import com.ai.cloud.skywalking.plugin.test.dubbox283.interfaces.param.DubboxRestInterAParameter;
+import com.ai.skywalking.testframework.api.TraceTreeAssert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
public class DubboxRestConsumer {
private static final Log logger = LogFactory.getLog(DubboxRestConsumer.class);
+ @Test
+ public void test() throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException {
+ TracingBootstrap
+ .main(new String[]{"com.ai.cloud.skywalking.plugin.test.dubbox283.consumer.DubboxRestConsumer"});
+ }
+
public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
new BugFixAcitve();
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:consumer/dubbox283-consumer.xml");
IDubboxRestInterA dubboxRestInterA = context.getBean(IDubboxRestInterA.class);
dubboxRestInterA.doBusiness(new DubboxRestInterAParameter("AAAAA"));
- Thread.sleep(10000000L);
+ TraceTreeAssert.assertEquals(new String[][]{
+ {"0", "rest://127.0.0.1:20880/com.ai.cloud.skywalking.plugin.test.dubbox283.interfaces.IDubboxRestInterA.doBusiness(DubboxRestInterAParameter)", ""}
+ });
}
}
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestStart.java b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestStart.java
index 867310d52..96116300e 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestStart.java
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox283/consumer/DubboxRestStart.java
@@ -1,10 +1,20 @@
package com.ai.cloud.skywalking.plugin.test.dubbox283.consumer;
+import com.ai.cloud.skywalking.plugin.TracingBootstrap;
import com.ai.cloud.skywalking.plugin.dubbox.bugfix.below283.BugFixAcitve;
+import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import java.lang.reflect.InvocationTargetException;
+
public class DubboxRestStart {
+ @Test
+ public void test() throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException {
+ TracingBootstrap
+ .main(new String[]{"com.ai.cloud.skywalking.plugin.test.dubbox283.consumer.DubboxRestStart"});
+ }
+
public static void main(String[] args) throws InterruptedException {
new BugFixAcitve();
ClassPathXmlApplicationContext classPathXmlApplicationContext = new
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestConsumer.java b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestConsumer.java
index 69a6df1ae..420ac8e28 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestConsumer.java
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestConsumer.java
@@ -1,22 +1,34 @@
package com.ai.cloud.skywalking.plugin.test.dubbox284.consumer;
+import com.ai.cloud.skywalking.plugin.TracingBootstrap;
import com.ai.cloud.skywalking.plugin.test.dubbox283.interfaces.param.DubboxRestInterAParameter;
import com.ai.cloud.skywalking.plugin.test.dubbox284.interfaces.IDubboxRestInterA;
+import com.ai.skywalking.testframework.api.TraceTreeAssert;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
import java.net.URISyntaxException;
public class DubboxRestConsumer {
private static final Log logger = LogFactory.getLog(DubboxRestConsumer.class);
+ @Test
+ public void test() throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException {
+ TracingBootstrap
+ .main(new String[]{"com.ai.cloud.skywalking.plugin.test.dubbox284.consumer.DubboxRestConsumer"});
+ }
+
public static void main(String[] args) throws IOException, URISyntaxException, InterruptedException {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:consumer/dubbox284-consumer.xml");
IDubboxRestInterA dubboxRestInterA = context.getBean(IDubboxRestInterA.class);
dubboxRestInterA.doBusiness(new DubboxRestInterAParameter("AAAAA"));
- Thread.sleep(10000000L);
+ TraceTreeAssert.assertEquals(new String[][]{
+ {"0", "rest://127.0.0.1:20880/com.ai.cloud.skywalking.plugin.test.dubbox284.interfaces.IDubboxRestInterA.doBusiness(DubboxRestInterAParameter)", ""}
+ });
}
}
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestStart.java b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestStart.java
index 67af9c4e4..2c384bc59 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestStart.java
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/java/com/ai/cloud/skywalking/plugin/test/dubbox284/consumer/DubboxRestStart.java
@@ -1,10 +1,20 @@
package com.ai.cloud.skywalking.plugin.test.dubbox284.consumer;
+import com.ai.cloud.skywalking.plugin.TracingBootstrap;
import com.ai.cloud.skywalking.plugin.dubbox.bugfix.below283.BugFixAcitve;
+import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
+import java.lang.reflect.InvocationTargetException;
+
public class DubboxRestStart {
+ @Test
+ public void test() throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, IllegalAccessException {
+ TracingBootstrap
+ .main(new String[]{"com.ai.cloud.skywalking.plugin.test.dubbox284.consumer.DubboxRestStart"});
+ }
+
public static void main(String[] args) throws InterruptedException {
new BugFixAcitve();
ClassPathXmlApplicationContext classPathXmlApplicationContext = new
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbo-consumer.xml b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbo-consumer.xml
index 61f1dfd32..d22f5436b 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbo-consumer.xml
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbo-consumer.xml
@@ -7,8 +7,7 @@
-
+ url="dubbo://127.0.0.1:20880"/>
\ No newline at end of file
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox283-consumer.xml b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox283-consumer.xml
index 1f250e20a..64db18cb9 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox283-consumer.xml
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox283-consumer.xml
@@ -7,8 +7,7 @@
-
+ url="rest://127.0.0.1:20880"/>
\ No newline at end of file
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox284-consumer.xml b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox284-consumer.xml
index 3ff101b44..df85b2acf 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox284-consumer.xml
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/consumer/dubbox284-consumer.xml
@@ -7,9 +7,8 @@
-
+ url="rest://127.0.0.1:20880"/>
\ No newline at end of file
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbo-provider.xml b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbo-provider.xml
index 577f5d1b8..8bb81ae9d 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbo-provider.xml
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbo-provider.xml
@@ -11,7 +11,6 @@
-
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox283-provider.xml b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox283-provider.xml
index 5beb68624..3c285cc84 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox283-provider.xml
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox283-provider.xml
@@ -8,7 +8,6 @@
-
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox284-provider.xml b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox284-provider.xml
index 43f413314..c60c48898 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox284-provider.xml
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/provider/dubbox284-provider.xml
@@ -8,7 +8,6 @@
-
diff --git a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/sky-walking.auth b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/sky-walking.auth
index cc8b1c7bb..ff0b6dcf1 100644
--- a/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/sky-walking.auth
+++ b/skywalking-sdk-plugin/dubbo-plugin/src/test/resources/sky-walking.auth
@@ -6,6 +6,7 @@ skywalking.application_code=test
skywalking.auth_system_env_name=SKYWALKING_RUN
#skywalking数据编码
skywalking.charset=UTF-8
+skywalking.auth_override=true
#是否打印数据
buriedpoint.printf=true
@@ -27,11 +28,8 @@ sender.max_send_length=20000
#当没有Sender时,尝试获取sender的等待周期
sender.retry_get_sender_wait_interval=2000
-
-
-
#最大消费线程数
-consumer.max_consumer=2
+consumer.max_consumer=0
#消费者最大等待时间
consumer.max_wait_time=5
#发送失败等待时间