-
Notifications
You must be signed in to change notification settings - Fork 26.6k
Closed
Description
Environment
- Dubbo version: 3.0
github构建日志
[INFO] Running org.apache.dubbo.remoting.api.MultiplexProtocolConnectionManagerTest
Error: Tests run: 2, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.046 s <<< FAILURE! - in org.apache.dubbo.remoting.api.MultiplexProtocolConnectionManagerTest
Error: testForEachConnection Time elapsed: 0.029 s <<< ERROR!
java.lang.IllegalStateException: No such extension org.apache.dubbo.remoting.api.WireProtocol by name tri, no related exception was found, please check whether related SPI module is missing.
at org.apache.dubbo.remoting.api.MultiplexProtocolConnectionManagerTest.testForEachConnection(MultiplexProtocolConnectionManagerTest.java:53)
测试方法代码:
public void testForEachConnection() throws RemotingException {
{
URL url = URL.valueOf("empty://127.0.0.1:8080?foo=bar");
Connection connect = connectionManager.connect(url);
}
{
URL url = URL.valueOf("tri://127.0.0.1:8080?foo=bar");
Connection connect = connectionManager.connect(url); <== throw IllegalStateException at line 53
}
Consumer<Connection> consumer = new Consumer<Connection>() {
@Override
public void accept(Connection connection) {
try {
Assertions.assertEquals("empty", connection.getUrl().getProtocol());
} catch (Exception e) {
Assertions.assertEquals("tri", connection.getUrl().getProtocol());
}
}
};
connectionManager.forEachConnection(consumer);
}
问题重现方法:
把创建两个Connection的代码块顺序颠倒一下,首先创建tri的connection。
分析原因:
指令重排导致tri的连接先行创建,但META-INF/dubbo/internal/org.apache.dubbo.remoting.api.WireProtocol文件里没有配置tri扩展。
其他问题:
- 两个connection的url用了相同的地址(host和port相同),导致只会建一个Connection;
- catch捕捉的类型错, 断言异常AssertionFailedError是Error类型,捕获Exception是捕获不到的 ;
- 测试方法结束时两个connection都没有关闭,SingleProtocolConnectionManager全局对象里的connections没有清空,影响后续测试类,修复前两个问题会导致windows环境github构建失败(windows默认按字母顺序执行测试,SingleProtocolConnectionManagerTest在MultiplexProtocolConnectionManagerTest后面)。
另外有个涉及MultiplexProtocolConnectionManager的疑问:
MultiplexProtocolConnectionManager的createSingleProtocolConnectionManager方法虽然传入了protocol:
private ConnectionManager createSingleProtocolConnectionManager(String protocol) {
return frameworkModel.getExtensionLoader(ConnectionManager.class).getExtension("single");
}
但并没有用到这个protocol参数,返回的SingleProtocolConnectionManager都是同一个对象,这样MultiplexProtocolConnectionManager的connect方法往下面这个map里面放的ConnectionManager都是同一个SingleProtocolConnectionManager对象:
private final ConcurrentMap<String, ConnectionManager> protocols = new ConcurrentHashMap<>();
只有一个SingleProtocolConnectionManager为啥还要搞个map?MultiplexProtocolConnectionManager的forEachConnection方法遍历上面这个protocols,每个protocol都要搞一遍所有协议的全部连接,这样设计不太符合常理。
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels