Merge branch 'performance-tuning-2.7.x'

This commit is contained in:
ken.lj 2019-09-03 14:17:40 +08:00
commit 0872090fa4
104 changed files with 1315 additions and 1011 deletions

View File

@ -38,16 +38,15 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.ADDRESS_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.FORCE_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHOD_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
/**
* ConditionRouter
@ -238,7 +237,7 @@ public class ConditionRouter extends AbstractRouter {
} else {
sampleValue = sample.get(key);
if (sampleValue == null) {
sampleValue = sample.get(DEFAULT_KEY_PREFIX + key);
sampleValue = sample.get(key);
}
}
if (sampleValue != null) {

View File

@ -38,6 +38,11 @@ public class MockDirInvocation implements Invocation {
return "echo";
}
@Override
public String getServiceName() {
return "DemoService";
}
public Class<?>[] getParameterTypes() {
return new Class[]{String.class};
}

View File

@ -47,10 +47,10 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.CLUSTER_AVAILABLE_CHECK_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
@ -493,21 +493,21 @@ public class AbstractClusterInvokerTest {
Directory<DemoService> directory = new StaticDirectory<DemoService>(invokers);
FailoverClusterInvoker<DemoService> failoverClusterInvoker = new FailoverClusterInvoker<DemoService>(directory);
try {
failoverClusterInvoker.invoke(new RpcInvocation("sayHello", new Class<?>[0], new Object[0]));
failoverClusterInvoker.invoke(new RpcInvocation("sayHello", DemoService.class.getName(), new Class<?>[0], new Object[0]));
Assertions.fail();
} catch (RpcException e) {
Assertions.assertEquals(RpcException.TIMEOUT_EXCEPTION, e.getCode());
}
ForkingClusterInvoker<DemoService> forkingClusterInvoker = new ForkingClusterInvoker<DemoService>(directory);
try {
forkingClusterInvoker.invoke(new RpcInvocation("sayHello", new Class<?>[0], new Object[0]));
forkingClusterInvoker.invoke(new RpcInvocation("sayHello", DemoService.class.getName(), new Class<?>[0], new Object[0]));
Assertions.fail();
} catch (RpcException e) {
Assertions.assertEquals(RpcException.TIMEOUT_EXCEPTION, e.getCode());
}
FailfastClusterInvoker<DemoService> failfastClusterInvoker = new FailfastClusterInvoker<DemoService>(directory);
try {
failfastClusterInvoker.invoke(new RpcInvocation("sayHello", new Class<?>[0], new Object[0]));
failfastClusterInvoker.invoke(new RpcInvocation("sayHello", DemoService.class.getName(), new Class<?>[0], new Object[0]));
Assertions.fail();
} catch (RpcException e) {
Assertions.assertEquals(RpcException.TIMEOUT_EXCEPTION, e.getCode());

View File

@ -43,11 +43,11 @@ import java.util.concurrent.ConcurrentHashMap;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PORT_KEY;
@ -108,10 +108,14 @@ class URL implements Serializable {
private final Map<String, String> parameters;
private final Map<String, Map<String, String>> methodParameters;
// ==== cache ====
private volatile transient Map<String, Number> numbers;
private volatile transient Map<String, Map<String, Number>> methodNumbers;
private volatile transient Map<String, URL> urls;
private volatile transient String ip;
@ -124,6 +128,10 @@ class URL implements Serializable {
private volatile transient String string;
private final transient String serviceKey;
private final transient String serviceInterface;
protected URL() {
this.protocol = null;
this.username = null;
@ -132,6 +140,9 @@ class URL implements Serializable {
this.port = 0;
this.path = null;
this.parameters = null;
this.methodParameters = null;
this.serviceKey = null;
this.serviceInterface = null;
}
public URL(String protocol, String host, int port) {
@ -166,7 +177,24 @@ class URL implements Serializable {
this(protocol, username, password, host, port, path, CollectionUtils.toStringMap(pairs));
}
public URL(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
public URL(String protocol,
String username,
String password,
String host,
int port,
String path,
Map<String, String> parameters) {
this (protocol, username, password, host, port, path, parameters, toMethodParameters(parameters));
}
public URL(String protocol,
String username,
String password,
String host,
int port,
String path,
Map<String, String> parameters,
Map<String, Map<String, String>> methodParameters) {
if (StringUtils.isEmpty(username)
&& StringUtils.isNotEmpty(password)) {
throw new IllegalArgumentException("Invalid url, password without username!");
@ -187,6 +215,14 @@ class URL implements Serializable {
parameters = new HashMap<>(parameters);
}
this.parameters = Collections.unmodifiableMap(parameters);
this.methodParameters = Collections.unmodifiableMap(methodParameters);
this.serviceInterface = getParameter(INTERFACE_KEY, path);
if (this.serviceInterface == null) {
this.serviceKey = null;
} else {
this.serviceKey = buildKey(serviceInterface, getParameter(GROUP_KEY), getParameter(VERSION_KEY));
}
}
/**
@ -273,9 +309,41 @@ class URL implements Serializable {
if (url.length() > 0) {
host = url;
}
return new URL(protocol, username, password, host, port, path, parameters);
}
public static Map<String, Map<String, String>> toMethodParameters(Map<String, String> parameters) {
Map<String, Map<String, String>> methodParameters = new HashMap<>();
if (parameters != null) {
String methodsString = parameters.get(METHODS_KEY);
if (StringUtils.isNotEmpty(methodsString)) {
String[] methods = methodsString.split(",");
for (Map.Entry<String, String> entry : parameters.entrySet()) {
String key = entry.getKey();
for (String method : methods) {
String methodPrefix = method + ".";
if (key.startsWith(methodPrefix)) {
String realKey = key.substring(methodPrefix.length());
URL.putMethodParameter(method, realKey, entry.getValue(), methodParameters);
}
}
}
} else {
for (Map.Entry<String, String> entry : parameters.entrySet()) {
String key = entry.getKey();
int methodSeparator = key.indexOf(".");
if (methodSeparator > 0) {
String method = key.substring(0, methodSeparator);
String realKey = key.substring(methodSeparator + 1);
URL.putMethodParameter(method, realKey, entry.getValue(), methodParameters);
}
}
}
}
return methodParameters;
}
public static URL valueOf(String url, String... reserveParams) {
URL result = valueOf(url);
if (reserveParams == null || reserveParams.length == 0) {
@ -483,6 +551,10 @@ class URL implements Serializable {
return parameters;
}
public Map<String, Map<String, String>> getMethodParameters() {
return methodParameters;
}
public String getParameterAndDecoded(String key) {
return getParameterAndDecoded(key, null);
}
@ -492,8 +564,7 @@ class URL implements Serializable {
}
public String getParameter(String key) {
String value = parameters.get(key);
return StringUtils.isEmpty(value) ? parameters.get(DEFAULT_KEY_PREFIX + key) : value;
return parameters.get(key);
}
public String getParameter(String key, String defaultValue) {
@ -520,6 +591,13 @@ class URL implements Serializable {
return numbers == null ? new ConcurrentHashMap<>() : numbers;
}
private Map<String, Map<String, Number>> getMethodNumbers() {
if (methodNumbers == null) { // concurrent initialization is tolerant
methodNumbers = new ConcurrentHashMap<>();
}
return methodNumbers;
}
private Map<String, URL> getUrls() {
// concurrent initialization is tolerant
return urls == null ? new ConcurrentHashMap<>() : urls;
@ -695,8 +773,15 @@ class URL implements Serializable {
}
public String getMethodParameter(String method, String key) {
String value = parameters.get(method + "." + key);
return StringUtils.isEmpty(value) ? getParameter(key) : value;
Map<String, String> keyMap = methodParameters.get(method);
String value = null;
if (keyMap != null) {
value = keyMap.get(key);
}
if (StringUtils.isEmpty(value)) {
value = parameters.get(key);
}
return value;
}
public String getMethodParameter(String method, String key, String defaultValue) {
@ -705,8 +790,7 @@ class URL implements Serializable {
}
public double getMethodParameter(String method, String key, double defaultValue) {
String methodKey = method + "." + key;
Number n = getNumbers().get(methodKey);
Number n = getCachedNumber(method, key);
if (n != null) {
return n.doubleValue();
}
@ -715,13 +799,12 @@ class URL implements Serializable {
return defaultValue;
}
double d = Double.parseDouble(value);
getNumbers().put(methodKey, d);
updateCachedNumber(method, key, d);
return d;
}
public float getMethodParameter(String method, String key, float defaultValue) {
String methodKey = method + "." + key;
Number n = getNumbers().get(methodKey);
Number n = getCachedNumber(method, key);
if (n != null) {
return n.floatValue();
}
@ -730,13 +813,12 @@ class URL implements Serializable {
return defaultValue;
}
float f = Float.parseFloat(value);
getNumbers().put(methodKey, f);
updateCachedNumber(method, key, f);
return f;
}
public long getMethodParameter(String method, String key, long defaultValue) {
String methodKey = method + "." + key;
Number n = getNumbers().get(methodKey);
Number n = getCachedNumber(method, key);
if (n != null) {
return n.longValue();
}
@ -745,13 +827,12 @@ class URL implements Serializable {
return defaultValue;
}
long l = Long.parseLong(value);
getNumbers().put(methodKey, l);
updateCachedNumber(method, key, l);
return l;
}
public int getMethodParameter(String method, String key, int defaultValue) {
String methodKey = method + "." + key;
Number n = getNumbers().get(methodKey);
Number n = getCachedNumber(method, key);
if (n != null) {
return n.intValue();
}
@ -760,13 +841,12 @@ class URL implements Serializable {
return defaultValue;
}
int i = Integer.parseInt(value);
getNumbers().put(methodKey, i);
updateCachedNumber(method, key, i);
return i;
}
public short getMethodParameter(String method, String key, short defaultValue) {
String methodKey = method + "." + key;
Number n = getNumbers().get(methodKey);
Number n = getCachedNumber(method, key);
if (n != null) {
return n.shortValue();
}
@ -775,13 +855,12 @@ class URL implements Serializable {
return defaultValue;
}
short s = Short.parseShort(value);
getNumbers().put(methodKey, s);
updateCachedNumber(method, key, s);
return s;
}
public byte getMethodParameter(String method, String key, byte defaultValue) {
String methodKey = method + "." + key;
Number n = getNumbers().get(methodKey);
Number n = getCachedNumber(method, key);
if (n != null) {
return n.byteValue();
}
@ -790,10 +869,23 @@ class URL implements Serializable {
return defaultValue;
}
byte b = Byte.parseByte(value);
getNumbers().put(methodKey, b);
updateCachedNumber(method, key, b);
return b;
}
private Number getCachedNumber(String method, String key) {
Map<String, Number> keyNumber = getMethodNumbers().get(method);
if (keyNumber != null) {
return keyNumber.get(key);
}
return null;
}
private void updateCachedNumber(String method, String key, Number n) {
Map<String, Number> keyNumber = getMethodNumbers().computeIfAbsent(method, m -> new HashMap<>());
keyNumber.put(key, n);
}
public double getMethodPositiveParameter(String method, String key, double defaultValue) {
if (defaultValue <= 0) {
throw new IllegalArgumentException("defaultValue <= 0");
@ -875,6 +967,13 @@ class URL implements Serializable {
return value != null && value.length() > 0;
}
public boolean hasMethodParameter(String method) {
if (method == null) {
return false;
}
return getMethodParameters().containsKey(method);
}
public boolean isLocalHost() {
return NetUtils.isLocalHost(host) || getParameter(LOCALHOST_KEY, false);
}
@ -955,6 +1054,7 @@ class URL implements Serializable {
Map<String, String> map = new HashMap<>(getParameters());
map.put(key, value);
return new URL(protocol, username, password, host, port, path, map);
}
@ -968,9 +1068,43 @@ class URL implements Serializable {
}
Map<String, String> map = new HashMap<>(getParameters());
map.put(key, value);
return new URL(protocol, username, password, host, port, path, map);
}
public URL addMethodParameter(String method, String key, String value) {
if (StringUtils.isEmpty(method)
|| StringUtils.isEmpty(key)
|| StringUtils.isEmpty(value)) {
return this;
}
Map<String, String> map = new HashMap<>(getParameters());
map.put(method + "." + key, value);
Map<String, Map<String, String>> methodMap = toMethodParameters(map);
URL.putMethodParameter(method, key, value, methodMap);
return new URL(protocol, username, password, host, port, path, map, methodMap);
}
public URL addMethodParameterIfAbsent(String method, String key, String value) {
if (StringUtils.isEmpty(method)
|| StringUtils.isEmpty(key)
|| StringUtils.isEmpty(value)) {
return this;
}
if (hasMethodParameter(method, key)) {
return this;
}
Map<String, String> map = new HashMap<>(getParameters());
map.put(method + "." + key, value);
Map<String, Map<String, String>> methodMap = toMethodParameters(map);
URL.putMethodParameter(method, key, value, methodMap);
return new URL(protocol, username, password, host, port, path, map, methodMap);
}
/**
* Add parameters to a new url.
*
@ -1274,11 +1408,7 @@ class URL implements Serializable {
* @return
*/
public String getServiceKey() {
String inf = getServiceInterface();
if (inf == null) {
return null;
}
return buildKey(inf, getParameter(GROUP_KEY), getParameter(VERSION_KEY));
return serviceKey;
}
/**
@ -1496,4 +1626,9 @@ class URL implements Serializable {
return true;
}
public static void putMethodParameter(String method, String key, String value, Map<String, Map<String, String>> methodParameters) {
Map<String, String> subParameter = methodParameters.computeIfAbsent(method, k -> new HashMap<>());
subParameter.put(key, value);
}
}

View File

@ -24,8 +24,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
public final class URLBuilder {
private String protocol;
@ -43,6 +41,8 @@ public final class URLBuilder {
private Map<String, String> parameters;
private Map<String, Map<String, String>> methodParameters;
public URLBuilder() {
protocol = null;
username = null;
@ -51,6 +51,7 @@ public final class URLBuilder {
port = 0;
path = null;
parameters = new HashMap<>();
methodParameters = new HashMap<>();
}
public URLBuilder(String protocol, String host, int port) {
@ -77,7 +78,22 @@ public final class URLBuilder {
this(protocol, null, null, host, port, path, parameters);
}
public URLBuilder(String protocol, String username, String password, String host, int port, String path, Map<String, String> parameters) {
public URLBuilder(String protocol,
String username,
String password,
String host,
int port,
String path, Map<String, String> parameters) {
this(protocol, username, password, host, port, path, parameters, URL.toMethodParameters(parameters));
}
public URLBuilder(String protocol,
String username,
String password,
String host,
int port,
String path, Map<String, String> parameters,
Map<String, Map<String, String>> methodParameters) {
this.protocol = protocol;
this.username = username;
this.password = password;
@ -85,6 +101,7 @@ public final class URLBuilder {
this.port = port;
this.path = path;
this.parameters = parameters != null ? parameters : new HashMap<>();
this.methodParameters = (methodParameters != null ? methodParameters : new HashMap<>());
}
public static URLBuilder from(URL url) {
@ -95,6 +112,7 @@ public final class URLBuilder {
int port = url.getPort();
String path = url.getPath();
Map<String, String> parameters = new HashMap<>(url.getParameters());
Map<String, Map<String, String>> methodParameters = new HashMap<>(url.getMethodParameters());
return new URLBuilder(
protocol,
username,
@ -102,7 +120,8 @@ public final class URLBuilder {
host,
port,
path,
parameters);
parameters,
methodParameters);
}
public URL build() {
@ -122,7 +141,7 @@ public final class URLBuilder {
path = path.substring(firstNonSlash);
}
}
return new URL(protocol, username, password, host, port, path, parameters);
return new URL(protocol, username, password, host, port, path, parameters, methodParameters);
}
@ -235,15 +254,19 @@ public final class URLBuilder {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
}
// if value doesn't change, return immediately
if (value.equals(parameters.get(key))) { // value != null
return this;
}
parameters.put(key, value);
return this;
}
public URLBuilder addMethodParameter(String method, String key, String value) {
if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
}
URL.putMethodParameter(method, key, value, methodParameters);
return this;
}
public URLBuilder addParameterIfAbsent(String key, String value) {
if (StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
@ -255,6 +278,17 @@ public final class URLBuilder {
return this;
}
public URLBuilder addMethodParameterIfAbsent(String method, String key, String value) {
if (StringUtils.isEmpty(method) || StringUtils.isEmpty(key) || StringUtils.isEmpty(value)) {
return this;
}
if (hasMethodParameter(method, key)) {
return this;
}
URL.putMethodParameter(method, key, value, methodParameters);
return this;
}
public URLBuilder addParameters(Map<String, String> parameters) {
if (CollectionUtils.isEmptyMap(parameters)) {
return this;
@ -278,6 +312,15 @@ public final class URLBuilder {
return this;
}
public URLBuilder addMethodParameters(Map<String, Map<String, String>> methodParameters) {
if (CollectionUtils.isEmptyMap(methodParameters)) {
return this;
}
this.methodParameters.putAll(methodParameters);
return this;
}
public URLBuilder addParametersIfAbsent(Map<String, String> parameters) {
if (CollectionUtils.isEmptyMap(parameters)) {
return this;
@ -342,10 +385,38 @@ public final class URLBuilder {
return value != null && value.length() > 0;
}
public boolean hasMethodParameter(String method, String key) {
if (method == null) {
String suffix = "." + key;
for (String fullKey : parameters.keySet()) {
if (fullKey.endsWith(suffix)) {
return true;
}
}
return false;
}
if (key == null) {
String prefix = method + ".";
for (String fullKey : parameters.keySet()) {
if (fullKey.startsWith(prefix)) {
return true;
}
}
return false;
}
String value = getMethodParameter(method, key);
return value != null && value.length() > 0;
}
public String getParameter(String key) {
String value = parameters.get(key);
if (StringUtils.isEmpty(value)) {
value = parameters.get(DEFAULT_KEY_PREFIX + key);
return parameters.get(key);
}
public String getMethodParameter(String method, String key) {
Map<String, String> keyMap = methodParameters.get(method);
String value = null;
if (keyMap != null) {
value = keyMap.get(key);
}
return value;
}

View File

@ -77,6 +77,8 @@ public interface CommonConstants {
int DEFAULT_THREADS = 200;
String EXECUTOR_SERVICE_COMPONENT_KEY = ExecutorService.class.getName();
String THREADPOOL_KEY = "threadpool";
String THREAD_NAME_KEY = "threadname";
@ -171,6 +173,12 @@ public interface CommonConstants {
*/
String PROXY_CLASS_REF = "refClass";
/**
* generic call
*/
String $INVOKE = "$invoke";
String $INVOKE_ASYNC = "$invokeAsync";
/**
* package version in the manifest
*/

View File

@ -37,7 +37,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY;
/**
* Consider implementing {@link Licycle} to enable executors shutdown when the process stops.
* Consider implementing {@code Licycle} to enable executors shutdown when the process stops.
*/
public class DefaultExecutorRepository implements ExecutorRepository {
private static final Logger logger = LoggerFactory.getLogger(DefaultExecutorRepository.class);
@ -50,15 +50,15 @@ public class DefaultExecutorRepository implements ExecutorRepository {
private ScheduledExecutorService reconnectScheduledExecutor;
private ConcurrentMap<String, ConcurrentMap<String, ExecutorService>> data = new ConcurrentHashMap<>();
private ConcurrentMap<String, ConcurrentMap<Integer, ExecutorService>> data = new ConcurrentHashMap<>();
public DefaultExecutorRepository() {
for (int i = 0; i < DEFAULT_SCHEDULER_SIZE; i++) {
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-framework-scheduler"));
scheduledExecutors.addItem(scheduler);
}
reconnectScheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-reconnect-scheduler"));
// for (int i = 0; i < DEFAULT_SCHEDULER_SIZE; i++) {
// ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-framework-scheduler"));
// scheduledExecutors.addItem(scheduler);
// }
//
// reconnectScheduledExecutor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("Dubbo-reconnect-scheduler"));
}
public ExecutorService createExecutorIfAbsent(URL url) {
@ -66,8 +66,20 @@ public class DefaultExecutorRepository implements ExecutorRepository {
if (CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(SIDE_KEY))) {
componentKey = CONSUMER_SIDE;
}
Map<String, ExecutorService> executors = data.computeIfAbsent(componentKey, k -> new ConcurrentHashMap<>());
return executors.computeIfAbsent(Integer.toString(url.getPort()), k -> (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url));
Map<Integer, ExecutorService> executors = data.computeIfAbsent(componentKey, k -> new ConcurrentHashMap<>());
return executors.computeIfAbsent(url.getPort(), k -> (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url));
}
public ExecutorService getExecutor(URL url) {
String componentKey = EXECUTOR_SERVICE_COMPONENT_KEY;
if (CONSUMER_SIDE.equalsIgnoreCase(url.getParameter(SIDE_KEY))) {
componentKey = CONSUMER_SIDE;
}
Map<Integer, ExecutorService> executors = data.get(componentKey);
if (executors == null) {
return null;
}
return executors.get(url.getPort());
}
@Override

View File

@ -37,6 +37,8 @@ public interface ExecutorRepository {
*/
ExecutorService createExecutorIfAbsent(URL url);
ExecutorService getExecutor(URL url);
/**
* Modify some of the threadpool's properties according to the url, for example, coreSize, maxSize, ...
*

View File

@ -180,6 +180,17 @@ public class NetUtils {
return address;
}
private static volatile String HOST_ADDRESS;
public static String getHostAddress () {
if (HOST_ADDRESS != null) {
return HOST_ADDRESS;
}
HOST_ADDRESS = getLocalHost();
return HOST_ADDRESS;
}
public static String getLocalHost() {
InetAddress address = getLocalAddress();
return address == null ? LOCALHOST_VALUE : address.getHostAddress();

View File

@ -1,8 +1,8 @@
package org.apache.dubbo.common.beanutil;
import org.apache.dubbo.common.model.person.FullAddress;
import org.apache.dubbo.common.model.person.PersonStatus;
import org.apache.dubbo.common.model.person.Phone;
import org.apache.dubbo.rpc.model.person.FullAddress;
import org.apache.dubbo.rpc.model.person.PersonStatus;
import org.apache.dubbo.rpc.model.person.Phone;
import java.util.Collection;
import java.util.Date;

View File

@ -16,12 +16,12 @@
*/
package org.apache.dubbo.common.beanutil;
import org.apache.dubbo.common.model.person.BigPerson;
import org.apache.dubbo.common.model.person.FullAddress;
import org.apache.dubbo.common.model.person.PersonInfo;
import org.apache.dubbo.common.model.person.PersonStatus;
import org.apache.dubbo.common.model.person.Phone;
import org.apache.dubbo.common.utils.PojoUtilsTest;
import org.apache.dubbo.rpc.model.person.BigPerson;
import org.apache.dubbo.rpc.model.person.FullAddress;
import org.apache.dubbo.rpc.model.person.PersonInfo;
import org.apache.dubbo.rpc.model.person.PersonStatus;
import org.apache.dubbo.rpc.model.person.Phone;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

View File

@ -16,14 +16,15 @@
*/
package org.apache.dubbo.common.utils;
import org.apache.dubbo.common.model.Person;
import org.apache.dubbo.common.model.SerializablePerson;
import org.apache.dubbo.common.model.User;
import org.apache.dubbo.common.model.person.BigPerson;
import org.apache.dubbo.common.model.person.FullAddress;
import org.apache.dubbo.common.model.person.PersonInfo;
import org.apache.dubbo.common.model.person.PersonStatus;
import org.apache.dubbo.common.model.person.Phone;
import org.apache.dubbo.rpc.model.Person;
import org.apache.dubbo.rpc.model.SerializablePerson;
import org.apache.dubbo.rpc.model.User;
import org.apache.dubbo.rpc.model.person.BigPerson;
import org.apache.dubbo.rpc.model.person.FullAddress;
import org.apache.dubbo.rpc.model.person.PersonInfo;
import org.apache.dubbo.rpc.model.person.PersonStatus;
import org.apache.dubbo.rpc.model.person.Phone;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -41,13 +42,13 @@ import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class PojoUtilsTest {
@ -696,7 +697,7 @@ public class PojoUtilsTest {
assertTrue(personInfo.isMale());
assertFalse(personInfo.isFemale());
}
@Test
public void testRealizeCollectionWithNullElement() {
LinkedList<String> listStr = new LinkedList<>();

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model;
package org.apache.dubbo.rpc.model;
import java.util.Arrays;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model;
package org.apache.dubbo.rpc.model;
import java.io.Serializable;
import java.util.Arrays;

View File

@ -15,7 +15,7 @@
* limitations under the License.
*/
package org.apache.dubbo.common.model;
package org.apache.dubbo.rpc.model;
import java.util.Objects;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model.media;
package org.apache.dubbo.rpc.model.media;
public class Image implements java.io.Serializable {

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model.media;
package org.apache.dubbo.rpc.model.media;
import java.util.List;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model.person;
package org.apache.dubbo.rpc.model.person;
import java.io.Serializable;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model.person;
package org.apache.dubbo.rpc.model.person;
import java.io.Serializable;

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model.person;
package org.apache.dubbo.rpc.model.person;
import java.io.Serializable;
import java.util.List;

View File

@ -1,22 +1,22 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model.person;
public enum PersonStatus {
ENABLED,
DISABLED
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model.person;
public enum PersonStatus {
ENABLED,
DISABLED
}

View File

@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.model.person;
package org.apache.dubbo.rpc.model.person;
import java.io.Serializable;

View File

@ -38,6 +38,11 @@ public interface Invocation extends org.apache.dubbo.rpc.Invocation {
}
@Override
default String getServiceName() {
return null;
}
class CompatibleInvocation implements Invocation {
private org.apache.dubbo.rpc.Invocation delegate;

View File

@ -17,8 +17,14 @@
package com.alibaba.dubbo.rpc;
import org.apache.dubbo.rpc.AppResponse;
import java.util.Map;
import java.util.function.BiConsumer;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
@Deprecated
public interface Result extends org.apache.dubbo.rpc.Result {
@ -36,7 +42,27 @@ public interface Result extends org.apache.dubbo.rpc.Result {
abstract class AbstractResult extends org.apache.dubbo.rpc.AbstractResult implements Result {
@Override
public org.apache.dubbo.rpc.Result whenCompleteWithContext(BiConsumer<org.apache.dubbo.rpc.Result, Throwable> fn) {
public void setValue(Object value) {
}
@Override
public org.apache.dubbo.rpc.Result thenApplyWithContext(Function<AppResponse, AppResponse> fn) {
return null;
}
@Override
public <U> CompletableFuture<U> thenApply(Function<org.apache.dubbo.rpc.Result, ? extends U> fn) {
return null;
}
@Override
public org.apache.dubbo.rpc.Result get() throws InterruptedException, ExecutionException {
return null;
}
@Override
public org.apache.dubbo.rpc.Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return null;
}
}
@ -83,32 +109,32 @@ public interface Result extends org.apache.dubbo.rpc.Result {
}
@Override
public Map<String, Object> getAttachments() {
public Map<String, String> getAttachments() {
return delegate.getAttachments();
}
@Override
public void addAttachments(Map<String, Object> map) {
public void addAttachments(Map<String, String> map) {
delegate.addAttachments(map);
}
@Override
public void setAttachments(Map<String, Object> map) {
public void setAttachments(Map<String, String> map) {
delegate.setAttachments(map);
}
@Override
public Object getAttachment(String key) {
public String getAttachment(String key) {
return delegate.getAttachment(key);
}
@Override
public Object getAttachment(String key, Object defaultValue) {
public String getAttachment(String key, String defaultValue) {
return delegate.getAttachment(key, defaultValue);
}
@Override
public void setAttachment(String key, Object value) {
public void setAttachment(String key, String value) {
delegate.setAttachment(key, value);
}
}

View File

@ -17,7 +17,7 @@
package org.apache.dubbo.config;
import org.apache.dubbo.rpc.model.ConsumerMethodModel;
import org.apache.dubbo.rpc.model.ConsumerModel;
import org.apache.dubbo.service.Person;
import com.alibaba.dubbo.config.ArgumentConfig;
@ -43,7 +43,6 @@ import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class MethodConfigTest {
@Test
@ -113,7 +112,7 @@ public class MethodConfigTest {
methodConfig.setOninvokeMethod("setName");
methodConfig.setOninvoke(new Person());
ConsumerMethodModel.AsyncMethodInfo methodInfo = org.apache.dubbo.config.MethodConfig.convertMethodConfig2AsyncInfo(methodConfig);
ConsumerModel.AsyncMethodInfo methodInfo = org.apache.dubbo.config.MethodConfig.convertMethodConfig2AyncInfo(methodConfig);
assertEquals(methodInfo.getOninvokeMethod(), Person.class.getMethod("setName", String.class));
}

View File

@ -44,6 +44,11 @@ public class MockInvocation implements Invocation {
return "echo";
}
@Override
public String getServiceName() {
return "DemoService";
}
public Class<?>[] getParameterTypes() {
return new Class[]{String.class};
}
@ -100,4 +105,4 @@ public class MockInvocation implements Invocation {
return getAttachments().get(key);
}
}
}

View File

@ -179,11 +179,7 @@ public abstract class AbstractConfig implements Serializable {
str = URL.encode(str);
}
if (parameter != null && parameter.append()) {
String pre = parameters.get(DEFAULT_KEY + "." + key);
if (pre != null && pre.length() > 0) {
str = pre + "," + str;
}
pre = parameters.get(key);
String pre = parameters.get(key);
if (pre != null && pre.length() > 0) {
str = pre + "," + str;
}

View File

@ -47,7 +47,6 @@ import org.apache.dubbo.rpc.support.ProtocolUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@ -327,7 +326,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
appendParameters(map, this);
Map<String, Object> attributes = null;
if (CollectionUtils.isNotEmpty(methods)) {
attributes = new HashMap<String, Object>();
attributes = new HashMap<>();
for (MethodConfig methodConfig : methods) {
appendParameters(map, methodConfig, methodConfig.getName());
String retryKey = methodConfig.getName() + ".retry";
@ -383,6 +382,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
}
}
return new ConsumerModel(attributes, metadata);
return new ConsumerModel(serviceKey, interfaceClass, ref, ApplicationModel.registerServiceModel(interfaceClass), attributes);
}
@SuppressWarnings({"unchecked", "rawtypes", "deprecation"})

View File

@ -476,6 +476,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
String pathKey = URL.buildKey(getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), group, version);
serviceMetadata.setServiceKey(pathKey);
ProviderModel providerModel = new ProviderModel(ref, serviceMetadata);
ProviderModel providerModel = new ProviderModel(pathKey, ref, ApplicationModel.registerServiceModel(interfaceClass));
ApplicationModel.initProviderModel(pathKey, providerModel);
doExportUrlsFor1Protocol(protocolConfig, registryURLs);
}

View File

@ -132,7 +132,7 @@ public class CacheTest {
parameters.put("findCache.cache", "threadlocal");
URL url = new URL("dubbo", "127.0.0.1", 29582, "org.apache.dubbo.config.cache.CacheService", parameters);
Invocation invocation = new RpcInvocation("findCache", new Class[]{String.class}, new String[]{"0"}, null, null);
Invocation invocation = new RpcInvocation("findCache", "org.apache.dubbo.config.cache.CacheService", new Class[]{String.class}, new String[]{"0"}, null, null);
Cache cache = cacheFactory.getCache(url, invocation);
assertTrue(cache instanceof ThreadLocalCache);

View File

@ -22,5 +22,8 @@ public interface DemoService {
String sayHello(String name);
CompletableFuture<String> sayHelloAsync(String name);
default CompletableFuture<String> sayHelloAsync(String name) {
return CompletableFuture.completedFuture(sayHello(name));
}
}

View File

@ -20,12 +20,18 @@ import org.apache.dubbo.demo.DemoService;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.concurrent.CompletableFuture;
public class Application {
public static void main(String[] args) {
/**
* In order to make sure multicast registry works, need to specify '-Djava.net.preferIPv4Stack=true' before
* launch the application
*/
public static void main(String[] args) throws Exception {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/dubbo-consumer.xml");
context.start();
DemoService demoService = context.getBean("demoService", DemoService.class);
String hello = demoService.sayHello("world");
System.out.println("result: " + hello);
CompletableFuture<String> hello = demoService.sayHelloAsync("world");
System.out.println("result: " + hello.get());
}
}

View File

@ -30,17 +30,24 @@ public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
logger.info("Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
@Override
public CompletableFuture<String> sayHelloAsync(String name) {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return CompletableFuture.completedFuture("future return value!");
return "Hello " + name + ", response from provider: " + RpcContext.getContext().getLocalAddress();
}
@Override
public CompletableFuture<String> sayHelloAsync(String name) {
CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return "async result";
});
return cf;
}
}

View File

@ -119,7 +119,7 @@ public class MonitorFilterTest {
public void testFilter() throws Exception {
MonitorFilter monitorFilter = new MonitorFilter();
monitorFilter.setMonitorFactory(monitorFactory);
Invocation invocation = new RpcInvocation("aaa", new Class<?>[0], new Object[0]);
Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), new Class<?>[0], new Object[0]);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
Result result = monitorFilter.invoke(serviceInvoker, invocation);
result.whenCompleteWithContext((r, t) -> {
@ -149,7 +149,7 @@ public class MonitorFilterTest {
MonitorFilter monitorFilter = new MonitorFilter();
MonitorFactory mockMonitorFactory = mock(MonitorFactory.class);
monitorFilter.setMonitorFactory(mockMonitorFactory);
Invocation invocation = new RpcInvocation("aaa", new Class<?>[0], new Object[0]);
Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), new Class<?>[0], new Object[0]);
Invoker invoker = mock(Invoker.class);
given(invoker.getUrl()).willReturn(URL.valueOf("dubbo://" + NetUtils.getLocalHost() + ":20880?" + APPLICATION_KEY + "=abc&" + SIDE_KEY + "=" + CONSUMER_SIDE));
@ -162,7 +162,7 @@ public class MonitorFilterTest {
public void testGenericFilter() throws Exception {
MonitorFilter monitorFilter = new MonitorFilter();
monitorFilter.setMonitorFactory(monitorFactory);
Invocation invocation = new RpcInvocation("$invoke", new Class<?>[]{String.class, String[].class, Object[].class}, new Object[]{"xxx", new String[]{}, new Object[]{}});
Invocation invocation = new RpcInvocation("$invoke", MonitorService.class.getName(), new Class<?>[]{String.class, String[].class, Object[].class}, new Object[]{"xxx", new String[]{}, new Object[]{}});
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
Result result = monitorFilter.invoke(serviceInvoker, invocation);
result.whenCompleteWithContext((r, t) -> {
@ -196,7 +196,7 @@ public class MonitorFilterTest {
monitorFilter.setMonitorFactory(mockMonitorFactory);
given(mockMonitorFactory.getMonitor(any(URL.class))).willReturn(mockMonitor);
Invocation invocation = new RpcInvocation("aaa", new Class<?>[0], new Object[0]);
Invocation invocation = new RpcInvocation("aaa", MonitorService.class.getName(), new Class<?>[0], new Object[0]);
monitorFilter.invoke(serviceInvoker, invocation);
}

View File

@ -25,9 +25,10 @@ import org.apache.dubbo.monitor.support.AbstractMonitorFactory;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
import static org.apache.dubbo.remoting.Constants.CHECK_KEY;
import static org.apache.dubbo.rpc.Constants.REFERENCE_FILTER_KEY;
@ -63,6 +64,7 @@ public class DubboMonitorFactory extends AbstractMonitorFactory {
}
urlBuilder.addParameters(CHECK_KEY, String.valueOf(false),
REFERENCE_FILTER_KEY, filter + "-monitor");
ApplicationModel.registerServiceModel(MonitorService.class);
Invoker<MonitorService> monitorInvoker = protocol.refer(MonitorService.class, urlBuilder.build());
MonitorService monitorService = proxyFactory.getProxy(monitorInvoker);
return new DubboMonitor(monitorInvoker, monitorService);

View File

@ -31,6 +31,7 @@ import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.support.RpcUtils;
import com.alibaba.fastjson.JSON;
@ -56,6 +57,7 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_PROTOCOL;
import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY;
import static org.apache.dubbo.monitor.Constants.DUBBO_CONSUMER;
import static org.apache.dubbo.monitor.Constants.DUBBO_CONSUMER_METHOD;
import static org.apache.dubbo.monitor.Constants.DUBBO_GROUP;
@ -65,7 +67,6 @@ import static org.apache.dubbo.monitor.Constants.METHOD;
import static org.apache.dubbo.monitor.Constants.METRICS_PORT;
import static org.apache.dubbo.monitor.Constants.METRICS_PROTOCOL;
import static org.apache.dubbo.monitor.Constants.SERVICE;
import static org.apache.dubbo.remoting.Constants.EXECUTOR_SERVICE_COMPONENT_KEY;
public class MetricsFilter implements Filter {
@ -88,6 +89,7 @@ public class MetricsFilter implements Filter {
Invoker<MetricsService> metricsInvoker = initMetricsInvoker();
try {
ApplicationModel.registerServiceModel(MetricsService.class);
protocol.export(metricsInvoker);
} catch (RuntimeException e) {
logger.error("Metrics Service need to be configured" +

View File

@ -118,7 +118,7 @@ public class MetricsFilterTest {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation invocation = new RpcInvocation("sayName", new Class<?>[]{Integer.class}, new Object[0]);
Invocation invocation = new RpcInvocation("sayName", DemoService.class.getName(), new Class<?>[]{Integer.class}, new Object[0]);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(SIDE_KEY, CONSUMER_SIDE));
AppResponse response = AppResponseBuilder.create()
@ -146,7 +146,7 @@ public class MetricsFilterTest {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation invocation = new RpcInvocation("timeoutException", null, null);
Invocation invocation = new RpcInvocation("timeoutException", DemoService.class.getName(), null, null);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(timeoutInvoker.getUrl().addParameter(SIDE_KEY, CONSUMER_SIDE)
.addParameter(TIMEOUT_KEY, 300));
@ -179,7 +179,7 @@ public class MetricsFilterTest {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
Invocation invocation = new RpcInvocation("sayName", DemoService.class.getName(), new Class<?>[0], new Object[0]);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(SIDE_KEY, PROVIDER));
AppResponse response = AppResponseBuilder.create()
@ -206,7 +206,7 @@ public class MetricsFilterTest {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation invocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
Invocation invocation = new RpcInvocation("sayName", DemoService.class.getName(), new Class<?>[0], new Object[0]);
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(SIDE_KEY, PROVIDER_SIDE)
.addParameter(TIMEOUT_KEY, 300));
@ -224,7 +224,7 @@ public class MetricsFilterTest {
Protocol protocol = new DubboProtocol();
URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":20880/" + MetricsService.class.getName());
Invoker<MetricsService> invoker = protocol.refer(MetricsService.class, url);
invocation = new RpcInvocation("getMetricsByGroup", new Class<?>[]{String.class}, new Object[]{DUBBO_GROUP});
invocation = new RpcInvocation("getMetricsByGroup", DemoService.class.getName(), new Class<?>[]{String.class}, new Object[]{DUBBO_GROUP});
try {
Thread.sleep(5000);
} catch (Exception e) {
@ -253,8 +253,8 @@ public class MetricsFilterTest {
IMetricManager metricManager = MetricManager.getIMetricManager();
metricManager.clear();
MetricsFilter metricsFilter = new MetricsFilter();
Invocation sayNameInvocation = new RpcInvocation("sayName", new Class<?>[0], new Object[0]);
Invocation echoInvocation = new RpcInvocation("echo", new Class<?>[]{Integer.class}, new Integer[]{1});
Invocation sayNameInvocation = new RpcInvocation("sayName", DemoService.class.getName(), new Class<?>[0], new Object[0]);
Invocation echoInvocation = new RpcInvocation("echo", DemoService.class.getName(), new Class<?>[]{Integer.class}, new Integer[]{1});
RpcContext.getContext().setRemoteAddress(NetUtils.getLocalHost(), 20880).setLocalAddress(NetUtils.getLocalHost(), 2345);
RpcContext.getContext().setUrl(serviceInvoker.getUrl().addParameter(SIDE_KEY, PROVIDER_SIDE)
.addParameter(TIMEOUT_KEY, 300));
@ -279,7 +279,7 @@ public class MetricsFilterTest {
Protocol protocol = new DubboProtocol();
URL url = URL.valueOf("dubbo://" + NetUtils.getLocalAddress().getHostName() + ":20880/" + MetricsService.class.getName());
Invoker<MetricsService> invoker = protocol.refer(MetricsService.class, url);
Invocation invocation = new RpcInvocation("getMetricsByGroup", new Class<?>[]{String.class}, new Object[]{DUBBO_GROUP});
Invocation invocation = new RpcInvocation("getMetricsByGroup", DemoService.class.getName(), new Class<?>[]{String.class}, new Object[]{DUBBO_GROUP});
try {
Thread.sleep(15000);
} catch (Exception e) {

View File

@ -57,7 +57,7 @@ public class Ls implements BaseCommand {
//Content
for (ProviderModel providerModel : providerModelList) {
tTable.addRow(providerModel.getServiceName(), isRegistered(providerModel.getServiceName()) ? "Y" : "N");
tTable.addRow(providerModel.getServiceKey(), isRegistered(providerModel.getServiceKey()) ? "Y" : "N");
}
stringBuilder.append(tTable.rendering());
@ -80,7 +80,7 @@ public class Ls implements BaseCommand {
//Content
//TODO to calculate consumerAddressNum
for (ConsumerModel consumerModel : consumerModelList) {
tTable.addRow(consumerModel.getServiceName(), getConsumerAddressNum(consumerModel.getServiceName()));
tTable.addRow(consumerModel.getServiceKey(), getConsumerAddressNum(consumerModel.getServiceKey()));
}
stringBuilder.append(tTable.rendering());

View File

@ -51,9 +51,9 @@ public class Offline implements BaseCommand {
Collection<ProviderModel> providerModelList = ApplicationModel.allProviderModels();
for (ProviderModel providerModel : providerModelList) {
if (providerModel.getServiceName().matches(servicePattern)) {
if (providerModel.getServiceKey().matches(servicePattern)) {
hasService = true;
Set<ProviderInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getProviderInvoker(providerModel.getServiceName());
Set<ProviderInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getProviderInvoker(providerModel.getServiceKey());
for (ProviderInvokerWrapper providerInvokerWrapper : providerInvokerWrapperSet) {
if (!providerInvokerWrapper.isReg()) {
continue;

View File

@ -53,9 +53,9 @@ public class Online implements BaseCommand {
Collection<ProviderModel> providerModelList = ApplicationModel.allProviderModels();
for (ProviderModel providerModel : providerModelList) {
if (providerModel.getServiceName().matches(servicePattern)) {
if (providerModel.getServiceKey().matches(servicePattern)) {
hasService = true;
Set<ProviderInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getProviderInvoker(providerModel.getServiceName());
Set<ProviderInvokerWrapper> providerInvokerWrapperSet = ProviderConsumerRegTable.getProviderInvoker(providerModel.getServiceKey());
for (ProviderInvokerWrapper providerInvokerWrapper : providerInvokerWrapperSet) {
if (providerInvokerWrapper.isReg()) {
continue;

View File

@ -25,14 +25,15 @@ import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ConsumerModel;
import org.apache.dubbo.rpc.model.ProviderModel;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.Map;
import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getProviderInvoker;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -40,9 +41,9 @@ public class LsTest {
@Test
public void testExecute() throws Exception {
ConsumerModel consumerModel = mock(ConsumerModel.class);
when(consumerModel.getServiceName()).thenReturn("org.apache.dubbo.FooService");
when(consumerModel.getServiceKey()).thenReturn("org.apache.dubbo.FooService");
ProviderModel providerModel = mock(ProviderModel.class);
when(providerModel.getServiceName()).thenReturn("org.apache.dubbo.BarService");
when(providerModel.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
ApplicationModel.initConsumerModel("org.apache.dubbo.FooService", consumerModel);
ApplicationModel.initProviderModel("org.apache.dubbo.BarService", providerModel);

View File

@ -24,13 +24,14 @@ import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ProviderModel;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getProviderInvoker;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.core.Is.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -38,7 +39,7 @@ public class OfflineTest {
@Test
public void testExecute() throws Exception {
ProviderModel providerModel = mock(ProviderModel.class);
when(providerModel.getServiceName()).thenReturn("org.apache.dubbo.BarService");
when(providerModel.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
ApplicationModel.initProviderModel("org.apache.dubbo.BarService", providerModel);
Invoker providerInvoker = mock(Invoker.class);

View File

@ -24,11 +24,12 @@ import org.apache.dubbo.registry.support.ProviderInvokerWrapper;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ProviderModel;
import org.junit.jupiter.api.Test;
import static org.apache.dubbo.registry.support.ProviderConsumerRegTable.getProviderInvoker;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@ -37,7 +38,7 @@ public class OnlineTest {
@Test
public void testExecute() throws Exception {
ProviderModel providerModel = mock(ProviderModel.class);
when(providerModel.getServiceName()).thenReturn("org.apache.dubbo.BarService");
when(providerModel.getServiceKey()).thenReturn("org.apache.dubbo.BarService");
ApplicationModel.initProviderModel("org.apache.dubbo.BarService", providerModel);
Invoker providerInvoker = mock(Invoker.class);

View File

@ -18,7 +18,6 @@ package org.apache.dubbo.registry.integration;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@ -35,7 +34,6 @@ import org.apache.dubbo.remoting.Constants;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.Cluster;
import org.apache.dubbo.rpc.cluster.Configurator;
import org.apache.dubbo.rpc.cluster.Router;
@ -571,43 +569,44 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> implements Notify
@Override
public List<Invoker<T>> doList(Invocation invocation) {
if (forbidden) {
// 1. No service provider 2. Service providers are disabled
throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " +
getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " +
NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() +
", please check status of providers(disabled, not registered or in blacklist).");
}
if (multiGroup) {
return this.invokers == null ? Collections.emptyList() : this.invokers;
}
List<Invoker<T>> invokers = null;
try {
// Get invokers from cache, only runtime routers will be executed.
invokers = routerChain.route(getConsumerUrl(), invocation);
} catch (Throwable t) {
logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
}
// FIXME Is there any need of failing back to Constants.ANY_VALUE or the first available method invokers when invokers is null?
/*Map<String, List<Invoker<T>>> localMethodInvokerMap = this.methodInvokerMap; // local reference
if (localMethodInvokerMap != null && localMethodInvokerMap.size() > 0) {
String methodName = RpcUtils.getMethodName(invocation);
invokers = localMethodInvokerMap.get(methodName);
if (invokers == null) {
invokers = localMethodInvokerMap.get(Constants.ANY_VALUE);
}
if (invokers == null) {
Iterator<List<Invoker<T>>> iterator = localMethodInvokerMap.values().iterator();
if (iterator.hasNext()) {
invokers = iterator.next();
}
}
}*/
return invokers == null ? Collections.emptyList() : invokers;
// if (forbidden) {
// // 1. No service provider 2. Service providers are disabled
// throw new RpcException(RpcException.FORBIDDEN_EXCEPTION, "No provider available from registry " +
// getUrl().getAddress() + " for service " + getConsumerUrl().getServiceKey() + " on consumer " +
// NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() +
// ", please check status of providers(disabled, not registered or in blacklist).");
// }
//
// if (multiGroup) {
// return this.invokers == null ? Collections.emptyList() : this.invokers;
// }
//
// List<Invoker<T>> invokers = null;
// try {
// // Get invokers from cache, only runtime routers will be executed.
// invokers = routerChain.route(getConsumerUrl(), invocation);
// } catch (Throwable t) {
// logger.error("Failed to execute router: " + getUrl() + ", cause: " + t.getMessage(), t);
// }
//
//
// // FIXME Is there any need of failing back to Constants.ANY_VALUE or the first available method invokers when invokers is null?
// /*Map<String, List<Invoker<T>>> localMethodInvokerMap = this.methodInvokerMap; // local reference
// if (localMethodInvokerMap != null && localMethodInvokerMap.size() > 0) {
// String methodName = RpcUtils.getMethodName(invocation);
// invokers = localMethodInvokerMap.get(methodName);
// if (invokers == null) {
// invokers = localMethodInvokerMap.get(Constants.ANY_VALUE);
// }
// if (invokers == null) {
// Iterator<List<Invoker<T>>> iterator = localMethodInvokerMap.values().iterator();
// if (iterator.hasNext()) {
// invokers = iterator.next();
// }
// }
// }*/
// return invokers == null ? Collections.emptyList() : invokers;
return invokers;
}
@Override

View File

@ -34,6 +34,7 @@ import org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance;
import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance;
import org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory;
import org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker;
import org.apache.dubbo.rpc.service.GenericService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@ -49,27 +50,27 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
import static org.apache.dubbo.rpc.cluster.Constants.LOADBALANCE_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.MOCK_PROTOCOL;
import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.TYPE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.DISABLED_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
import static org.apache.dubbo.common.constants.RegistryConstants.PROVIDERS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.ROUTERS_CATEGORY;
import static org.apache.dubbo.common.constants.RegistryConstants.ROUTE_PROTOCOL;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.INVOCATION_NEED_MOCK;
import static org.apache.dubbo.rpc.cluster.Constants.LOADBALANCE_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.MOCK_PROTOCOL;
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.RULE_KEY;
import static org.apache.dubbo.rpc.cluster.Constants.TYPE_KEY;
import static org.junit.jupiter.api.Assertions.fail;
@SuppressWarnings({"rawtypes", "unchecked"})
@ -482,7 +483,7 @@ public class RegistryDirectoryTest {
registryDirectory.notify(serviceUrls);
// Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException;
invocation = new RpcInvocation($INVOKE, new Class[]{String.class, String[].class, Object[].class},
invocation = new RpcInvocation($INVOKE, GenericService.class.getName(), new Class[]{String.class, String[].class, Object[].class},
new Object[]{"getXXX1", "", new Object[]{}});
List<Invoker> invokers = registryDirectory.list(invocation);
@ -509,7 +510,7 @@ public class RegistryDirectoryTest {
registryDirectory.notify(serviceUrls);
invocation = new RpcInvocation($INVOKE,
invocation = new RpcInvocation($INVOKE, GenericService.class.getName(),
new Class[]{String.class, String[].class, Object[].class},
new Object[]{"getXXX1", new String[]{"Enum"}, new Object[]{Param.MORGAN}});

View File

@ -18,8 +18,6 @@
package org.apache.dubbo.remoting;
import java.util.concurrent.ExecutorService;
public interface Constants {
String BUFFER_KEY = "buffer";
@ -117,8 +115,6 @@ public interface Constants {
String CHANNEL_SEND_READONLYEVENT_KEY = "channel.readonly.send";
String EXECUTOR_SERVICE_COMPONENT_KEY = ExecutorService.class.getName();
String RECONNECT_KEY = "reconnect";
int DEFAULT_RECONNECT_PERIOD = 2000;

View File

@ -45,11 +45,11 @@ public abstract class AbstractTimerTask implements TimerTask {
}
static Long lastRead(Channel channel) {
return (Long) channel.getAttribute(HeaderExchangeHandler.KEY_READ_TIMESTAMP);
return (Long) channel.getAttribute(HeartbeatHandler.KEY_READ_TIMESTAMP);
}
static Long lastWrite(Channel channel) {
return (Long) channel.getAttribute(HeaderExchangeHandler.KEY_WRITE_TIMESTAMP);
return (Long) channel.getAttribute(HeartbeatHandler.KEY_WRITE_TIMESTAMP);
}
static Long now() {

View File

@ -76,6 +76,12 @@ final class HeaderExchangeChannel implements ExchangeChannel {
}
}
static void removeChannel(Channel ch) {
if (ch != null) {
ch.removeAttribute(CHANNEL_KEY);
}
}
@Override
public void send(Object message) throws RemotingException {
send(message, false);

View File

@ -44,10 +44,6 @@ public class HeaderExchangeHandler implements ChannelHandlerDelegate {
protected static final Logger logger = LoggerFactory.getLogger(HeaderExchangeHandler.class);
public static final String KEY_READ_TIMESTAMP = HeartbeatHandler.KEY_READ_TIMESTAMP;
public static final String KEY_WRITE_TIMESTAMP = HeartbeatHandler.KEY_WRITE_TIMESTAMP;
private final ExchangeHandler handler;
public HeaderExchangeHandler(ExchangeHandler handler) {
@ -112,8 +108,6 @@ public class HeaderExchangeHandler implements ChannelHandlerDelegate {
channel.send(res);
} catch (RemotingException e) {
logger.warn("Send result to consumer failed, channel is " + channel + ", msg is " + e);
} finally {
// HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
});
} catch (Throwable e) {
@ -125,26 +119,18 @@ public class HeaderExchangeHandler implements ChannelHandlerDelegate {
@Override
public void connected(Channel channel) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
handler.connected(exchangeChannel);
} finally {
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
handler.connected(exchangeChannel);
}
@Override
public void disconnected(Channel channel) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
handler.disconnected(exchangeChannel);
} finally {
DefaultFuture.closeChannel(channel);
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
HeaderExchangeChannel.removeChannel(channel);
}
}
@ -152,15 +138,11 @@ public class HeaderExchangeHandler implements ChannelHandlerDelegate {
public void sent(Channel channel, Object message) throws RemotingException {
Throwable exception = null;
try {
channel.setAttribute(KEY_WRITE_TIMESTAMP, System.currentTimeMillis());
ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
handler.sent(exchangeChannel, message);
} finally {
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
handler.sent(exchangeChannel, message);
} catch (Throwable t) {
exception = t;
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
}
if (message instanceof Request) {
Request request = (Request) message;
@ -180,38 +162,33 @@ public class HeaderExchangeHandler implements ChannelHandlerDelegate {
@Override
public void received(Channel channel, Object message) throws RemotingException {
channel.setAttribute(KEY_READ_TIMESTAMP, System.currentTimeMillis());
final ExchangeChannel exchangeChannel = HeaderExchangeChannel.getOrAddChannel(channel);
try {
if (message instanceof Request) {
// handle request.
Request request = (Request) message;
if (request.isEvent()) {
handlerEvent(channel, request);
} else {
if (request.isTwoWay()) {
handleRequest(exchangeChannel, request);
} else {
handler.received(exchangeChannel, request.getData());
}
}
} else if (message instanceof Response) {
handleResponse(channel, (Response) message);
} else if (message instanceof String) {
if (isClientSide(channel)) {
Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
logger.error(e.getMessage(), e);
} else {
String echo = handler.telnet(channel, (String) message);
if (echo != null && echo.length() > 0) {
channel.send(echo);
}
}
if (message instanceof Request) {
// handle request.
Request request = (Request) message;
if (request.isEvent()) {
handlerEvent(channel, request);
} else {
handler.received(exchangeChannel, message);
if (request.isTwoWay()) {
handleRequest(exchangeChannel, request);
} else {
handler.received(exchangeChannel, request.getData());
}
}
} finally {
HeaderExchangeChannel.removeChannelIfDisconnected(channel);
} else if (message instanceof Response) {
handleResponse(channel, (Response) message);
} else if (message instanceof String) {
if (isClientSide(channel)) {
Exception e = new Exception("Dubbo client can not supported string message: " + message + " in channel: " + channel + ", url: " + channel.getUrl());
logger.error(e.getMessage(), e);
} else {
String echo = handler.telnet(channel, (String) message);
if (echo != null && echo.length() > 0) {
channel.send(echo);
}
}
} else {
handler.received(exchangeChannel, message);
}
}

View File

@ -36,7 +36,6 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_CLIENT_THREADPOOL;
import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY;
@ -193,7 +192,7 @@ public abstract class AbstractClient extends AbstractEndpoint implements Client
} else {
if (logger.isInfoEnabled()) {
logger.info("Succeed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
logger.info("Successed connect to server " + getRemoteAddress() + " from " + getClass().getSimpleName() + " "
+ NetUtils.getLocalHost() + " using dubbo version " + Version.getVersion()
+ ", channel is " + this.getChannel());
}

View File

@ -35,11 +35,10 @@ import java.util.concurrent.ExecutorService;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY;
import static org.apache.dubbo.remoting.Constants.IDLE_TIMEOUT_KEY;
import static org.apache.dubbo.remoting.Constants.DEFAULT_IDLE_TIMEOUT;
import static org.apache.dubbo.remoting.Constants.ACCEPTS_KEY;
import static org.apache.dubbo.remoting.Constants.DEFAULT_ACCEPTS;
import static org.apache.dubbo.remoting.Constants.DEFAULT_IDLE_TIMEOUT;
import static org.apache.dubbo.remoting.Constants.IDLE_TIMEOUT_KEY;
/**
* AbstractServer

View File

@ -21,6 +21,7 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.timer.HashedWheelTimer;
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.exchange.Request;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -63,10 +64,8 @@ public class HeartBeatTaskTest {
long now = System.currentTimeMillis();
url = url.addParameter(DUBBO_VERSION_KEY, "2.1.1");
channel.setAttribute(
HeaderExchangeHandler.KEY_READ_TIMESTAMP, now);
channel.setAttribute(
HeaderExchangeHandler.KEY_WRITE_TIMESTAMP, now);
channel.setAttribute(HeartbeatHandler.KEY_READ_TIMESTAMP, now);
channel.setAttribute(HeartbeatHandler.KEY_WRITE_TIMESTAMP, now);
heartbeatTimer.newTimeout(heartbeatTimerTask, 250, TimeUnit.MILLISECONDS);

View File

@ -30,6 +30,7 @@ import java.net.InetSocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_TIMEOUT;
import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
@ -50,6 +51,9 @@ final class NettyChannel extends AbstractChannel {
private final Channel channel;
private final Map<String, Object> attributes = new ConcurrentHashMap<String, Object>();
private final AtomicBoolean active = new AtomicBoolean(false);
/**
* The constructor of NettyChannel.
* It is private so NettyChannel usually create by {@link NettyChannel#getOrAddChannel(Channel, URL, ChannelHandler)}
@ -82,6 +86,7 @@ final class NettyChannel extends AbstractChannel {
if (ret == null) {
NettyChannel nettyChannel = new NettyChannel(ch, url, handler);
if (ch.isActive()) {
nettyChannel.markActive(true);
ret = CHANNEL_MAP.putIfAbsent(ch, nettyChannel);
}
if (ret == null) {
@ -97,7 +102,19 @@ final class NettyChannel extends AbstractChannel {
*/
static void removeChannelIfDisconnected(Channel ch) {
if (ch != null && !ch.isActive()) {
CHANNEL_MAP.remove(ch);
NettyChannel nettyChannel = CHANNEL_MAP.remove(ch);
if (nettyChannel != null) {
nettyChannel.markActive(false);
}
}
}
static void removeChannel(Channel ch) {
if (ch != null) {
NettyChannel nettyChannel = CHANNEL_MAP.remove(ch);
if (nettyChannel != null) {
nettyChannel.markActive(false);
}
}
}
@ -113,7 +130,15 @@ final class NettyChannel extends AbstractChannel {
@Override
public boolean isConnected() {
return !isClosed() && channel.isActive();
return !isClosed() && active.get();
}
public boolean isActive() {
return active.get();
}
public void markActive(boolean isActive) {
active.set(isActive);
}
/**
@ -142,6 +167,7 @@ final class NettyChannel extends AbstractChannel {
throw cause;
}
} catch (Throwable e) {
removeChannelIfDisconnected(channel);
throw new RemotingException(this, "Failed to send message " + message + " to " + getRemoteAddress() + ", cause: " + e.getMessage(), e);
}
if (!success) {

View File

@ -40,10 +40,10 @@ import io.netty.handler.proxy.Socks5ProxyHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.concurrent.DefaultThreadFactory;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.net.InetSocketAddress;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
/**
* NettyClient.
*/
@ -192,7 +192,7 @@ public class NettyClient extends AbstractClient {
@Override
protected org.apache.dubbo.remoting.Channel getChannel() {
Channel c = channel;
if (c == null || !c.isActive()) {
if (c == null) {
return null;
}
return NettyChannel.getOrAddChannel(c, getUrl(), this);

View File

@ -55,11 +55,7 @@ public class NettyClientHandler extends ChannelDuplexHandler {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
handler.connected(channel);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
}
handler.connected(channel);
}
@Override
@ -68,18 +64,14 @@ public class NettyClientHandler extends ChannelDuplexHandler {
try {
handler.disconnected(channel);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
NettyChannel.removeChannel(ctx.channel());
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
handler.received(channel, msg);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
}
handler.received(channel, msg);
}
@Override
@ -92,21 +84,17 @@ public class NettyClientHandler extends ChannelDuplexHandler {
// If our out bound event has an error (in most cases the encoder fails),
// we need to have the request return directly instead of blocking the invoke process.
promise.addListener(future -> {
try {
if (future.isSuccess()) {
// if our future is success, mark the future to sent.
handler.sent(channel, msg);
return;
}
if (future.isSuccess()) {
// if our future is success, mark the future to sent.
handler.sent(channel, msg);
return;
}
Throwable t = future.cause();
if (t != null && isRequest) {
Request request = (Request) msg;
Response response = buildErrorResponse(request, t);
handler.received(channel, response);
}
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
Throwable t = future.cause();
if (t != null && isRequest) {
Request request = (Request) msg;
Response response = buildErrorResponse(request, t);
handler.received(channel, response);
}
});
}

View File

@ -66,11 +66,7 @@ final public class NettyCodecAdapter {
org.apache.dubbo.remoting.buffer.ChannelBuffer buffer = new NettyBackedChannelBuffer(out);
Channel ch = ctx.channel();
NettyChannel channel = NettyChannel.getOrAddChannel(ch, url, handler);
try {
codec.encode(channel, buffer, msg);
} finally {
NettyChannel.removeChannelIfDisconnected(ch);
}
codec.encode(channel, buffer, msg);
}
}
@ -83,27 +79,23 @@ final public class NettyCodecAdapter {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
// decode object.
do {
int saveReaderIndex = message.readerIndex();
Object msg = codec.decode(channel, message);
if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
message.readerIndex(saveReaderIndex);
break;
} else {
//is it possible to go here ?
if (saveReaderIndex == message.readerIndex()) {
throw new IOException("Decode without read data.");
}
if (msg != null) {
out.add(msg);
}
// decode object.
do {
int saveReaderIndex = message.readerIndex();
Object msg = codec.decode(channel, message);
if (msg == Codec2.DecodeResult.NEED_MORE_INPUT) {
message.readerIndex(saveReaderIndex);
break;
} else {
//is it possible to go here ?
if (saveReaderIndex == message.readerIndex()) {
throw new IOException("Decode without read data.");
}
} while (message.readable());
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
}
if (msg != null) {
out.add(msg);
}
}
} while (message.readable());
}
}
}

View File

@ -66,14 +66,10 @@ public class NettyServerHandler extends ChannelDuplexHandler {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
if (channel != null) {
channels.put(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()), channel);
}
handler.connected(channel);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
if (channel != null) {
channels.put(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()), channel);
}
handler.connected(channel);
}
@Override
@ -83,18 +79,14 @@ public class NettyServerHandler extends ChannelDuplexHandler {
channels.remove(NetUtils.toAddressString((InetSocketAddress) ctx.channel().remoteAddress()));
handler.disconnected(channel);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
NettyChannel.removeChannel(ctx.channel());
}
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
handler.received(channel, msg);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
}
handler.received(channel, msg);
}
@ -102,11 +94,7 @@ public class NettyServerHandler extends ChannelDuplexHandler {
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
super.write(ctx, msg, promise);
NettyChannel channel = NettyChannel.getOrAddChannel(ctx.channel(), url, handler);
try {
handler.sent(channel, msg);
} finally {
NettyChannel.removeChannelIfDisconnected(ctx.channel());
}
handler.sent(channel, msg);
}
@Override

View File

@ -16,10 +16,8 @@
*/
package org.apache.dubbo.rpc;
import java.util.concurrent.CompletableFuture;
/**
*
*/
public abstract class AbstractResult extends CompletableFuture<Result> implements Result {
public abstract class AbstractResult implements Result {
}

View File

@ -19,11 +19,11 @@ package org.apache.dubbo.rpc;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
/**
* {@link AsyncRpcResult} is introduced in 3.0.0 to replace RpcResult, and RpcResult is replaced with {@link AppResponse}:
@ -158,7 +158,22 @@ public class AppResponse extends AbstractResult implements Serializable {
}
@Override
public Result whenCompleteWithContext(BiConsumer<Result, Throwable> fn) {
public Result thenApplyWithContext(Function<AppResponse, AppResponse> fn) {
throw new UnsupportedOperationException("AppResponse represents an concrete business response, there will be no status changes, you should get internal values directly.");
}
@Override
public <U> CompletableFuture<U> thenApply(Function<Result, ? extends U> fn) {
throw new UnsupportedOperationException("AppResponse represents an concrete business response, there will be no status changes, you should get internal values directly.");
}
@Override
public Result get() throws InterruptedException, ExecutionException {
throw new UnsupportedOperationException("AppResponse represents an concrete business response, there will be no status changes, you should get internal values directly.");
}
@Override
public Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
throw new UnsupportedOperationException("AppResponse represents an concrete business response, there will be no status changes, you should get internal values directly.");
}

View File

@ -19,7 +19,6 @@ package org.apache.dubbo.rpc;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.ThreadlessExecutor;
import org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
@ -27,7 +26,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.BiConsumer;
import java.util.function.Function;
/**
* This class represents an unfinished RPC call, it will hold some context information for this call, for example RpcContext and Invocation,
@ -56,18 +55,15 @@ public class AsyncRpcResult extends AbstractResult {
private Invocation invocation;
public AsyncRpcResult(Invocation invocation) {
private CompletableFuture<AppResponse> responseFuture;
public AsyncRpcResult(CompletableFuture<AppResponse> future, Invocation invocation) {
this.responseFuture = future;
this.invocation = invocation;
this.storedContext = RpcContext.getContext();
this.storedServerContext = RpcContext.getServerContext();
}
public AsyncRpcResult(AsyncRpcResult asyncRpcResult) {
this.invocation = asyncRpcResult.getInvocation();
this.storedContext = asyncRpcResult.getStoredContext();
this.storedServerContext = asyncRpcResult.getStoredServerContext();
}
/**
* Notice the return type of {@link #getValue} is the actual type of the RPC method, not {@link AppResponse}
*
@ -91,12 +87,12 @@ public class AsyncRpcResult extends AbstractResult {
@Override
public void setValue(Object value) {
try {
if (this.isDone()) {
this.get().setValue(value);
if (responseFuture.isDone()) {
responseFuture.get().setValue(value);
} else {
AppResponse appResponse = new AppResponse();
appResponse.setValue(value);
this.complete(appResponse);
responseFuture.complete(appResponse);
}
} catch (Exception e) {
// This should never happen;
@ -112,12 +108,12 @@ public class AsyncRpcResult extends AbstractResult {
@Override
public void setException(Throwable t) {
try {
if (this.isDone()) {
this.get().setException(t);
if (responseFuture.isDone()) {
responseFuture.get().setException(t);
} else {
AppResponse appResponse = new AppResponse();
appResponse.setException(t);
this.complete(appResponse);
responseFuture.complete(appResponse);
}
} catch (Exception e) {
// This should never happen;
@ -130,10 +126,18 @@ public class AsyncRpcResult extends AbstractResult {
return getAppResponse().hasException();
}
public CompletableFuture<AppResponse> getResponseFuture() {
return responseFuture;
}
public void setResponseFuture(CompletableFuture<AppResponse> responseFuture) {
this.responseFuture = responseFuture;
}
public Result getAppResponse() {
try {
if (this.isDone()) {
return this.get();
if (responseFuture.isDone()) {
return responseFuture.get();
}
} catch (Exception e) {
// This should never happen;
@ -142,7 +146,6 @@ public class AsyncRpcResult extends AbstractResult {
return new AppResponse();
}
/**
* This method will always return after a maximum 'timeout' waiting:
* 1. if value returns before timeout, return normally.
@ -158,12 +161,12 @@ public class AsyncRpcResult extends AbstractResult {
ThreadlessExecutor threadlessExecutor = (ThreadlessExecutor) executor;
threadlessExecutor.waitAndDrain();
}
return super.get();
return responseFuture.get();
}
@Override
public Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return this.get();
return responseFuture.get(timeout, unit);
}
@Override
@ -178,27 +181,14 @@ public class AsyncRpcResult extends AbstractResult {
return getAppResponse().recreate();
}
@Override
public Result whenCompleteWithContext(BiConsumer<Result, Throwable> fn) {
CompletableFuture<Result> future = this.whenComplete((v, t) -> {
beforeContext.accept(v, t);
fn.accept(v, t);
afterContext.accept(v, t);
});
AsyncRpcResult nextStage = new AsyncRpcResult(this);
nextStage.subscribeTo(future);
return nextStage;
public Result thenApplyWithContext(Function<AppResponse, AppResponse> fn) {
this.responseFuture = responseFuture.thenApply(fn.compose(beforeContext).andThen(afterContext));
return this;
}
public void subscribeTo(CompletableFuture<?> future) {
future.whenComplete((obj, t) -> {
if (t != null) {
this.completeExceptionally(t);
} else {
this.complete((Result) obj);
}
});
@Override
public <U> CompletableFuture<U> thenApply(Function<Result,? extends U> fn) {
return this.responseFuture.thenApply(fn);
}
@Override
@ -231,18 +221,6 @@ public class AsyncRpcResult extends AbstractResult {
getAppResponse().setAttachment(key, value);
}
public RpcContext getStoredContext() {
return storedContext;
}
public RpcContext getStoredServerContext() {
return storedServerContext;
}
public Invocation getInvocation() {
return invocation;
}
public Executor getExecutor() {
return executor;
}
@ -257,25 +235,25 @@ public class AsyncRpcResult extends AbstractResult {
private RpcContext tmpContext;
private RpcContext tmpServerContext;
private BiConsumer<Result, Throwable> beforeContext = (appResponse, t) -> {
private Function<AppResponse, AppResponse> beforeContext = (appResponse) -> {
tmpContext = RpcContext.getContext();
tmpServerContext = RpcContext.getServerContext();
RpcContext.restoreContext(storedContext);
RpcContext.restoreServerContext(storedServerContext);
return appResponse;
};
private BiConsumer<Result, Throwable> afterContext = (appResponse, t) -> {
private Function<AppResponse, AppResponse> afterContext = (appResponse) -> {
RpcContext.restoreContext(tmpContext);
RpcContext.restoreServerContext(tmpServerContext);
return appResponse;
};
/**
* Some utility methods used to quickly generate default AsyncRpcResult instance.
*/
public static AsyncRpcResult newDefaultAsyncResult(AppResponse appResponse, Invocation invocation) {
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
asyncRpcResult.complete(appResponse);
return asyncRpcResult;
return new AsyncRpcResult(CompletableFuture.completedFuture(appResponse), invocation);
}
public static AsyncRpcResult newDefaultAsyncResult(Invocation invocation) {
@ -291,15 +269,15 @@ public class AsyncRpcResult extends AbstractResult {
}
public static AsyncRpcResult newDefaultAsyncResult(Object value, Throwable t, Invocation invocation) {
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
AppResponse appResponse = new AppResponse();
CompletableFuture<AppResponse> future = new CompletableFuture<>();
AppResponse result = new AppResponse();
if (t != null) {
appResponse.setException(t);
result.setException(t);
} else {
appResponse.setValue(value);
result.setValue(value);
}
asyncRpcResult.complete(appResponse);
return asyncRpcResult;
future.complete(result);
return new AsyncRpcResult(future, invocation);
}
}

View File

@ -103,8 +103,6 @@ public interface Constants {
* To decide whether to make connection when the client is created
*/
String LAZY_CONNECT_KEY = "lazy";
String $INVOKE = "$invoke";
String $INVOKE_ASYNC = "$invokeAsync";
String INPUT_KEY = "input";
String OUTPUT_KEY = "output";

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.protocol.dubbo;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.RpcException;
package org.apache.dubbo.rpc;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@ -53,6 +50,10 @@ public class FutureAdapter<V> extends CompletableFuture<V> {
// TODO figure out the meaning of cancel in DefaultFuture.
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
// Invocation invocation = invocationSoftReference.get();
// if (invocation != null) {
// invocation.getInvoker().invoke(cancel);
// }
return appResponseFuture.cancel(mayInterruptIfRunning);
}
@ -90,7 +91,4 @@ public class FutureAdapter<V> extends CompletableFuture<V> {
}
}
public CompletableFuture<AppResponse> getAppResponseFuture() {
return appResponseFuture;
}
}

View File

@ -35,6 +35,13 @@ public interface Invocation {
*/
String getMethodName();
/**
* get the interface name
* @return
*/
String getServiceName();
/**
* get parameter types.
*

View File

@ -20,8 +20,11 @@ import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.BiConsumer;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Function;
/**
@ -38,7 +41,7 @@ import java.util.function.BiConsumer;
* @see org.apache.dubbo.rpc.Invoker#invoke(Invocation)
* @see AppResponse
*/
public interface Result extends CompletionStage<Result>, Future<Result>, Serializable {
public interface Result extends Serializable {
/**
* Get invoke result.
@ -118,14 +121,6 @@ public interface Result extends CompletionStage<Result>, Future<Result>, Seriali
void setAttachment(String key, Object value);
/**
* Returns the specified {@code valueIfAbsent} when not complete, or
* returns the result value or throws an exception when complete.
*
* @see CompletableFuture#getNow(Object)
*/
Result getNow(Result valueIfAbsent);
/**
* Add a callback which can be triggered when the RPC call finishes.
* <p>
@ -135,9 +130,11 @@ public interface Result extends CompletionStage<Result>, Future<Result>, Seriali
* @param fn
* @return
*/
Result whenCompleteWithContext(BiConsumer<Result, Throwable> fn);
Result thenApplyWithContext(Function<AppResponse, AppResponse> fn);
default CompletableFuture<Result> completionFuture() {
return toCompletableFuture();
}
<U> CompletableFuture<U> thenApply(Function<Result, ? extends U> fn);
Result get() throws InterruptedException, ExecutionException;
Result get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

View File

@ -17,9 +17,12 @@
package org.apache.dubbo.rpc;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@ -42,8 +45,10 @@ public class RpcInvocation implements Invocation, Serializable {
private static final long serialVersionUID = -4355285085441097045L;
private String methodName;
private String serviceName;
private Class<?>[] parameterTypes;
private transient Class<?>[] parameterTypes;
private String parameterTypesDesc;
private Object[] arguments;
@ -55,13 +60,15 @@ public class RpcInvocation implements Invocation, Serializable {
private transient Class<?> returnType;
private transient Type[] returnTypes;
private transient InvokeMode invokeMode;
public RpcInvocation() {
}
public RpcInvocation(Invocation invocation, Invoker<?> invoker) {
this(invocation.getMethodName(), invocation.getParameterTypes(),
this(invocation.getMethodName(), invocation.getServiceName(), invocation.getParameterTypes(),
invocation.getArguments(), new HashMap<>(invocation.getAttachments()),
invocation.getInvoker());
if (invoker != null) {
@ -89,34 +96,43 @@ public class RpcInvocation implements Invocation, Serializable {
}
public RpcInvocation(Invocation invocation) {
this(invocation.getMethodName(), invocation.getParameterTypes(),
this(invocation.getMethodName(), invocation.getServiceName(), invocation.getParameterTypes(),
invocation.getArguments(), invocation.getAttachments(), invocation.getInvoker());
}
public RpcInvocation(Method method, Object[] arguments) {
this(method.getName(), method.getParameterTypes(), arguments, null, null);
public RpcInvocation(Method method, String serviceName, Object[] arguments) {
this(method, serviceName, arguments, null);
}
public RpcInvocation(Method method, Object[] arguments, Map<String, Object> attachment, Map<Object, Object> attributes) {
this(method.getName(), method.getParameterTypes(), arguments, attachment, null);
public RpcInvocation(Method method, String serviceName, Object[] arguments, Map<String, Object> attachment, Map<Object, Object> attributes) {
this(method.getName(), serviceName, method.getParameterTypes(), arguments, attachment, null);
this.returnType = method.getReturnType();
this.attributes = attributes == null ? new HashMap<>() : attributes;
}
public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments) {
this(methodName, parameterTypes, arguments, null, null);
public RpcInvocation(String methodName, String serviceName, Class<?>[] parameterTypes, Object[] arguments) {
this(methodName, serviceName, parameterTypes, arguments, null, null);
}
public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments, Map<String, Object> attachments) {
this(methodName, parameterTypes, arguments, attachments, null);
public RpcInvocation(String methodName, String serviceName, Class<?>[] parameterTypes, Object[] arguments, Map<String, Object> attachments) {
this(methodName, serviceName, parameterTypes, arguments, attachments, null);
}
public RpcInvocation(String methodName, Class<?>[] parameterTypes, Object[] arguments, Map<String, Object> attachments, Invoker<?> invoker) {
public RpcInvocation(String methodName, String serviceName, Class<?>[] parameterTypes, Object[] arguments, Map<String, Object> attachments, Invoker<?> invoker) {
this.methodName = methodName;
this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
this.arguments = arguments == null ? new Object[0] : arguments;
this.attachments = attachments == null ? new HashMap<String, Object>() : attachments;
this.invoker = invoker;
if (StringUtils.isNotEmpty(serviceName)) {
ApplicationModel.getServiceModel(serviceName).ifPresent(serviceModel ->
serviceModel.getMethod(methodName, parameterTypes)
.ifPresent(methodModel -> {
this.parameterTypesDesc = methodModel.getParamDesc();
this.returnTypes = methodModel.getReturnTypes();
})
);
}
}
@Override
@ -146,6 +162,15 @@ public class RpcInvocation implements Invocation, Serializable {
return methodName;
}
@Override
public String getServiceName() {
return serviceName;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public void setMethodName(String methodName) {
this.methodName = methodName;
}
@ -159,6 +184,14 @@ public class RpcInvocation implements Invocation, Serializable {
this.parameterTypes = parameterTypes == null ? new Class<?>[0] : parameterTypes;
}
public String getParameterTypesDesc() {
return parameterTypesDesc;
}
public void setParameterTypesDesc(String parameterTypesDesc) {
this.parameterTypesDesc = parameterTypesDesc;
}
@Override
public Object[] getArguments() {
return arguments;
@ -242,6 +275,14 @@ public class RpcInvocation implements Invocation, Serializable {
this.returnType = returnType;
}
public Type[] getReturnTypes() {
return returnTypes;
}
public void setReturnTypes(Type[] returnTypes) {
this.returnTypes = returnTypes;
}
public InvokeMode getInvokeMode() {
return invokeMode;
}

View File

@ -47,7 +47,7 @@ public class ConsumerContextFilter extends ListenableFilter {
RpcContext.getContext()
.setInvoker(invoker)
.setInvocation(invocation)
.setLocalAddress(NetUtils.getLocalHost(), 0)
.setLocalAddress(NetUtils.getHostAddress(), 0)
.setRemoteAddress(invoker.getUrl().getHost(),
invoker.getUrl().getPort());
if (invocation instanceof RpcInvocation) {

View File

@ -42,8 +42,8 @@ import org.apache.dubbo.rpc.support.ProtocolUtils;
import java.io.IOException;
import java.lang.reflect.Method;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.$INVOKE_ASYNC;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE_ASYNC;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_BEAN;
import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
@ -138,7 +138,7 @@ public class GenericFilter extends ListenableFilter {
args[0].getClass().getName());
}
}
return invoker.invoke(new RpcInvocation(method, args, inv.getAttachments(), inv.getAttributes()));
return invoker.invoke(new RpcInvocation(method, invoker.getInterface().getName(), args, inv.getAttachments(), inv.getAttributes()));
} catch (NoSuchMethodException e) {
throw new RpcException(e.getMessage(), e);
} catch (ClassNotFoundException e) {

View File

@ -40,8 +40,8 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.$INVOKE_ASYNC;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE_ASYNC;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
/**
@ -54,6 +54,8 @@ public class GenericImplFilter extends ListenableFilter {
private static final Class<?>[] GENERIC_PARAMETER_TYPES = new Class<?>[]{String.class, String[].class, Object[].class};
private static final String GENERIC_PARAMETER_DESC = "Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/Object;";
public GenericImplFilter() {
super.listener = new GenericImplListener();
}
@ -90,6 +92,7 @@ public class GenericImplFilter extends ListenableFilter {
invocation2.setMethodName($INVOKE);
}
invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
invocation2.setParameterTypesDesc(GENERIC_PARAMETER_DESC);
invocation2.setArguments(new Object[]{methodName, types, args});
return invoker.invoke(invocation2);
} else if ((invocation.getMethodName().equals($INVOKE) || invocation.getMethodName().equals($INVOKE_ASYNC))

View File

@ -21,6 +21,7 @@ import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -36,18 +37,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
* adjust project structure in order to fully utilize the methods introduced here.
*/
public class ApplicationModel {
protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
/**
* full qualified class name -> provided service
* serviceKey -> exported service
* each service may has different group, version, path, instance and so on, but they point to the same {@link ServiceModel}
*/
private static final ConcurrentMap<String, ProviderModel> PROVIDED_SERVICES = new ConcurrentHashMap<>();
/**
* full qualified class name -> subscribe service
* serviceKey -> referred service
* each service may has different group, version, path, instance and so on, but they point to the same {@link ServiceModel}
*/
private static final ConcurrentMap<String, ConsumerModel> CONSUMED_SERVICES = new ConcurrentHashMap<>();
/**
* The description of a unique service (interface definition in Dubbo)
*/
private static final ConcurrentHashMap<String, ServiceModel> SERVICES = new ConcurrentHashMap<>();
private static String application;
private static AtomicBoolean INIT_FLAG = new AtomicBoolean(false);
@ -60,12 +67,12 @@ public class ApplicationModel {
return PROVIDED_SERVICES.values();
}
public static ProviderModel getProviderModel(String serviceName) {
return PROVIDED_SERVICES.get(serviceName);
public static ProviderModel getProviderModel(String serviceKey) {
return PROVIDED_SERVICES.get(serviceKey);
}
public static ConsumerModel getConsumerModel(String serviceName) {
return CONSUMED_SERVICES.get(serviceName);
public static ConsumerModel getConsumerModel(String serviceKey) {
return CONSUMED_SERVICES.get(serviceKey);
}
public static void init() {
@ -90,6 +97,38 @@ public class ApplicationModel {
}
}
public static ServiceModel registerServiceModel(Class<?> interfaceClass) {
return SERVICES.computeIfAbsent(interfaceClass.getName(), (k) -> new ServiceModel(interfaceClass));
}
/**
* See {@link #registerServiceModel(Class)}
*
* we assume:
* 1. services with different interface are not allowed to have the same path.
* 2. services with the same interface but different group/version can share the same path.
* 3. path's default value is the name of the interface.
* @param path
* @param interfaceClass
* @return
*/
public static ServiceModel registerServiceModel(String path, Class<?> interfaceClass) {
ServiceModel serviceModel = registerServiceModel(interfaceClass);
// register path
if (!interfaceClass.getName().equals(path)) {
SERVICES.putIfAbsent(path, serviceModel);
}
return serviceModel;
}
public static Optional<ServiceModel> getServiceModel (String interfaceName) {
return Optional.ofNullable(SERVICES.get(interfaceName));
}
public static Optional<ServiceModel> getServiceModel (Class<?> interfaceClass) {
return Optional.ofNullable(SERVICES.get(interfaceClass.getName()));
}
public static String getApplication() {
return application;
}
@ -105,4 +144,5 @@ public class ApplicationModel {
PROVIDED_SERVICES.clear();
CONSUMED_SERVICES.clear();
}
}

View File

@ -1,161 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model;
import java.lang.reflect.Method;
import java.util.Map;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
public class ConsumerMethodModel {
private final Method method;
// private final boolean isCallBack;
// private final boolean isFuture;
private final String[] parameterTypes;
private final Class<?>[] parameterClasses;
private final Class<?> returnClass;
private final String methodName;
private final boolean generic;
private final AsyncMethodInfo asyncInfo;
public ConsumerMethodModel(Method method, Map<String, Object> attributes) {
this.method = method;
this.parameterClasses = method.getParameterTypes();
this.returnClass = method.getReturnType();
this.parameterTypes = this.createParamSignature(parameterClasses);
this.methodName = method.getName();
this.generic = methodName.equals($INVOKE) && parameterTypes != null && parameterTypes.length == 3;
if (attributes != null) {
asyncInfo = (AsyncMethodInfo) attributes.get(methodName);
} else {
asyncInfo = null;
}
}
public Method getMethod() {
return method;
}
public Class<?> getReturnClass() {
return returnClass;
}
public AsyncMethodInfo getAsyncInfo() {
return asyncInfo;
}
public String getMethodName() {
return methodName;
}
public String[] getParameterTypes() {
return parameterTypes;
}
private String[] createParamSignature(Class<?>[] args) {
if (args == null || args.length == 0) {
return new String[]{};
}
String[] paramSig = new String[args.length];
for (int x = 0; x < args.length; x++) {
paramSig[x] = args[x].getName();
}
return paramSig;
}
public boolean isGeneric() {
return generic;
}
public Class<?>[] getParameterClasses() {
return parameterClasses;
}
public static class AsyncMethodInfo {
// callback instance when async-call is invoked
private Object oninvokeInstance;
// callback method when async-call is invoked
private Method oninvokeMethod;
// callback instance when async-call is returned
private Object onreturnInstance;
// callback method when async-call is returned
private Method onreturnMethod;
// callback instance when async-call has exception thrown
private Object onthrowInstance;
// callback method when async-call has exception thrown
private Method onthrowMethod;
public Object getOninvokeInstance() {
return oninvokeInstance;
}
public void setOninvokeInstance(Object oninvokeInstance) {
this.oninvokeInstance = oninvokeInstance;
}
public Method getOninvokeMethod() {
return oninvokeMethod;
}
public void setOninvokeMethod(Method oninvokeMethod) {
this.oninvokeMethod = oninvokeMethod;
}
public Object getOnreturnInstance() {
return onreturnInstance;
}
public void setOnreturnInstance(Object onreturnInstance) {
this.onreturnInstance = onreturnInstance;
}
public Method getOnreturnMethod() {
return onreturnMethod;
}
public void setOnreturnMethod(Method onreturnMethod) {
this.onreturnMethod = onreturnMethod;
}
public Object getOnthrowInstance() {
return onthrowInstance;
}
public void setOnthrowInstance(Object onthrowInstance) {
this.onthrowInstance = onthrowInstance;
}
public Method getOnthrowMethod() {
return onthrowMethod;
}
public void setOnthrowMethod(Method onthrowMethod) {
this.onthrowMethod = onthrowMethod;
}
}
}

View File

@ -16,83 +16,59 @@
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.common.utils.CollectionUtils;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* Consumer Model which is about subscribed services.
* This model is bind to your reference's configuration, for example, group, version or method level configuration.
*/
public class ConsumerModel {
private final ServiceMetadata serviceMetadata;
private final Map<Method, ConsumerMethodModel> methodModels = new IdentityHashMap<Method, ConsumerMethodModel>();
private final String serviceKey;
private final Object proxyObject;
private final ServiceModel serviceModel;
private final Map<String, AsyncMethodInfo> methodConfigs = new HashMap<>();
/**
* This constructor create an instance of ConsumerModel and passed objects should not be null.
* If service name, service instance, proxy object,methods should not be null. If these are null
* then this constructor will throw {@link IllegalArgumentException}
*
* This constructor create an instance of ConsumerModel and passed objects should not be null.
* If service name, service instance, proxy object,methods should not be null. If these are null
* then this constructor will throw {@link IllegalArgumentException}
* @param serviceKey Name of the service.
* @param serviceInterfaceClass Service interface class.
* @param proxyObject Proxy object.
* @param attributes Attributes of methods.
* @param metadata
*/
public ConsumerModel(Map<String, Object> attributes, ServiceMetadata metadata) {
this.serviceMetadata = metadata;
for (Method method : metadata.getServiceType().getMethods()) {
methodModels.put(method, new ConsumerMethodModel(method, attributes));
public ConsumerModel(String serviceKey
, Class<?> serviceInterfaceClass
, Object proxyObject
, ServiceModel serviceModel
, Map<String, Object> attributes) {
Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
Assert.notNull(serviceInterfaceClass, "Service interface class can't null");
Assert.notNull(proxyObject, "Proxy object can't be null");
this.serviceKey = serviceKey;
this.proxyObject = proxyObject;
this.serviceModel = serviceModel;
if (CollectionUtils.isNotEmptyMap(attributes)) {
attributes.forEach((method, object) -> {
methodConfigs.put(method, (AsyncMethodInfo) object);
});
}
}
/**
* @return serviceMetadata
*/
public ServiceMetadata getServiceMetadata() {
return serviceMetadata;
}
/**
* Return method model for the given method on consumer side
*
* @param method method object
* @return method model
*/
public ConsumerMethodModel getMethodModel(Method method) {
return methodModels.get(method);
}
/**
* Return method model for the given method on consumer side
*
* @param method method object
* @return method model
*/
public ConsumerMethodModel getMethodModel(String method) {
Optional<Map.Entry<Method, ConsumerMethodModel>> consumerMethodModelEntry = methodModels.entrySet().stream().filter(entry -> entry.getKey().getName().equals(method)).findFirst();
return consumerMethodModelEntry.map(Map.Entry::getValue).orElse(null);
}
/**
* @param method metodName
* @param argsType method arguments type
* Return the proxy object used by called while creating instance of ConsumerModel
* @return
*/
public ConsumerMethodModel getMethodModel(String method, String[] argsType) {
Optional<ConsumerMethodModel> consumerMethodModel = methodModels.entrySet().stream()
.filter(entry -> entry.getKey().getName().equals(method))
.map(Map.Entry::getValue).filter(methodModel -> Arrays.equals(argsType, methodModel.getParameterTypes()))
.findFirst();
return consumerMethodModel.orElse(null);
}
/**
* @return
*/
public Class<?> getServiceInterfaceClass() {
return serviceMetadata.getServiceType();
public Object getProxyObject() {
return proxyObject;
}
/**
@ -100,20 +76,91 @@ public class ConsumerModel {
*
* @return method model list
*/
public List<ConsumerMethodModel> getAllMethods() {
return new ArrayList<ConsumerMethodModel>(methodModels.values());
public Set<MethodModel> getAllMethods() {
return serviceModel.getAllMethods();
}
/**
* Return the proxy object used by called while creating instance of ConsumerModel
*
* @return
*/
public Object getProxyObject() {
return this.serviceMetadata.getTarget();
public Class<?> getServiceInterfaceClass() {
return serviceModel.getServiceInterfaceClass();
}
public String getServiceName() {
return this.serviceMetadata.getServiceKey();
public String getServiceKey() {
return serviceKey;
}
public AsyncMethodInfo getMethodConfig(String methodName) {
return methodConfigs.get(methodName);
}
public ServiceModel getServiceModel() {
return serviceModel;
}
public static class AsyncMethodInfo {
// callback instance when async-call is invoked
private Object oninvokeInstance;
// callback method when async-call is invoked
private Method oninvokeMethod;
// callback instance when async-call is returned
private Object onreturnInstance;
// callback method when async-call is returned
private Method onreturnMethod;
// callback instance when async-call has exception thrown
private Object onthrowInstance;
// callback method when async-call has exception thrown
private Method onthrowMethod;
public Object getOninvokeInstance() {
return oninvokeInstance;
}
public void setOninvokeInstance(Object oninvokeInstance) {
this.oninvokeInstance = oninvokeInstance;
}
public Method getOninvokeMethod() {
return oninvokeMethod;
}
public void setOninvokeMethod(Method oninvokeMethod) {
this.oninvokeMethod = oninvokeMethod;
}
public Object getOnreturnInstance() {
return onreturnInstance;
}
public void setOnreturnInstance(Object onreturnInstance) {
this.onreturnInstance = onreturnInstance;
}
public Method getOnreturnMethod() {
return onreturnMethod;
}
public void setOnreturnMethod(Method onreturnMethod) {
this.onreturnMethod = onreturnMethod;
}
public Object getOnthrowInstance() {
return onthrowInstance;
}
public void setOnthrowInstance(Object onthrowInstance) {
this.onthrowInstance = onthrowInstance;
}
public Method getOnthrowMethod() {
return onthrowMethod;
}
public void setOnthrowMethod(Method onthrowMethod) {
this.onthrowMethod = onthrowMethod;
}
}
}

View File

@ -16,61 +16,68 @@
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.utils.ReflectUtils;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class ProviderMethodModel {
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE_ASYNC;
/**
*
*/
public class MethodModel {
private final Method method;
private final String methodName;
// private final boolean isCallBack;
// private final boolean isFuture;
private final String paramDesc;
private final Class<?>[] parameterClasses;
private final String[] methodArgTypes;
private final Type[] genericParameterTypes;
private final ConcurrentMap<String, Object> attributeMap = new ConcurrentHashMap<>();
private final Class<?> returnClass;
private final Type[] returnTypes;
private final String methodName;
private final boolean generic;
public ProviderMethodModel(Method method) {
public MethodModel (Method method) {
this.method = method;
this.methodName = method.getName();
this.parameterClasses = method.getParameterTypes();
this.methodArgTypes = getArgTypes(method);
this.genericParameterTypes = method.getGenericParameterTypes();
this.returnClass = method.getReturnType();
this.returnTypes = ReflectUtils.getReturnTypes(method);
this.paramDesc = ReflectUtils.getDesc(method);
this.methodName = method.getName();
this.generic = (methodName.equals($INVOKE) || methodName.equals($INVOKE_ASYNC)) && parameterClasses.length == 3;
}
public boolean matchParams (String params) {
return paramDesc.equalsIgnoreCase(params);
}
public Method getMethod() {
return method;
}
public String getMethodName() {
return methodName;
}
public String[] getMethodArgTypes() {
return methodArgTypes;
}
public ConcurrentMap<String, Object> getAttributeMap() {
return attributeMap;
}
private static String[] getArgTypes(Method method) {
String[] methodArgTypes = new String[0];
Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length > 0) {
methodArgTypes = new String[parameterTypes.length];
int index = 0;
for (Class<?> paramType : parameterTypes) {
methodArgTypes[index++] = paramType.getName();
}
}
return methodArgTypes;
public String getParamDesc() {
return paramDesc;
}
public Class<?>[] getParameterClasses() {
return parameterClasses;
}
public Type[] getGenericParameterTypes() {
return genericParameterTypes;
public Class<?> getReturnClass() {
return returnClass;
}
public Type[] getReturnTypes() {
return returnTypes;
}
public String getMethodName() {
return methodName;
}
public boolean isGeneric() {
return generic;
}
}

View File

@ -16,99 +16,43 @@
*/
package org.apache.dubbo.rpc.model;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* ProviderModel which is about published services
*/
public class ProviderModel {
private final String serviceKey;
private final Object serviceInstance;
private final ServiceMetadata serviceMetadata;
private final String serivceKey;
private final Map<String, List<ProviderMethodModel>> methods = new HashMap<String, List<ProviderMethodModel>>();
private final ServiceModel serviceModel;
public ProviderModel(String serviceName, String group, String version, Object serviceInstance, Class<?> serviceInterfaceClass) {
public ProviderModel(String serviceKey, Object serviceInstance, ServiceModel serviceModel) {
if (null == serviceInstance) {
throw new IllegalArgumentException("Service[" + serviceName + "]Target is NULL.");
throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
}
this.serviceKey = serviceKey;
this.serviceInstance = serviceInstance;
this.serviceMetadata = new ServiceMetadata(serviceName, group, version, serviceInterfaceClass);
this.serivceKey = serviceMetadata.getServiceKey();
initMethod(serviceInterfaceClass);
this.serviceModel = serviceModel;
}
public ProviderModel(Object serviceInstance, ServiceMetadata serviceMetadata) {
this.serviceInstance = serviceInstance;
this.serviceMetadata = serviceMetadata;
this.serivceKey = serviceMetadata.getServiceKey();
initMethod(serviceMetadata.getServiceType());
}
public String getServiceName() {
return this.serviceMetadata.getServiceKey();
public String getServiceKey() {
return serviceKey;
}
public Class<?> getServiceInterfaceClass() {
return this.serviceMetadata.getServiceType();
return serviceModel.getServiceInterfaceClass();
}
public Object getServiceInstance() {
return serviceInstance;
}
public List<ProviderMethodModel> getAllMethods() {
List<ProviderMethodModel> result = new ArrayList<ProviderMethodModel>();
for (List<ProviderMethodModel> models : methods.values()) {
result.addAll(models);
}
return result;
public Set<MethodModel> getAllMethods() {
return serviceModel.getAllMethods();
}
public ProviderMethodModel getMethodModel(String methodName, String[] argTypes) {
List<ProviderMethodModel> methodModels = methods.get(methodName);
if (methodModels != null) {
for (ProviderMethodModel methodModel : methodModels) {
if (Arrays.equals(argTypes, methodModel.getMethodArgTypes())) {
return methodModel;
}
}
}
return null;
}
public List<ProviderMethodModel> getMethodModelList(String methodName) {
List<ProviderMethodModel> resultList = methods.get(methodName);
return resultList == null ? Collections.emptyList() : resultList;
}
private void initMethod(Class<?> serviceInterfaceClass) {
Method[] methodsToExport;
methodsToExport = serviceInterfaceClass.getMethods();
for (Method method : methodsToExport) {
method.setAccessible(true);
List<ProviderMethodModel> methodModels = methods.get(method.getName());
if (methodModels == null) {
methodModels = new ArrayList<ProviderMethodModel>();
methods.put(method.getName(), methodModels);
}
methodModels.add(new ProviderMethodModel(method));
}
}
/**
* @return serviceMetadata
*/
public ServiceMetadata getServiceMetadata() {
return serviceMetadata;
public ServiceModel getServiceModel() {
return serviceModel;
}
}

View File

@ -0,0 +1,100 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.utils.CollectionUtils;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class ServiceModel {
private final String serviceName;
private final Class<?> serviceInterfaceClass;
// to accelarate search
private final Map<String, Set<MethodModel>> methods = new HashMap<>();
private final Map<String, Map<String, MethodModel>> descToMethods = new HashMap<>();
public ServiceModel (Class<?> interfaceClass) {
this.serviceInterfaceClass = interfaceClass;
this.serviceName = interfaceClass.getName();
initMethods();
}
private void initMethods() {
Method[] methodsToExport = null;
methodsToExport = this.serviceInterfaceClass.getMethods();
for (Method method : methodsToExport) {
method.setAccessible(true);
Set<MethodModel> methodModels = methods.computeIfAbsent(method.getName(), (k) ->new HashSet<>(1));
methodModels.add(new MethodModel(method));
}
methods.forEach((methodName, methodList) -> {
Map<String, MethodModel> descMap = descToMethods.computeIfAbsent(methodName, k -> new HashMap<>());
methodList.forEach(methodModel -> descMap.put(methodModel.getParamDesc(), methodModel));
// Map<Class<?>[], MethodModel> typesMap = typeToMethods.computeIfAbsent(methodName, k -> new HashMap<>());
// methodList.forEach(methodModel -> typesMap.put(methodModel.getParameterClasses(), methodModel));
});
}
public String getServiceName() {
return serviceName;
}
public Class<?> getServiceInterfaceClass() {
return serviceInterfaceClass;
}
public Set<MethodModel> getAllMethods () {
Set<MethodModel> methodModels = new HashSet<>();
methods.forEach((k, v) -> methodModels.addAll(v));
return methodModels;
}
public Optional<MethodModel> getMethod (String methodName, String params) {
Map<String, MethodModel> methods = descToMethods.get(methodName);
if (CollectionUtils.isNotEmptyMap(methods)) {
return Optional.ofNullable(methods.get(params));
}
return Optional.empty();
}
public Optional<MethodModel> getMethod (String methodName, Class<?>[] paramTypes) {
Set<MethodModel> methodModels = methods.get(methodName);
if (CollectionUtils.isNotEmpty(methodModels)) {
for (MethodModel methodModel : methodModels) {
if (Arrays.equals(paramTypes, methodModel.getParameterClasses())) {
return Optional.of(methodModel);
}
}
}
return Optional.empty();
}
public Set<MethodModel> getMethods (String methodName) {
return methods.get(methodName);
}
}

View File

@ -27,6 +27,7 @@ import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.rpc.AsyncRpcResult;
import org.apache.dubbo.rpc.FutureAdapter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.InvokeMode;
import org.apache.dubbo.rpc.Invoker;
@ -34,7 +35,6 @@ import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.protocol.dubbo.FutureAdapter;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.lang.reflect.InvocationTargetException;
@ -55,21 +55,21 @@ public abstract class AbstractInvoker<T> implements Invoker<T> {
private final URL url;
private final Map<String, Object> attachment;
private final Map<String, String> attachment;
private volatile boolean available = true;
private AtomicBoolean destroyed = new AtomicBoolean(false);
public AbstractInvoker(Class<T> type, URL url) {
this(type, url, (Map<String, Object>) null);
this(type, url, (Map<String, String>) null);
}
public AbstractInvoker(Class<T> type, URL url, String[] keys) {
this(type, url, convertAttachment(url, keys));
}
public AbstractInvoker(Class<T> type, URL url, Map<String, Object> attachment) {
public AbstractInvoker(Class<T> type, URL url, Map<String, String> attachment) {
if (type == null) {
throw new IllegalArgumentException("service type == null");
}
@ -81,11 +81,11 @@ public abstract class AbstractInvoker<T> implements Invoker<T> {
this.attachment = attachment == null ? null : Collections.unmodifiableMap(attachment);
}
private static Map<String, Object> convertAttachment(URL url, String[] keys) {
private static Map<String, String> convertAttachment(URL url, String[] keys) {
if (ArrayUtils.isEmpty(keys)) {
return null;
}
Map<String, Object> attachment = new HashMap<String, Object>();
Map<String, String> attachment = new HashMap<String, String>();
for (String key : keys) {
String value = url.getParameter(key);
if (value != null && value.length() > 0) {
@ -143,11 +143,11 @@ public abstract class AbstractInvoker<T> implements Invoker<T> {
if (CollectionUtils.isNotEmptyMap(attachment)) {
invocation.addAttachmentsIfAbsent(attachment);
}
Map<String, Object> contextAttachments = RpcContext.getContext().getAttachments();
Map<String, String> contextAttachments = RpcContext.getContext().getAttachments();
if (CollectionUtils.isNotEmptyMap(contextAttachments)) {
/**
* invocation.addAttachmentsIfAbsent(context){@link RpcInvocation#addAttachmentsIfAbsent(Map)}should not be used here,
* because the {@link RpcContext#setAttachment(String, Object)} is passed in the Filter when the call is triggered
* because the {@link RpcContext#setAttachment(String, String)} is passed in the Filter when the call is triggered
* by the built-in retry mechanism of the Dubbo. The attachment to update RpcContext will no longer work, which is
* a mistake in most cases (for example, through Filter to RpcContext output traceId and spanId and other information).
*/
@ -179,12 +179,12 @@ public abstract class AbstractInvoker<T> implements Invoker<T> {
} catch (Throwable e) {
asyncResult = AsyncRpcResult.newDefaultAsyncResult(null, e, invocation);
}
RpcContext.getContext().setFuture(new FutureAdapter(asyncResult));
RpcContext.getContext().setFuture(new FutureAdapter(asyncResult.getResponseFuture()));
return asyncResult;
}
protected ExecutorService getCallbackExecutor(URL url, Invocation inv) {
ExecutorService sharedExecutor = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension().createExecutorIfAbsent(url);
ExecutorService sharedExecutor = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension().getExecutor(url);
if (InvokeMode.SYNC == RpcUtils.getInvokeMode(getUrl(), inv)) {
return new ThreadlessExecutor(sharedExecutor);
} else {

View File

@ -83,8 +83,7 @@ public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
try {
Object value = doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments());
CompletableFuture<Object> future = wrapWithFuture(value, invocation);
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(invocation);
future.whenComplete((obj, t) -> {
CompletableFuture<AppResponse> appResponseFuture = future.handle((obj, t) -> {
AppResponse result = new AppResponse();
if (t != null) {
if (t instanceof CompletionException) {
@ -95,9 +94,9 @@ public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
} else {
result.setValue(obj);
}
asyncRpcResult.complete(result);
return result;
});
return asyncRpcResult;
return new AsyncRpcResult(appResponseFuture, invocation);
} catch (InvocationTargetException e) {
if (RpcContext.getContext().isAsyncStarted() && !RpcContext.getContext().stopAsync()) {
logger.error("Provider async started, but got an exception from the original method, cannot write the exception back to consumer because an async result may have returned the new thread.", e);

View File

@ -38,20 +38,20 @@ public class InvokerInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
Class<?>[] parameterTypes = method.getParameterTypes();
if (method.getDeclaringClass() == Object.class) {
return method.invoke(invoker, args);
}
if ("toString".equals(methodName) && parameterTypes.length == 0) {
return invoker.toString();
}
if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
return invoker.hashCode();
}
if ("equals".equals(methodName) && parameterTypes.length == 1) {
return invoker.equals(args[0]);
}
// Class<?>[] parameterTypes = method.getParameterTypes();
// if (method.getDeclaringClass() == Object.class) {
// return method.invoke(invoker, args);
// }
// if ("toString".equals(methodName) && parameterTypes.length == 0) {
// return invoker.toString();
// }
// if ("hashCode".equals(methodName) && parameterTypes.length == 0) {
// return invoker.hashCode();
// }
// if ("equals".equals(methodName) && parameterTypes.length == 1) {
// return invoker.equals(args[0]);
// }
return invoker.invoke(new RpcInvocation(method, args)).recreate();
return invoker.invoke(new RpcInvocation(method, invoker.getInterface().getName(), args)).recreate();
}
}

View File

@ -39,12 +39,12 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
import static org.apache.dubbo.rpc.Constants.RETURN_PREFIX;
import static org.apache.dubbo.rpc.Constants.THROW_PREFIX;
import static org.apache.dubbo.rpc.Constants.FAIL_PREFIX;
import static org.apache.dubbo.rpc.Constants.FORCE_PREFIX;
import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
import static org.apache.dubbo.rpc.Constants.RETURN_KEY;
import static org.apache.dubbo.rpc.Constants.RETURN_PREFIX;
import static org.apache.dubbo.rpc.Constants.THROW_PREFIX;
final public class MockInvoker<T> implements Invoker<T> {
private final static ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
@ -95,10 +95,13 @@ final public class MockInvoker<T> implements Invoker<T> {
@Override
public Result invoke(Invocation invocation) throws RpcException {
String mock = getUrl().getParameter(invocation.getMethodName() + "." + MOCK_KEY);
if (invocation instanceof RpcInvocation) {
((RpcInvocation) invocation).setInvoker(this);
}
String mock = null;
if (getUrl().hasMethodParameter(invocation.getMethodName())) {
mock = getUrl().getParameter(invocation.getMethodName() + "." + MOCK_KEY);
}
if (StringUtils.isBlank(mock)) {
mock = getUrl().getParameter(MOCK_KEY);
}

View File

@ -30,8 +30,8 @@ import java.lang.reflect.Type;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicLong;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.$INVOKE_ASYNC;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE_ASYNC;
import static org.apache.dubbo.rpc.Constants.ASYNC_KEY;
import static org.apache.dubbo.rpc.Constants.AUTO_ATTACH_INVOCATIONID_KEY;
import static org.apache.dubbo.rpc.Constants.ID_KEY;
@ -168,7 +168,12 @@ public class RpcUtils {
}
public static boolean isReturnTypeFuture(Invocation inv) {
Class<?> clazz = getReturnType(inv);
Class<?> clazz;
if (inv instanceof RpcInvocation) {
clazz = ((RpcInvocation) inv).getReturnType();
} else {
clazz = getReturnType(inv);
}
return (clazz != null && CompletableFuture.class.isAssignableFrom(clazz)) || isGenericAsync(inv);
}

View File

@ -28,7 +28,6 @@ import org.apache.dubbo.rpc.support.DemoService;
import org.apache.dubbo.rpc.support.LocalException;
import com.alibaba.com.caucho.hessian.HessianException;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@ -52,7 +51,7 @@ public class ExceptionFilterTest {
RpcException exception = new RpcException("TestRpcException");
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class<?>[]{String.class}, new Object[]{"world"});
RpcInvocation invocation = new RpcInvocation("sayHello", DemoService.class.getName(), new Class<?>[]{String.class}, new Object[]{"world"});
Invoker<DemoService> invoker = mock(Invoker.class);
given(invoker.getInterface()).willReturn(DemoService.class);
given(invoker.invoke(eq(invocation))).willThrow(exception);
@ -76,7 +75,7 @@ public class ExceptionFilterTest {
public void testJavaException() {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class<?>[]{String.class}, new Object[]{"world"});
RpcInvocation invocation = new RpcInvocation("sayHello", DemoService.class.getName(), new Class<?>[]{String.class}, new Object[]{"world"});
AppResponse appResponse = new AppResponse();
appResponse.setException(new IllegalArgumentException("java"));
@ -96,7 +95,7 @@ public class ExceptionFilterTest {
public void testRuntimeException() {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class<?>[]{String.class}, new Object[]{"world"});
RpcInvocation invocation = new RpcInvocation("sayHello", DemoService.class.getName(), new Class<?>[]{String.class}, new Object[]{"world"});
AppResponse appResponse = new AppResponse();
appResponse.setException(new LocalException("localException"));
@ -116,7 +115,7 @@ public class ExceptionFilterTest {
public void testConvertToRunTimeException() throws Exception {
ExceptionFilter exceptionFilter = new ExceptionFilter();
RpcInvocation invocation = new RpcInvocation("sayHello", new Class<?>[]{String.class}, new Object[]{"world"});
RpcInvocation invocation = new RpcInvocation("sayHello", DemoService.class.getName(), new Class<?>[]{String.class}, new Object[]{"world"});
AppResponse mockRpcResult = new AppResponse();
mockRpcResult.setException(new HessianException("hessian"));

View File

@ -36,11 +36,11 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
public class GenericFilterTest {
GenericFilter genericFilter = new GenericFilter();
@ -54,7 +54,7 @@ public class GenericFilterTest {
person.put("name", "dubbo");
person.put("age", 10);
RpcInvocation invocation = new RpcInvocation($INVOKE, genericInvoke.getParameterTypes(),
RpcInvocation invocation = new RpcInvocation($INVOKE, GenericService.class.getName(), genericInvoke.getParameterTypes(),
new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}, new Object[]{person}});
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
@ -82,7 +82,7 @@ public class GenericFilterTest {
person.put("name", "dubbo");
person.put("age", 10);
RpcInvocation invocation = new RpcInvocation($INVOKE, genericInvoke.getParameterTypes(),
RpcInvocation invocation = new RpcInvocation($INVOKE, GenericService.class.getName(), genericInvoke.getParameterTypes(),
new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}, new Object[]{person}});
invocation.setAttachment(GENERIC_KEY, GENERIC_SERIALIZATION_NATIVE_JAVA);
@ -106,7 +106,7 @@ public class GenericFilterTest {
person.put("name", "dubbo");
person.put("age", 10);
RpcInvocation invocation = new RpcInvocation("sayHi", genericInvoke.getParameterTypes()
RpcInvocation invocation = new RpcInvocation("sayHi", GenericService.class.getName(), genericInvoke.getParameterTypes()
, new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}, new Object[]{person}});
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
@ -130,7 +130,7 @@ public class GenericFilterTest {
person.put("name", "dubbo");
person.put("age", 10);
RpcInvocation invocation = new RpcInvocation($INVOKE, genericInvoke.getParameterTypes()
RpcInvocation invocation = new RpcInvocation($INVOKE, GenericService.class.getName(), genericInvoke.getParameterTypes()
, new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}});
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +

View File

@ -36,12 +36,11 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.when;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
public class GenericImplFilterTest {
private GenericImplFilter genericImplFilter = new GenericImplFilter();
@ -49,7 +48,7 @@ public class GenericImplFilterTest {
@Test
public void testInvoke() throws Exception {
RpcInvocation invocation = new RpcInvocation("getPerson",
RpcInvocation invocation = new RpcInvocation("getPerson", "org.apache.dubbo.rpc.support.DemoService",
new Class[]{Person.class}, new Object[]{new Person("dubbo", 10)});
@ -77,7 +76,7 @@ public class GenericImplFilterTest {
@Test
public void testInvokeWithException() throws Exception {
RpcInvocation invocation = new RpcInvocation("getPerson",
RpcInvocation invocation = new RpcInvocation("getPerson", "org.apache.dubbo.rpc.support.DemoService",
new Class[]{Person.class}, new Object[]{new Person("dubbo", 10)});
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +
@ -105,7 +104,7 @@ public class GenericImplFilterTest {
person.put("name", "dubbo");
person.put("age", 10);
RpcInvocation invocation = new RpcInvocation($INVOKE, genericInvoke.getParameterTypes(),
RpcInvocation invocation = new RpcInvocation($INVOKE, GenericService.class.getName(), genericInvoke.getParameterTypes(),
new Object[]{"getPerson", new String[]{Person.class.getCanonicalName()}, new Object[]{person}});
URL url = URL.valueOf("test://test:11/org.apache.dubbo.rpc.support.DemoService?" +

View File

@ -51,7 +51,7 @@ public abstract class AbstractProxyTest {
//Assertions.assertEquals(proxy.toString(), invoker.toString());
//Assertions.assertEquals(proxy.hashCode(), invoker.hashCode());
Assertions.assertEquals(invoker.invoke(new RpcInvocation("echo", new Class[]{String.class}, new Object[]{"aa"})).getValue()
Assertions.assertEquals(invoker.invoke(new RpcInvocation("echo", DemoService.class.getName(), new Class[]{String.class}, new Object[]{"aa"})).getValue()
, proxy.echo("aa"));
}
@ -65,7 +65,7 @@ public abstract class AbstractProxyTest {
Assertions.assertEquals(invoker.getInterface(), DemoService.class);
Assertions.assertEquals(invoker.invoke(new RpcInvocation("echo", new Class[]{String.class}, new Object[]{"aa"})).getValue(),
Assertions.assertEquals(invoker.invoke(new RpcInvocation("echo", DemoService.class.getName(), new Class[]{String.class}, new Object[]{"aa"})).getValue(),
origin.echo("aa"));
}

View File

@ -38,6 +38,11 @@ public class MockInvocation implements Invocation {
return "echo";
}
@Override
public String getServiceName() {
return "DemoService";
}
public Class<?>[] getParameterTypes() {
return new Class[]{String.class};
}

View File

@ -24,6 +24,8 @@ import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import java.util.concurrent.CompletableFuture;
/**
* MockInvoker.java
*/
@ -67,7 +69,7 @@ public class MyInvoker<T> implements Invoker<T> {
result.setException(new RuntimeException("mocked exception"));
}
return AsyncRpcResult.newDefaultAsyncResult(result, invocation);
return new AsyncRpcResult(CompletableFuture.completedFuture(result), invocation);
}
@Override

View File

@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcInvocation;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -28,6 +29,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.apache.dubbo.rpc.Constants.AUTO_ATTACH_INVOCATIONID_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
@ -35,8 +37,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
import static org.apache.dubbo.rpc.Constants.AUTO_ATTACH_INVOCATIONID_KEY;
public class RpcUtilsTest {
/**
@ -48,7 +48,7 @@ public class RpcUtilsTest {
URL url = URL.valueOf("dubbo://localhost/?test.async=true");
Map<String, Object> attachments = new HashMap<String, Object>();
attachments.put("aa", "bb");
Invocation inv = new RpcInvocation("test", new Class[]{}, new String[]{}, attachments);
Invocation inv = new RpcInvocation("test", "DemoService", new Class[]{}, new String[]{}, attachments);
RpcUtils.attachInvocationIdIfAsync(url, inv);
long id1 = RpcUtils.getInvocationId(inv);
RpcUtils.attachInvocationIdIfAsync(url, inv);
@ -65,7 +65,7 @@ public class RpcUtilsTest {
@Test
public void testAttachInvocationIdIfAsync_sync() {
URL url = URL.valueOf("dubbo://localhost/");
Invocation inv = new RpcInvocation("test", new Class[]{}, new String[]{});
Invocation inv = new RpcInvocation("test", "DemoService", new Class[]{}, new String[]{});
RpcUtils.attachInvocationIdIfAsync(url, inv);
assertNull(RpcUtils.getInvocationId(inv));
}
@ -77,7 +77,7 @@ public class RpcUtilsTest {
@Test
public void testAttachInvocationIdIfAsync_nullAttachments() {
URL url = URL.valueOf("dubbo://localhost/?test.async=true");
Invocation inv = new RpcInvocation("test", new Class[]{}, new String[]{});
Invocation inv = new RpcInvocation("test", "DemoService", new Class[]{}, new String[]{});
RpcUtils.attachInvocationIdIfAsync(url, inv);
assertTrue(RpcUtils.getInvocationId(inv) >= 0L);
}
@ -89,7 +89,7 @@ public class RpcUtilsTest {
@Test
public void testAttachInvocationIdIfAsync_forceNotAttache() {
URL url = URL.valueOf("dubbo://localhost/?test.async=true&" + AUTO_ATTACH_INVOCATIONID_KEY + "=false");
Invocation inv = new RpcInvocation("test", new Class[]{}, new String[]{});
Invocation inv = new RpcInvocation("test", "DemoService", new Class[]{}, new String[]{});
RpcUtils.attachInvocationIdIfAsync(url, inv);
assertNull(RpcUtils.getInvocationId(inv));
}
@ -101,7 +101,7 @@ public class RpcUtilsTest {
@Test
public void testAttachInvocationIdIfAsync_forceAttache() {
URL url = URL.valueOf("dubbo://localhost/?" + AUTO_ATTACH_INVOCATIONID_KEY + "=true");
Invocation inv = new RpcInvocation("test", new Class[]{}, new String[]{});
Invocation inv = new RpcInvocation("test", "DemoService", new Class[]{}, new String[]{});
RpcUtils.attachInvocationIdIfAsync(url, inv);
assertNotNull(RpcUtils.getInvocationId(inv));
}
@ -109,40 +109,41 @@ public class RpcUtilsTest {
@Test
public void testGetReturnTypes() throws Exception {
Invoker invoker = mock(Invoker.class);
String service = "org.apache.dubbo.rpc.support.DemoService";
given(invoker.getUrl()).willReturn(URL.valueOf("test://127.0.0.1:1/org.apache.dubbo.rpc.support.DemoService?interface=org.apache.dubbo.rpc.support.DemoService"));
Invocation inv = new RpcInvocation("testReturnType", new Class<?>[]{String.class}, null, null, invoker);
Invocation inv = new RpcInvocation("testReturnType", service, new Class<?>[]{String.class}, null, null, invoker);
java.lang.reflect.Type[] types = RpcUtils.getReturnTypes(inv);
Assertions.assertEquals(2, types.length);
Assertions.assertEquals(String.class, types[0]);
Assertions.assertEquals(String.class, types[1]);
Invocation inv1 = new RpcInvocation("testReturnType1", new Class<?>[]{String.class}, null, null, invoker);
Invocation inv1 = new RpcInvocation("testReturnType1", service, new Class<?>[]{String.class}, null, null, invoker);
java.lang.reflect.Type[] types1 = RpcUtils.getReturnTypes(inv1);
Assertions.assertEquals(2, types1.length);
Assertions.assertEquals(List.class, types1[0]);
Assertions.assertEquals(DemoService.class.getMethod("testReturnType1", new Class<?>[]{String.class}).getGenericReturnType(), types1[1]);
Invocation inv2 = new RpcInvocation("testReturnType2", new Class<?>[]{String.class}, null, null, invoker);
Invocation inv2 = new RpcInvocation("testReturnType2", service, new Class<?>[]{String.class}, null, null, invoker);
java.lang.reflect.Type[] types2 = RpcUtils.getReturnTypes(inv2);
Assertions.assertEquals(2, types2.length);
Assertions.assertEquals(String.class, types2[0]);
Assertions.assertEquals(String.class, types2[1]);
Invocation inv3 = new RpcInvocation("testReturnType3", new Class<?>[]{String.class}, null, null, invoker);
Invocation inv3 = new RpcInvocation("testReturnType3", service, new Class<?>[]{String.class}, null, null, invoker);
java.lang.reflect.Type[] types3 = RpcUtils.getReturnTypes(inv3);
Assertions.assertEquals(2, types3.length);
Assertions.assertEquals(List.class, types3[0]);
java.lang.reflect.Type genericReturnType3 = DemoService.class.getMethod("testReturnType3", new Class<?>[]{String.class}).getGenericReturnType();
Assertions.assertEquals(((ParameterizedType) genericReturnType3).getActualTypeArguments()[0], types3[1]);
Invocation inv4 = new RpcInvocation("testReturnType4", new Class<?>[]{String.class}, null, null, invoker);
Invocation inv4 = new RpcInvocation("testReturnType4", service, new Class<?>[]{String.class}, null, null, invoker);
java.lang.reflect.Type[] types4 = RpcUtils.getReturnTypes(inv4);
Assertions.assertEquals(2, types4.length);
Assertions.assertNull(types4[0]);
Assertions.assertNull(types4[1]);
Invocation inv5 = new RpcInvocation("testReturnType5", new Class<?>[]{String.class}, null, null, invoker);
Invocation inv5 = new RpcInvocation("testReturnType5", service, new Class<?>[]{String.class}, null, null, invoker);
java.lang.reflect.Type[] types5 = RpcUtils.getReturnTypes(inv5);
Assertions.assertEquals(2, types5.length);
Assertions.assertEquals(Map.class, types5[0]);

View File

@ -41,13 +41,13 @@ import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;
import static org.apache.dubbo.rpc.Constants.CALLBACK_INSTANCES_LIMIT_KEY;
import static org.apache.dubbo.rpc.Constants.DEFAULT_CALLBACK_INSTANCES;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_PROXY_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CHANNEL_CALLBACK_KEY;
import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_PROXY_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CHANNEL_CALLBACK_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;
/**
* callback service helper
@ -65,7 +65,7 @@ class CallbackServiceCodec {
private static byte isCallBack(URL url, String methodName, int argIndex) {
// parameter callback rule: method-name.parameter-index(starting from 0).callback
byte isCallback = CALLBACK_NONE;
if (url != null) {
if (url != null && url.hasMethodParameter(methodName)) {
String callback = url.getParameter(methodName + "." + argIndex + ".callback");
if (callback != null) {
if ("true".equalsIgnoreCase(callback)) {

View File

@ -72,16 +72,8 @@ class ChannelWrappedInvoker<T> extends AbstractInvoker<T> {
currentClient.send(inv, getUrl().getMethodParameter(invocation.getMethodName(), SENT_KEY, false));
return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else {
CompletableFuture<Object> responseFuture = currentClient.request(inv);
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(inv);
responseFuture.whenComplete((appResponse, t) -> {
if (t != null) {
asyncRpcResult.completeExceptionally(t);
} else {
asyncRpcResult.complete((AppResponse) appResponse);
}
});
return asyncRpcResult;
CompletableFuture<AppResponse> appResponseFuture = currentClient.request(inv).thenApply(obj -> (AppResponse) obj);
return new AsyncRpcResult(appResponseFuture, inv);
}
} catch (RpcException e) {
throw e;

View File

@ -32,7 +32,7 @@ public interface Constants {
String DECODE_IN_IO_THREAD_KEY = "decode.in.io";
boolean DEFAULT_DECODE_IN_IO_THREAD = true;
boolean DEFAULT_DECODE_IN_IO_THREAD = false;
/**
* callback inst id

View File

@ -22,7 +22,6 @@ import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.serialize.Cleanable;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.Codec;
@ -30,17 +29,21 @@ import org.apache.dubbo.remoting.Decodeable;
import org.apache.dubbo.remoting.exchange.Request;
import org.apache.dubbo.remoting.transport.CodecSupport;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.MethodModel;
import org.apache.dubbo.rpc.model.ServiceModel;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.decodeInvocationArgument;
import static org.apache.dubbo.remoting.Constants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.CallbackServiceCodec.decodeInvocationArgument;
public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Decodeable {
@ -97,27 +100,37 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec
request.setVersion(dubboVersion);
setAttachment(DUBBO_VERSION_KEY, dubboVersion);
setAttachment(PATH_KEY, in.readUTF());
String path = in.readUTF();
setAttachment(PATH_KEY, path);
setAttachment(VERSION_KEY, in.readUTF());
setMethodName(in.readUTF());
String desc = in.readUTF();
setParameterTypesDesc(desc);
try {
Object[] args;
Class<?>[] pts;
String desc = in.readUTF();
if (desc.length() == 0) {
pts = DubboCodec.EMPTY_CLASS_ARRAY;
args = DubboCodec.EMPTY_OBJECT_ARRAY;
} else {
pts = ReflectUtils.desc2classArray(desc);
args = new Object[pts.length];
for (int i = 0; i < args.length; i++) {
try {
args[i] = in.readObject(pts[i]);
} catch (Exception e) {
if (log.isWarnEnabled()) {
log.warn("Decode argument failed: " + e.getMessage(), e);
Object[] args = DubboCodec.EMPTY_OBJECT_ARRAY;
Class<?>[] pts = DubboCodec.EMPTY_CLASS_ARRAY;
if (desc.length() > 0) {
// TODO, lambda function requires variables to be final.
Optional<ServiceModel> serviceModel = ApplicationModel.getServiceModel(path);
if (serviceModel.isPresent()) {
Optional<MethodModel> methodOptional = serviceModel.get().getMethod(getMethodName(), desc);
if (methodOptional.isPresent()) {
pts = methodOptional.get().getParameterClasses();
args = new Object[pts.length];
for (int i = 0; i < args.length; i++) {
try {
args[i] = in.readObject(pts[i]);
} catch (Exception e) {
if (log.isWarnEnabled()) {
log.warn("Decode argument failed: " + e.getMessage(), e);
}
}
}
this.setReturnTypes(methodOptional.get().getReturnTypes());
}
}
}
@ -132,6 +145,7 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec
attachment.putAll(map);
setAttachments(attachment);
}
//decode argument ,may be callback
for (int i = 0; i < args.length; i++) {
args[i] = decodeInvocationArgument(channel, this, pts, i, args[i]);

View File

@ -30,6 +30,7 @@ import org.apache.dubbo.remoting.exchange.Response;
import org.apache.dubbo.remoting.transport.CodecSupport;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.support.RpcUtils;
import java.io.IOException;
@ -38,6 +39,7 @@ import java.io.OutputStream;
import java.lang.reflect.Type;
import java.util.Map;
public class DecodeableRpcResult extends AppResponse implements Codec, Decodeable {
private static final Logger log = LoggerFactory.getLogger(DecodeableRpcResult.class);
@ -125,7 +127,12 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl
private void handleValue(ObjectInput in) throws IOException {
try {
Type[] returnTypes = RpcUtils.getReturnTypes(invocation);
Type[] returnTypes;
if (invocation instanceof RpcInvocation) {
returnTypes = ((RpcInvocation)invocation).getReturnTypes();
} else {
returnTypes = RpcUtils.getReturnTypes(invocation);
}
Object value = null;
if (ArrayUtils.isEmpty(returnTypes)) {
value = in.readObject();

View File

@ -23,7 +23,6 @@ import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.serialize.ObjectOutput;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.exchange.Request;
@ -179,7 +178,7 @@ public class DubboCodec extends ExchangeCodec {
out.writeUTF((String) inv.getAttachment(VERSION_KEY));
out.writeUTF(inv.getMethodName());
out.writeUTF(ReflectUtils.getDesc(inv.getParameterTypes()));
out.writeUTF(inv.getParameterTypesDesc());
Object[] args = inv.getArguments();
if (args != null) {
for (int i = 0; i < args.length; i++) {

View File

@ -93,12 +93,11 @@ public class DubboInvoker<T> extends AbstractInvoker<T> {
currentClient.send(inv, isSent);
return AsyncRpcResult.newDefaultAsyncResult(invocation);
} else {
AsyncRpcResult asyncRpcResult = new AsyncRpcResult(inv);
CompletableFuture<Object> responseFuture = currentClient.request(inv, timeout);
asyncRpcResult.subscribeTo(responseFuture);
CompletableFuture<AppResponse> appResponseFuture = currentClient.request(inv, timeout).thenApply(obj -> (AppResponse) obj);
RpcContext.getContext().setFuture(new FutureAdapter(appResponseFuture));
// save for 2.6.x compatibility, for example, TraceFilter in Zipkin uses com.alibaba.xxx.FutureAdapter
FutureContext.getContext().setCompatibleFuture(responseFuture);
return asyncRpcResult;
return new AsyncRpcResult(appResponseFuture, inv);
}
} catch (TimeoutException e) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);

View File

@ -62,27 +62,27 @@ import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.rpc.Constants.LAZY_CONNECT_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_CONNECT_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_DISCONNECT_KEY;
import static org.apache.dubbo.remoting.Constants.DEFAULT_HEARTBEAT;
import static org.apache.dubbo.remoting.Constants.HEARTBEAT_KEY;
import static org.apache.dubbo.remoting.Constants.CHANNEL_READONLYEVENT_SENT_KEY;
import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
import static org.apache.dubbo.remoting.Constants.CODEC_KEY;
import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY;
import static org.apache.dubbo.remoting.Constants.DEFAULT_HEARTBEAT;
import static org.apache.dubbo.remoting.Constants.DEFAULT_REMOTING_CLIENT;
import static org.apache.dubbo.remoting.Constants.HEARTBEAT_KEY;
import static org.apache.dubbo.remoting.Constants.SERVER_KEY;
import static org.apache.dubbo.rpc.Constants.DEFAULT_REMOTING_SERVER;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;
import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY;
import static org.apache.dubbo.rpc.Constants.DEFAULT_STUB_EVENT;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;
import static org.apache.dubbo.rpc.Constants.IS_SERVER_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.OPTIMIZER_KEY;
import static org.apache.dubbo.rpc.Constants.LAZY_CONNECT_KEY;
import static org.apache.dubbo.rpc.Constants.STUB_EVENT_KEY;
import static org.apache.dubbo.rpc.Constants.STUB_EVENT_METHODS_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.SHARE_CONNECTIONS_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.CALLBACK_SERVICE_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.DEFAULT_SHARE_CONNECTIONS;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.IS_CALLBACK_SERVICE;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_CONNECT_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ON_DISCONNECT_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.OPTIMIZER_KEY;
import static org.apache.dubbo.rpc.protocol.dubbo.Constants.SHARE_CONNECTIONS_KEY;
/**
@ -150,7 +150,7 @@ public class DubboProtocol extends AbstractProtocol {
}
RpcContext.getContext().setRemoteAddress(channel.getRemoteAddress());
Result result = invoker.invoke(inv);
return result.completionFuture().thenApply(Function.identity());
return result.thenApply(Function.identity());
}
@Override
@ -187,13 +187,22 @@ public class DubboProtocol extends AbstractProtocol {
}
}
/**
* FIXME channel.getUrl() always binds to a fixed service, and this service is random.
* we can choose to use a common service to carry onConnect event if there's no easy way to get the specific
* service this connection is binding to.
* @param channel
* @param url
* @param methodKey
* @return
*/
private Invocation createInvocation(Channel channel, URL url, String methodKey) {
String method = url.getParameter(methodKey);
if (method == null || method.length() == 0) {
return null;
}
RpcInvocation invocation = new RpcInvocation(method, new Class<?>[0], new Object[0]);
RpcInvocation invocation = new RpcInvocation(method, url.getParameter(INTERFACE_KEY), new Class<?>[0], new Object[0]);
invocation.setAttachment(PATH_KEY, url.getPath());
invocation.setAttachment(GROUP_KEY, url.getParameter(GROUP_KEY));
invocation.setAttachment(INTERFACE_KEY, url.getParameter(INTERFACE_KEY));

View File

@ -26,13 +26,12 @@ import org.apache.dubbo.rpc.ListenableFilter;
import org.apache.dubbo.rpc.Result;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ConsumerMethodModel;
import org.apache.dubbo.rpc.model.ConsumerModel;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static org.apache.dubbo.rpc.Constants.$INVOKE;
import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
/**
* EventFilter
@ -55,7 +54,7 @@ public class FutureFilter extends ListenableFilter {
}
private void fireInvokeCallback(final Invoker<?> invoker, final Invocation invocation) {
final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);
final ConsumerModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);
if (asyncMethodInfo == null) {
return;
}
@ -83,7 +82,7 @@ public class FutureFilter extends ListenableFilter {
}
private void fireReturnCallback(final Invoker<?> invoker, final Invocation invocation, final Object result) {
final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);
final ConsumerModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);
if (asyncMethodInfo == null) {
return;
}
@ -129,7 +128,7 @@ public class FutureFilter extends ListenableFilter {
}
private void fireThrowCallback(final Invoker<?> invoker, final Invocation invocation, final Throwable exception) {
final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);
final ConsumerModel.AsyncMethodInfo asyncMethodInfo = getAsyncMethodInfo(invoker, invocation);
if (asyncMethodInfo == null) {
return;
}
@ -175,7 +174,7 @@ public class FutureFilter extends ListenableFilter {
}
}
private ConsumerMethodModel.AsyncMethodInfo getAsyncMethodInfo(Invoker<?> invoker, Invocation invocation) {
private ConsumerModel.AsyncMethodInfo getAsyncMethodInfo(Invoker<?> invoker, Invocation invocation) {
final ConsumerModel consumerModel = ApplicationModel.getConsumerModel(invoker.getUrl().getServiceKey());
if (consumerModel == null) {
return null;
@ -186,12 +185,7 @@ public class FutureFilter extends ListenableFilter {
methodName = (String) invocation.getArguments()[0];
}
ConsumerMethodModel methodModel = consumerModel.getMethodModel(methodName);
if (methodModel == null) {
return null;
}
final ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = methodModel.getAsyncInfo();
final ConsumerModel.AsyncMethodInfo asyncMethodInfo = consumerModel.getMethodConfig(methodName);
if (asyncMethodInfo == null) {
return null;
}

View File

@ -16,12 +16,12 @@
*/
package org.apache.dubbo.rpc.protocol.dubbo.status;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.status.Status;
import org.apache.dubbo.common.status.StatusChecker;
import org.apache.dubbo.common.store.DataStore;
import org.apache.dubbo.remoting.Constants;
import java.util.Map;
import java.util.concurrent.ExecutorService;
@ -36,7 +36,7 @@ public class ThreadPoolStatusChecker implements StatusChecker {
@Override
public Status check() {
DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
Map<String, Object> executors = dataStore.get(Constants.EXECUTOR_SERVICE_COMPONENT_KEY);
Map<String, Object> executors = dataStore.get(CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY);
StringBuilder msg = new StringBuilder();
Status.Level level = Status.Level.OK;

View File

@ -25,7 +25,7 @@ import org.apache.dubbo.remoting.telnet.TelnetHandler;
import org.apache.dubbo.remoting.telnet.support.Help;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ProviderMethodModel;
import org.apache.dubbo.rpc.model.MethodModel;
import org.apache.dubbo.rpc.model.ProviderModel;
import com.alibaba.fastjson.JSON;
@ -35,6 +35,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.common.utils.PojoUtils.realize;
@ -152,15 +153,15 @@ public class InvokeTelnetHandler implements TelnetHandler {
private boolean isServiceMatch(String service, ProviderModel provider) {
return provider.getServiceName().equalsIgnoreCase(service)
return provider.getServiceKey().equalsIgnoreCase(service)
|| provider.getServiceInterfaceClass().getSimpleName().equalsIgnoreCase(service)
|| provider.getServiceInterfaceClass().getName().equalsIgnoreCase(service)
|| StringUtils.isEmpty(service);
}
private List<Method> findSameSignatureMethod(List<ProviderMethodModel> methods, String lookupMethodName, List<Object> args) {
private List<Method> findSameSignatureMethod(Set<MethodModel> methods, String lookupMethodName, List<Object> args) {
List<Method> sameSignatureMethods = new ArrayList<>();
for (ProviderMethodModel model : methods) {
for (MethodModel model : methods) {
Method method = model.getMethod();
if (method.getName().equals(lookupMethodName) && method.getParameterTypes().length == args.size()) {
sameSignatureMethods.add(method);

View File

@ -23,9 +23,8 @@ import org.apache.dubbo.remoting.Channel;
import org.apache.dubbo.remoting.telnet.TelnetHandler;
import org.apache.dubbo.remoting.telnet.support.Help;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ConsumerMethodModel;
import org.apache.dubbo.rpc.model.ConsumerModel;
import org.apache.dubbo.rpc.model.ProviderMethodModel;
import org.apache.dubbo.rpc.model.MethodModel;
import org.apache.dubbo.rpc.model.ProviderModel;
import java.lang.reflect.Method;
@ -87,11 +86,11 @@ public class ListTelnetHandler implements TelnetHandler {
}
for (ProviderModel provider : ApplicationModel.allProviderModels()) {
buf.append(provider.getServiceName());
buf.append(provider.getServiceKey());
if (detail) {
buf.append(" -> ");
buf.append(" published: ");
buf.append(isRegistered(provider.getServiceName()) ? "Y" : "N");
buf.append(isRegistered(provider.getServiceKey()) ? "Y" : "N");
}
buf.append("\r\n");
}
@ -103,11 +102,11 @@ public class ListTelnetHandler implements TelnetHandler {
}
for (ConsumerModel consumer : ApplicationModel.allConsumerModels()) {
buf.append(consumer.getServiceName());
buf.append(consumer.getServiceKey());
if (detail) {
buf.append(" -> ");
buf.append(" addresses: ");
buf.append(getConsumerAddressNum(consumer.getServiceName()));
buf.append(getConsumerAddressNum(consumer.getServiceKey()));
}
}
}
@ -120,8 +119,8 @@ public class ListTelnetHandler implements TelnetHandler {
private void printSpecifiedProvidedService(String service, StringBuilder buf, boolean detail) {
for (ProviderModel provider : ApplicationModel.allProviderModels()) {
if (isProviderMatched(service,provider)) {
buf.append(provider.getServiceName()).append(" (as provider):\r\n");
for (ProviderMethodModel method : provider.getAllMethods()) {
buf.append(provider.getServiceKey()).append(" (as provider):\r\n");
for (MethodModel method : provider.getAllMethods()) {
printMethod(method.getMethod(), buf, detail);
}
}
@ -131,8 +130,8 @@ public class ListTelnetHandler implements TelnetHandler {
private void printSpecifiedReferredService(String service, StringBuilder buf, boolean detail) {
for (ConsumerModel consumer : ApplicationModel.allConsumerModels()) {
if (isConsumerMatcher(service,consumer)) {
buf.append(consumer.getServiceName()).append(" (as consumer):\r\n");
for (ConsumerMethodModel method : consumer.getAllMethods()) {
buf.append(consumer.getServiceKey()).append(" (as consumer):\r\n");
for (MethodModel method : consumer.getAllMethods()) {
printMethod(method.getMethod(), buf, detail);
}
}
@ -149,13 +148,13 @@ public class ListTelnetHandler implements TelnetHandler {
}
private boolean isProviderMatched(String service, ProviderModel provider) {
return service.equalsIgnoreCase(provider.getServiceName())
return service.equalsIgnoreCase(provider.getServiceKey())
|| service.equalsIgnoreCase(provider.getServiceInterfaceClass().getName())
|| service.equalsIgnoreCase(provider.getServiceInterfaceClass().getSimpleName());
}
private boolean isConsumerMatcher(String service,ConsumerModel consumer) {
return service.equalsIgnoreCase(consumer.getServiceName())
return service.equalsIgnoreCase(consumer.getServiceKey())
|| service.equalsIgnoreCase(consumer.getServiceInterfaceClass().getName())
|| service.equalsIgnoreCase(consumer.getServiceInterfaceClass().getSimpleName());
}

View File

@ -69,7 +69,7 @@ public class InvokerTelnetHandlerTest {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ProviderModel providerModel = new ProviderModel(DemoService.class.getName(), new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel(DemoService.class.getName(), providerModel);
String result = invoke.telnet(mockChannel, "echo(\"ok\")");
@ -84,8 +84,8 @@ public class InvokerTelnetHandlerTest {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
ProviderModel providerModel = new ProviderModel(DemoService.class.getName(), new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel(DemoService.class.getName(), providerModel);
String result = invoke.telnet(mockChannel, "DemoService.echo(\"ok\")");
assertTrue(result.contains("result: \"ok\""));
@ -99,9 +99,8 @@ public class InvokerTelnetHandlerTest {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
ProviderModel providerModel = new ProviderModel(DemoService.class.getName(), new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel(DemoService.class.getName(), providerModel);
try {
invoke.telnet(mockChannel, "sayHello(null)");
} catch (Exception ex) {
@ -116,8 +115,8 @@ public class InvokerTelnetHandlerTest {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
ProviderModel providerModel = new ProviderModel(DemoService.class.getName(), new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel(DemoService.class.getName(), providerModel);
String result = invoke.telnet(mockChannel, "getType(\"High\")");
assertTrue(result.contains("result: \"High\""));
@ -132,9 +131,8 @@ public class InvokerTelnetHandlerTest {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
ProviderModel providerModel = new ProviderModel(DemoService.class.getName(), new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel(DemoService.class.getName(), providerModel);
String result = invoke.telnet(mockChannel, "getPerson({\"name\":\"zhangsan\",\"age\":12,\"class\":\"org.apache.dubbo.rpc.protocol.dubbo.support.Person\"})");
assertTrue(result.contains("result: 12"));
}
@ -147,9 +145,8 @@ public class InvokerTelnetHandlerTest {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
ProviderModel providerModel = new ProviderModel(DemoService.class.getName(), new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel(DemoService.class.getName(), providerModel);
String param = "{\"name\":\"Dubbo\",\"age\":8}";
String result = invoke.telnet(mockChannel, "getPerson(" + param + ")");
assertTrue(result.contains("Please use the select command to select the method you want to invoke. eg: select 1"));
@ -165,9 +162,8 @@ public class InvokerTelnetHandlerTest {
given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
ProviderModel providerModel = new ProviderModel(DemoService.class.getName(), new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel(DemoService.class.getName(), providerModel);
String param = "{\"name\":\"Dubbo\",\"age\":8},{\"name\":\"Apache\",\"age\":20}";
String result = invoke.telnet(mockChannel, "getPerson(" + param + ")");
assertTrue(result.contains("result: 28"));

View File

@ -27,8 +27,8 @@ import org.apache.dubbo.rpc.protocol.dubbo.support.DemoServiceImpl;
import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.lang.reflect.Method;
@ -66,7 +66,7 @@ public class ListTelnetHandlerTest {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
String result = list.telnet(mockChannel, "-l DemoService");
@ -80,7 +80,7 @@ public class ListTelnetHandlerTest {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
String result = list.telnet(mockChannel, "DemoService");
@ -94,11 +94,11 @@ public class ListTelnetHandlerTest {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn(null);
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
String result = list.telnet(mockChannel, "");
assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService:1.0.0\r\n", result);
assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService\r\n", result);
}
@Test
@ -106,11 +106,11 @@ public class ListTelnetHandlerTest {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn(null);
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
String result = list.telnet(mockChannel, "-l");
assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService:1.0.0 -> published: N\r\n", result);
assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService -> published: N\r\n", result);
}
@Test
@ -118,12 +118,12 @@ public class ListTelnetHandlerTest {
mockChannel = mock(Channel.class);
given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), ApplicationModel.registerServiceModel(DemoService.class));
ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
String result = list.telnet(mockChannel, "");
assertTrue(result.startsWith("Use default service org.apache.dubbo.rpc.protocol.dubbo.support.DemoService.\r\n" +
"org.apache.dubbo.rpc.protocol.dubbo.support.DemoService:1.0.0 (as provider):\r\n"));
"org.apache.dubbo.rpc.protocol.dubbo.support.DemoService (as provider):\r\n"));
for (Method method : DemoService.class.getMethods()) {
assertTrue(result.contains(method.getName()));
}

Some files were not shown because too many files have changed in this diff Show More