Observability task: registration center (#11493)
This commit is contained in:
parent
d57ad31299
commit
c041fa1f93
|
|
@ -68,5 +68,11 @@
|
|||
<version>${project.parent.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-registry</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,31 @@
|
|||
*/
|
||||
package org.apache.dubbo.rpc.cluster.directory;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.Version;
|
||||
import org.apache.dubbo.common.config.Configuration;
|
||||
import org.apache.dubbo.common.config.ConfigurationUtils;
|
||||
import org.apache.dubbo.common.constants.LoggerCodeConstants;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||
import org.apache.dubbo.common.utils.NetUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
import org.apache.dubbo.rpc.cluster.Router;
|
||||
import org.apache.dubbo.rpc.cluster.RouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
|
@ -31,29 +56,6 @@ import java.util.concurrent.ThreadLocalRandom;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.Version;
|
||||
import org.apache.dubbo.common.config.Configuration;
|
||||
import org.apache.dubbo.common.config.ConfigurationUtils;
|
||||
import org.apache.dubbo.common.constants.LoggerCodeConstants;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||
import org.apache.dubbo.common.utils.NetUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcContext;
|
||||
import org.apache.dubbo.rpc.RpcException;
|
||||
import org.apache.dubbo.rpc.cluster.Directory;
|
||||
import org.apache.dubbo.rpc.cluster.Router;
|
||||
import org.apache.dubbo.rpc.cluster.RouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RECONNECT_TASK_PERIOD;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_RECONNECT_TASK_TRY_COUNT;
|
||||
|
|
@ -128,6 +130,10 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
*/
|
||||
private final int reconnectTaskPeriod;
|
||||
|
||||
private final GlobalMetricsEventMulticaster eventMulticaster;
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
|
||||
public AbstractDirectory(URL url) {
|
||||
this(url, null, false);
|
||||
}
|
||||
|
|
@ -153,7 +159,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
}
|
||||
|
||||
// remove some local only parameters
|
||||
ApplicationModel applicationModel = url.getOrDefaultApplicationModel();
|
||||
applicationModel = url.getOrDefaultApplicationModel();
|
||||
this.queryMap = applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap);
|
||||
|
||||
if (consumerUrl == null) {
|
||||
|
|
@ -179,12 +185,14 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
this.reconnectTaskTryCount = configuration.getInt(RECONNECT_TASK_TRY_COUNT, DEFAULT_RECONNECT_TASK_TRY_COUNT);
|
||||
this.reconnectTaskPeriod = configuration.getInt(RECONNECT_TASK_PERIOD, DEFAULT_RECONNECT_TASK_PERIOD);
|
||||
setRouterChain(routerChain);
|
||||
|
||||
eventMulticaster = applicationModel.getBeanFactory().getBean(GlobalMetricsEventMulticaster.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Invoker<T>> list(Invocation invocation) throws RpcException {
|
||||
if (destroyed) {
|
||||
throw new RpcException("Directory of type " + this.getClass().getSimpleName() + " already destroyed for service " + getConsumerUrl().getServiceKey() + " from registry " + getUrl());
|
||||
throw new RpcException("Directory of type " + this.getClass().getSimpleName() + " already destroyed for service " + getConsumerUrl().getServiceKey() + " from registry " + getUrl());
|
||||
}
|
||||
|
||||
BitList<Invoker<T>> availableInvokers;
|
||||
|
|
@ -381,6 +389,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
|
||||
@Override
|
||||
public void addDisabledInvoker(Invoker<T> invoker) {
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_DISABLE));
|
||||
if (invokers.contains(invoker)) {
|
||||
disabledInvokers.add(invoker);
|
||||
removeValidInvoker(invoker);
|
||||
|
|
@ -390,6 +399,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
|
||||
@Override
|
||||
public void recoverDisabledInvoker(Invoker<T> invoker) {
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_RECOVER_DISABLE));
|
||||
if (disabledInvokers.remove(invoker)) {
|
||||
try {
|
||||
addValidInvoker(invoker);
|
||||
|
|
@ -453,6 +463,7 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
this.invokers = invokers;
|
||||
refreshInvokerInternal();
|
||||
this.invokersInitialized = true;
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_CURRENT, invokers.size()));
|
||||
}
|
||||
|
||||
protected void destroyInvokers() {
|
||||
|
|
@ -463,12 +474,14 @@ public abstract class AbstractDirectory<T> implements Directory<T> {
|
|||
}
|
||||
|
||||
private boolean addValidInvoker(Invoker<T> invoker) {
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_VALID));
|
||||
synchronized (this.validInvokers) {
|
||||
return this.validInvokers.add(invoker);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean removeValidInvoker(Invoker<T> invoker) {
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsDirectoryEvent(applicationModel, RegistryEvent.Type.D_UN_VALID));
|
||||
synchronized (this.validInvokers) {
|
||||
return this.validInvokers.remove(invoker);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.cluster.directory;
|
|||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.utils.Holder;
|
||||
import org.apache.dubbo.common.utils.NetUtils;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.apache.dubbo.rpc.cluster.router.MockInvoker;
|
||||
|
|
@ -26,6 +27,7 @@ import org.apache.dubbo.rpc.cluster.router.condition.ConditionStateRouterFactory
|
|||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||
import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
|
||||
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
|
@ -60,6 +62,7 @@ class StaticDirectoryTest {
|
|||
|
||||
|
||||
List<Invoker<String>> filteredInvokers = router.route(invokers.clone(), URL.valueOf("consumer://" + NetUtils.getLocalHost() + "/com.foo.BarService"), new RpcInvocation(), false, new Holder<>());
|
||||
ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
|
||||
StaticDirectory<String> staticDirectory = new StaticDirectory<>(filteredInvokers);
|
||||
boolean isAvailable = staticDirectory.isAvailable();
|
||||
Assertions.assertTrue(!isAvailable);
|
||||
|
|
|
|||
|
|
@ -16,18 +16,11 @@
|
|||
*/
|
||||
package org.apache.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
||||
import org.apache.dubbo.common.utils.NetUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
|
|
@ -41,6 +34,7 @@ import org.apache.dubbo.rpc.cluster.filter.DemoService;
|
|||
import org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance;
|
||||
import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
|
||||
import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
|
@ -50,6 +44,14 @@ import org.junit.jupiter.api.Disabled;
|
|||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.ENABLE_CONNECTIVITY_VALIDATION;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
|
||||
|
|
@ -104,6 +106,7 @@ class AbstractClusterInvokerTest {
|
|||
@SuppressWarnings({"unchecked"})
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("application", "abstractClusterInvokerTest");
|
||||
url = url.putAttribute(REFER_KEY, attributes);
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.cluster.support;
|
|||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Result;
|
||||
|
|
@ -28,6 +29,7 @@ import org.apache.dubbo.rpc.cluster.Directory;
|
|||
import org.apache.dubbo.rpc.cluster.LoadBalance;
|
||||
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
|
||||
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
|
@ -70,6 +72,7 @@ class ConnectivityValidationTest {
|
|||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
|
||||
invoker1 = Mockito.mock(Invoker.class);
|
||||
invoker2 = Mockito.mock(Invoker.class);
|
||||
invoker3 = Mockito.mock(Invoker.class);
|
||||
|
|
|
|||
|
|
@ -16,11 +16,8 @@
|
|||
*/
|
||||
package org.apache.dubbo.rpc.cluster.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.rpc.AppResponse;
|
||||
import org.apache.dubbo.rpc.AsyncRpcResult;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
|
|
@ -33,10 +30,15 @@ import org.apache.dubbo.rpc.cluster.Directory;
|
|||
import org.apache.dubbo.rpc.cluster.SingleRouterChain;
|
||||
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
|
||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.protocol.AbstractInvoker;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertSame;
|
||||
|
|
@ -65,7 +67,7 @@ class FailoverClusterInvokerTest {
|
|||
|
||||
@BeforeEach
|
||||
public void setUp() throws Exception {
|
||||
|
||||
ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
|
||||
dic = mock(Directory.class);
|
||||
|
||||
given(dic.getUrl()).willReturn(url);
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.cluster.support.wrapper;
|
|||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.Protocol;
|
||||
|
|
@ -28,6 +29,7 @@ import org.apache.dubbo.rpc.RpcInvocation;
|
|||
import org.apache.dubbo.rpc.cluster.LoadBalance;
|
||||
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
|
||||
import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.support.MockProtocol;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
|
|
@ -49,6 +51,7 @@ class MockClusterInvokerTest {
|
|||
|
||||
@BeforeEach
|
||||
public void beforeMethod() {
|
||||
ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
|
||||
invokers.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.cluster.support.wrapper;
|
|||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.extension.ExtensionLoader;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.rpc.Invocation;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
import org.apache.dubbo.rpc.ProxyFactory;
|
||||
|
|
@ -28,6 +29,7 @@ import org.apache.dubbo.rpc.cluster.LoadBalance;
|
|||
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
|
||||
import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker;
|
||||
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
|
@ -46,6 +48,7 @@ class MockProviderRpcExceptionTest {
|
|||
|
||||
@BeforeEach
|
||||
public void beforeMethod() {
|
||||
ApplicationModel.defaultModel().getBeanFactory().registerBean(GlobalMetricsEventMulticaster.class);
|
||||
invokers.clear();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,12 @@ public class MetricsConfig extends AbstractConfig {
|
|||
private Boolean enableJvmMetrics;
|
||||
|
||||
/**
|
||||
* Enable jvm metrics when collecting.
|
||||
* Enable registry metrics.
|
||||
*/
|
||||
private Boolean enableRegistryMetrics;
|
||||
|
||||
/**
|
||||
* Enable metadata metrics.
|
||||
*/
|
||||
private Boolean enableMetadataMetrics;
|
||||
|
||||
|
|
@ -103,6 +108,14 @@ public class MetricsConfig extends AbstractConfig {
|
|||
this.enableJvmMetrics = enableJvmMetrics;
|
||||
}
|
||||
|
||||
public Boolean getEnableRegistryMetrics() {
|
||||
return enableRegistryMetrics;
|
||||
}
|
||||
|
||||
public void setEnableRegistryMetrics(Boolean enableRegistryMetrics) {
|
||||
this.enableRegistryMetrics = enableRegistryMetrics;
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return port;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,12 +42,24 @@
|
|||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-default</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-registry</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-metadata</artifactId>
|
||||
|
|
|
|||
|
|
@ -51,6 +51,9 @@ import org.apache.dubbo.config.utils.ConfigValidationUtils;
|
|||
import org.apache.dubbo.metadata.report.MetadataReportFactory;
|
||||
import org.apache.dubbo.metadata.report.MetadataReportInstance;
|
||||
import org.apache.dubbo.metrics.collector.DefaultMetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.metrics.report.MetricsReporter;
|
||||
import org.apache.dubbo.metrics.report.MetricsReporterFactory;
|
||||
import org.apache.dubbo.metrics.service.MetricsServiceExporter;
|
||||
|
|
@ -825,10 +828,15 @@ public class DefaultApplicationDeployer extends AbstractDeployer<ApplicationMode
|
|||
private final AtomicInteger serviceRefreshState = new AtomicInteger(0);
|
||||
|
||||
private void registerServiceInstance() {
|
||||
TimePair timePair = TimePair.start();
|
||||
GlobalMetricsEventMulticaster eventMulticaster = applicationModel.getBeanFactory().getBean(GlobalMetricsEventMulticaster.class);
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
|
||||
try {
|
||||
registered = true;
|
||||
ServiceInstanceMetadataUtils.registerMetadataAndInstance(applicationModel);
|
||||
eventMulticaster.publishFinishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
|
||||
} catch (Exception e) {
|
||||
eventMulticaster.publishErrorEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
|
||||
logger.error(CONFIG_REGISTER_INSTANCE_ERROR, "configuration server disconnected", "", "Register instance error.", e);
|
||||
}
|
||||
if (registered) {
|
||||
|
|
|
|||
|
|
@ -190,6 +190,13 @@
|
|||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-registry</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-prometheus</artifactId>
|
||||
|
|
@ -502,6 +509,7 @@
|
|||
<include>org.apache.dubbo:dubbo-metadata-report-zookeeper</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-api</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-default</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-registry</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-metadata</include>
|
||||
<include>org.apache.dubbo:dubbo-metrics-prometheus</include>
|
||||
<include>org.apache.dubbo:dubbo-monitor-api</include>
|
||||
|
|
|
|||
|
|
@ -235,6 +235,11 @@
|
|||
<artifactId>dubbo-metrics-default</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-registry</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-prometheus</artifactId>
|
||||
|
|
|
|||
|
|
@ -36,11 +36,6 @@
|
|||
<artifactId>dubbo-common</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-cluster</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-rpc-api</artifactId>
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ public class SimpleMetricsEventMulticaster implements MetricsEventMulticaster {
|
|||
publishTimeEvent(event, metricsLifeListener -> metricsLifeListener.onEventError(event));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
private void publishTimeEvent(MetricsEvent event, Consumer<MetricsLifeListener> consumer) {
|
||||
if (event instanceof EmptyEvent) {
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ public enum MetricsKey {
|
|||
// provider metrics key
|
||||
METRIC_REQUESTS("dubbo.%s.requests.total", "Total Requests"),
|
||||
METRIC_REQUESTS_SUCCEED("dubbo.%s.requests.succeed.total", "Succeed Requests"),
|
||||
METRIC_REQUEST_BUSINESS_FAILED("dubbo.%s.requests.business.failed.total","Failed Business Requests"),
|
||||
METRIC_REQUEST_BUSINESS_FAILED("dubbo.%s.requests.business.failed.total", "Failed Business Requests"),
|
||||
METRIC_REQUESTS_PROCESSING("dubbo.%s.requests.processing", "Processing Requests"),
|
||||
METRIC_REQUESTS_TIMEOUT("dubbo.%s.requests.timeout.total", "Total Timeout Failed Requests"),
|
||||
METRIC_REQUESTS_LIMIT("dubbo.%s.requests.limit.total", "Total Limit Failed Requests"),
|
||||
|
|
@ -59,6 +59,26 @@ public enum MetricsKey {
|
|||
GENERIC_METRIC_RT_P99("dubbo.%s.rt.seconds.p99", "Response Time P99"),
|
||||
GENERIC_METRIC_RT_P95("dubbo.%s.rt.seconds.p95", "Response Time P95"),
|
||||
|
||||
// register metrics key
|
||||
REGISTER_METRIC_REQUESTS("dubbo.registry.register.requests.total", "Total Register Requests"),
|
||||
REGISTER_METRIC_REQUESTS_SUCCEED("dubbo.registry.register.requests.succeed.total", "Succeed Register Requests"),
|
||||
REGISTER_METRIC_REQUESTS_FAILED("dubbo.registry.register.requests.failed.total", "Failed Register Requests"),
|
||||
|
||||
// subscribe metrics key
|
||||
SUBSCRIBE_METRIC_NUM("dubbo.registry.subscribe.num.total", "Total Subscribe Num"),
|
||||
SUBSCRIBE_METRIC_NUM_SUCCEED("dubbo.registry.subscribe.num.succeed.total", "Succeed Subscribe Num"),
|
||||
SUBSCRIBE_METRIC_NUM_FAILED("dubbo.registry.subscribe.num.failed.total", "Failed Subscribe Num"),
|
||||
|
||||
// directory metrics key
|
||||
DIRECTORY_METRIC_NUM_CURRENT("dubbo.registry.directory.num.current", "Current Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_VALID("dubbo.registry.directory.num.valid.total", "Valid Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_UN_VALID("dubbo.registry.directory.num.un_valid.total", "UnValid Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_DISABLE("dubbo.registry.directory.num.disable.total", "Disable Directory Urls"),
|
||||
DIRECTORY_METRIC_NUM_RECOVER_DISABLE("dubbo.registry.directory.num.recover.disable.total", "Recover Disable Directory Urls"),
|
||||
|
||||
NOTIFY_METRIC_REQUESTS("dubbo.registry.notify.requests.total", "Total Notify Requests"),
|
||||
NOTIFY_METRIC_NUM_LAST("dubbo.registry.notify.num.last", "Last Notify Nums"),
|
||||
|
||||
THREAD_POOL_CORE_SIZE("dubbo.thread.pool.core.size", "Thread Pool Core Size"),
|
||||
THREAD_POOL_LARGEST_SIZE("dubbo.thread.pool.largest.size", "Thread Pool Largest Size"),
|
||||
THREAD_POOL_MAX_SIZE("dubbo.thread.pool.max.size", "Thread Pool Max Size"),
|
||||
|
|
@ -85,6 +105,7 @@ public enum MetricsKey {
|
|||
public final String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public final String getNameByType(String type) {
|
||||
return String.format(name, type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ public class TimePair {
|
|||
|
||||
private final long begin;
|
||||
private long end;
|
||||
private static final TimePair empty = new TimePair(0L);
|
||||
|
||||
public TimePair(long currentTimeMillis) {
|
||||
this.begin = currentTimeMillis;
|
||||
|
|
@ -37,4 +38,8 @@ public class TimePair {
|
|||
public long calc() {
|
||||
return end - begin;
|
||||
}
|
||||
|
||||
public static TimePair empty() {
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,5 +46,11 @@
|
|||
<artifactId>micrometer-tracing-integration-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-cluster</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics</artifactId>
|
||||
<version>${revision}</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<artifactId>dubbo-metrics-registry</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>The metrics module of dubbo project</description>
|
||||
<properties>
|
||||
<skip_maven_deploy>false</skip_maven_deploy>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-api</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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.metrics.registry.collector;
|
||||
|
||||
import org.apache.dubbo.common.extension.Activate;
|
||||
import org.apache.dubbo.config.context.ConfigManager;
|
||||
import org.apache.dubbo.metrics.collector.ApplicationMetricsCollector;
|
||||
import org.apache.dubbo.metrics.collector.MetricsCollector;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.MetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryMetricsEventMulticaster;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
|
||||
/**
|
||||
* Registry implementation of {@link MetricsCollector}
|
||||
*/
|
||||
@Activate
|
||||
public class RegistryMetricsCollector implements ApplicationMetricsCollector<RegistryEvent.Type, RegistryEvent> {
|
||||
|
||||
private Boolean collectEnabled = null;
|
||||
private final RegistryStatComposite stats;
|
||||
private final MetricsEventMulticaster registryMulticaster;
|
||||
private final ApplicationModel applicationModel;
|
||||
|
||||
public RegistryMetricsCollector(ApplicationModel applicationModel) {
|
||||
this.stats = new RegistryStatComposite();
|
||||
this.registryMulticaster = new RegistryMetricsEventMulticaster();
|
||||
this.applicationModel = applicationModel;
|
||||
}
|
||||
|
||||
public void setCollectEnabled(Boolean collectEnabled) {
|
||||
if (collectEnabled != null) {
|
||||
this.collectEnabled = collectEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollectEnabled() {
|
||||
if (collectEnabled == null) {
|
||||
ConfigManager configManager = applicationModel.getApplicationConfigManager();
|
||||
configManager.getMetrics().ifPresent(metricsConfig -> setCollectEnabled(metricsConfig.getEnableRegistryMetrics()));
|
||||
}
|
||||
return Optional.ofNullable(collectEnabled).orElse(false);
|
||||
}
|
||||
|
||||
public void setNum(RegistryEvent.Type registryType, String applicationName, Map<String, Integer> lastNumMap) {
|
||||
lastNumMap.forEach((serviceKey, num) ->
|
||||
this.stats.setServiceKey(registryType, applicationName, serviceKey, num));
|
||||
}
|
||||
|
||||
public void setNum(RegistryEvent.Type registryType, String applicationName, Integer num) {
|
||||
this.stats.setApplicationKey(registryType, applicationName, num);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void increment(String applicationName, RegistryEvent.Type registryType) {
|
||||
this.stats.increment(registryType, applicationName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addRT(String applicationName, String registryOpType, Long responseTime) {
|
||||
stats.calcRt(applicationName, registryOpType, responseTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetricSample> collect() {
|
||||
if (!isCollectEnabled()) {
|
||||
new ArrayList<>();
|
||||
}
|
||||
List<MetricSample> list = new ArrayList<>();
|
||||
list.addAll(stats.exportNumMetrics());
|
||||
list.addAll(stats.exportRtMetrics());
|
||||
list.addAll(stats.exportSkMetrics());
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RegistryEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(RegistryEvent event) {
|
||||
registryMulticaster.publishEvent(event);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEventFinish(RegistryEvent event) {
|
||||
registryMulticaster.publishFinishEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventError(RegistryEvent event) {
|
||||
registryMulticaster.publishErrorEvent(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* 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.metrics.registry.collector.stat;
|
||||
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashMapUtils;
|
||||
import org.apache.dubbo.metrics.collector.MetricsCollector;
|
||||
import org.apache.dubbo.metrics.model.ApplicationMetric;
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.metrics.report.MetricsExport;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.atomic.LongAccumulator;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* As a data aggregator, use internal data containers calculates and classifies
|
||||
* the registry data collected by {@link MetricsCollector MetricsCollector}, and
|
||||
* provides an {@link MetricsExport MetricsExport} interface for exporting standard output formats.
|
||||
*/
|
||||
public class RegistryStatComposite implements MetricsExport {
|
||||
|
||||
|
||||
public Map<RegistryEvent.Type, Map<String, AtomicLong>> numStats = new ConcurrentHashMap<>();
|
||||
public Map<RegistryEvent.Type, Map<ServiceKeyMetric, AtomicLong>> skStats = new ConcurrentHashMap<>();
|
||||
public List<LongContainer<? extends Number>> rtStats = new ArrayList<>();
|
||||
public static String OP_TYPE_REGISTER = "register";
|
||||
public static String OP_TYPE_SUBSCRIBE = "subscribe";
|
||||
public static String OP_TYPE_NOTIFY = "notify";
|
||||
|
||||
public RegistryStatComposite() {
|
||||
for (RegistryEvent.Type type : RegistryEvent.Type.values()) {
|
||||
numStats.put(type, new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
rtStats.addAll(initStats(OP_TYPE_REGISTER));
|
||||
rtStats.addAll(initStats(OP_TYPE_SUBSCRIBE));
|
||||
rtStats.addAll(initStats(OP_TYPE_NOTIFY));
|
||||
}
|
||||
|
||||
private List<LongContainer<? extends Number>> initStats(String registryOpType) {
|
||||
List<LongContainer<? extends Number>> singleRtStats = new ArrayList<>();
|
||||
singleRtStats.add(new AtomicLongContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_LAST)));
|
||||
singleRtStats.add(new LongAccumulatorContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_MIN), new LongAccumulator(Long::min, Long.MAX_VALUE)));
|
||||
singleRtStats.add(new LongAccumulatorContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_MAX), new LongAccumulator(Long::max, Long.MIN_VALUE)));
|
||||
singleRtStats.add(new AtomicLongContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_SUM), (responseTime, longAccumulator) -> longAccumulator.addAndGet(responseTime)));
|
||||
// AvgContainer is a special counter that stores the number of times but outputs function of sum/times
|
||||
AtomicLongContainer avgContainer = new AtomicLongContainer(new MetricsKeyWrapper(registryOpType, MetricsKey.GENERIC_METRIC_RT_AVG), (k, v) -> v.incrementAndGet());
|
||||
avgContainer.setValueSupplier(applicationName -> {
|
||||
LongContainer<? extends Number> totalContainer = rtStats.stream().filter(longContainer -> longContainer.isKeyWrapper(MetricsKey.GENERIC_METRIC_RT_SUM, registryOpType)).findFirst().get();
|
||||
AtomicLong totalRtTimes = avgContainer.get(applicationName);
|
||||
AtomicLong totalRtSum = (AtomicLong) totalContainer.get(applicationName);
|
||||
return totalRtSum.get() / totalRtTimes.get();
|
||||
});
|
||||
singleRtStats.add(avgContainer);
|
||||
return singleRtStats;
|
||||
}
|
||||
|
||||
public void setApplicationKey(RegistryEvent.Type type, String applicationName, int num) {
|
||||
if (!numStats.containsKey(type)) {
|
||||
return;
|
||||
}
|
||||
numStats.get(type).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).set(num);
|
||||
}
|
||||
|
||||
public void setServiceKey(RegistryEvent.Type type, String applicationName, String serviceKey, int num) {
|
||||
if (!skStats.containsKey(type)) {
|
||||
return;
|
||||
}
|
||||
skStats.get(type).computeIfAbsent(new ServiceKeyMetric(applicationName, serviceKey), k -> new AtomicLong(0L)).set(num);
|
||||
}
|
||||
|
||||
public void increment(RegistryEvent.Type type, String applicationName) {
|
||||
if (!numStats.containsKey(type)) {
|
||||
return;
|
||||
}
|
||||
numStats.get(type).computeIfAbsent(applicationName, k -> new AtomicLong(0L)).incrementAndGet();
|
||||
}
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void calcRt(String applicationName, String registryOpType, Long responseTime) {
|
||||
for (LongContainer container : rtStats.stream().filter(longContainer -> longContainer.specifyType(registryOpType)).collect(Collectors.toList())) {
|
||||
Number current = (Number) ConcurrentHashMapUtils.computeIfAbsent(container, applicationName, container.getInitFunc());
|
||||
container.getConsumerFunc().accept(responseTime, current);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GaugeMetricSample> exportNumMetrics() {
|
||||
List<GaugeMetricSample> list = new ArrayList<>();
|
||||
for (RegistryEvent.Type type : numStats.keySet()) {
|
||||
Map<String, AtomicLong> stringAtomicLongMap = numStats.get(type);
|
||||
for (String applicationName : stringAtomicLongMap.keySet()) {
|
||||
list.add(convertToSample(applicationName, type, MetricsCategory.REGISTRY, stringAtomicLongMap.get(applicationName)));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GaugeMetricSample> exportRtMetrics() {
|
||||
List<GaugeMetricSample> list = new ArrayList<>();
|
||||
for (LongContainer<? extends Number> rtContainer : rtStats) {
|
||||
MetricsKeyWrapper metricsKeyWrapper = rtContainer.getMetricsKeyWrapper();
|
||||
for (Map.Entry<String, ? extends Number> entry : rtContainer.entrySet()) {
|
||||
list.add(new GaugeMetricSample(metricsKeyWrapper.targetKey(), metricsKeyWrapper.targetDesc(), ApplicationMetric.getTagsByName(entry.getKey()), MetricsCategory.RT, () -> rtContainer.getValueSupplier().apply(entry.getKey())));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<GaugeMetricSample> exportSkMetrics() {
|
||||
List<GaugeMetricSample> list = new ArrayList<>();
|
||||
for (RegistryEvent.Type type : skStats.keySet()) {
|
||||
Map<ServiceKeyMetric, AtomicLong> stringAtomicLongMap = skStats.get(type);
|
||||
for (ServiceKeyMetric serviceKeyMetric : stringAtomicLongMap.keySet()) {
|
||||
list.add(new GaugeMetricSample(type.getMetricsKey(), serviceKeyMetric.getTags(), MetricsCategory.REGISTRY, stringAtomicLongMap.get(serviceKeyMetric)::get));
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public GaugeMetricSample convertToSample(String applicationName, RegistryEvent.Type type, MetricsCategory category, AtomicLong targetNumber) {
|
||||
return new GaugeMetricSample(type.getMetricsKey(), ApplicationMetric.getTagsByName(applicationName), category, targetNumber::get);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collect Number type data
|
||||
*
|
||||
* @param <NUMBER>
|
||||
*/
|
||||
public static class LongContainer<NUMBER extends Number> extends ConcurrentHashMap<String, NUMBER> {
|
||||
|
||||
/**
|
||||
* Provide the metric type name
|
||||
*/
|
||||
private final MetricsKeyWrapper metricsKeyWrapper;
|
||||
/**
|
||||
* The initial value corresponding to the key is generally 0 of different data types
|
||||
*/
|
||||
private final Function<String, NUMBER> initFunc;
|
||||
/**
|
||||
* Statistical data calculation function, which can be self-increment, self-decrement, or more complex avg function
|
||||
*/
|
||||
private final BiConsumer<Long, NUMBER> consumerFunc;
|
||||
/**
|
||||
* Data output function required by {@link GaugeMetricSample GaugeMetricSample}
|
||||
*/
|
||||
private Function<String, Long> valueSupplier;
|
||||
|
||||
|
||||
public LongContainer(MetricsKeyWrapper metricsKeyWrapper, Supplier<NUMBER> initFunc, BiConsumer<Long, NUMBER> consumerFunc) {
|
||||
this.metricsKeyWrapper = metricsKeyWrapper;
|
||||
this.initFunc = s -> initFunc.get();
|
||||
this.consumerFunc = consumerFunc;
|
||||
this.valueSupplier = k -> this.get(k).longValue();
|
||||
}
|
||||
|
||||
public boolean specifyType(String type) {
|
||||
return type.equals(getMetricsKeyWrapper().getType());
|
||||
}
|
||||
|
||||
public MetricsKeyWrapper getMetricsKeyWrapper() {
|
||||
return metricsKeyWrapper;
|
||||
}
|
||||
|
||||
public boolean isKeyWrapper(MetricsKey metricsKey, String registryOpType) {
|
||||
return metricsKeyWrapper.isKey(metricsKey,registryOpType);
|
||||
}
|
||||
|
||||
public Function<String, NUMBER> getInitFunc() {
|
||||
return initFunc;
|
||||
}
|
||||
|
||||
public BiConsumer<Long, NUMBER> getConsumerFunc() {
|
||||
return consumerFunc;
|
||||
}
|
||||
|
||||
public Function<String, Long> getValueSupplier() {
|
||||
return valueSupplier;
|
||||
}
|
||||
|
||||
public void setValueSupplier(Function<String, Long> valueSupplier) {
|
||||
this.valueSupplier = valueSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "LongContainer{" +
|
||||
"metricsKeyWrapper=" + metricsKeyWrapper +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
public static class AtomicLongContainer extends LongContainer<AtomicLong> {
|
||||
|
||||
public AtomicLongContainer(MetricsKeyWrapper metricsKeyWrapper) {
|
||||
super(metricsKeyWrapper, AtomicLong::new, (responseTime, longAccumulator) -> longAccumulator.set(responseTime));
|
||||
}
|
||||
|
||||
public AtomicLongContainer(MetricsKeyWrapper metricsKeyWrapper, BiConsumer<Long, AtomicLong> consumerFunc) {
|
||||
super(metricsKeyWrapper, AtomicLong::new, consumerFunc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class LongAccumulatorContainer extends LongContainer<LongAccumulator> {
|
||||
public LongAccumulatorContainer(MetricsKeyWrapper metricsKeyWrapper, LongAccumulator accumulator) {
|
||||
super(metricsKeyWrapper, () -> accumulator, (responseTime, longAccumulator) -> longAccumulator.accumulate(responseTime));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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.metrics.registry.collector.stat;
|
||||
|
||||
import org.apache.dubbo.metrics.model.Metric;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
|
||||
|
||||
/**
|
||||
* Metric class for service.
|
||||
*/
|
||||
public class ServiceKeyMetric implements Metric {
|
||||
private final String applicationName;
|
||||
private final String serviceKey;
|
||||
|
||||
public ServiceKeyMetric(String applicationName, String serviceKey) {
|
||||
this.applicationName = applicationName;
|
||||
this.serviceKey = serviceKey;
|
||||
}
|
||||
|
||||
public String getServiceKey() {
|
||||
return serviceKey;
|
||||
}
|
||||
|
||||
public Map<String, String> getTags() {
|
||||
Map<String, String> tags = new HashMap<>();
|
||||
tags.put(TAG_IP, getLocalHost());
|
||||
tags.put(TAG_HOSTNAME, getLocalHostName());
|
||||
tags.put(TAG_APPLICATION_NAME, applicationName);
|
||||
|
||||
tags.put(TAG_INTERFACE_KEY, serviceKey);
|
||||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ServiceKeyMetric that = (ServiceKeyMetric) o;
|
||||
|
||||
if (!applicationName.equals(that.applicationName)) return false;
|
||||
return serviceKey.equals(that.serviceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = applicationName.hashCode();
|
||||
result = 31 * result + serviceKey.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServiceKeyMetric{" +
|
||||
"applicationName='" + applicationName + '\'' +
|
||||
", serviceKey='" + serviceKey + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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.metrics.registry.event;
|
||||
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsListener;
|
||||
|
||||
public class MetricsDirectoryListener implements MetricsListener<RegistryEvent.MetricsDirectoryEvent> {
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RegistryEvent.MetricsDirectoryEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(RegistryEvent.MetricsDirectoryEvent event) {
|
||||
if (!event.isAvailable()) {
|
||||
return;
|
||||
}
|
||||
if (event.getType().isIncrement()) {
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), event.getType());
|
||||
} else {
|
||||
event.getCollector().setNum(event.getType(), event.getSource().getApplicationName(), event.getSize());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* 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.metrics.registry.event;
|
||||
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsLifeListener;
|
||||
|
||||
import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_NOTIFY;
|
||||
|
||||
/**
|
||||
* The registration center actively pushes Listener, no failure and rt statistics
|
||||
*/
|
||||
public class MetricsNotifyListener implements MetricsLifeListener<RegistryEvent.MetricsNotifyEvent> {
|
||||
|
||||
protected final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(getClass());
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RegistryEvent.MetricsNotifyEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(RegistryEvent.MetricsNotifyEvent event) {
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.N_TOTAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventFinish(RegistryEvent.MetricsNotifyEvent event) {
|
||||
event.getCollector().setNum(RegistryEvent.Type.N_LAST_NUM, event.getSource().getApplicationName(), event.getLastNotifyNum());
|
||||
event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_NOTIFY, event.getTimePair().calc());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventError(RegistryEvent.MetricsNotifyEvent event) {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.metrics.registry.event;
|
||||
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsLifeListener;
|
||||
|
||||
import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_REGISTER;
|
||||
|
||||
public class MetricsRegisterListener implements MetricsLifeListener<RegistryEvent.MetricsRegisterEvent> {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RegistryEvent.MetricsRegisterEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(RegistryEvent.MetricsRegisterEvent event) {
|
||||
if (!event.isAvailable()) {
|
||||
return;
|
||||
}
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.R_TOTAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventFinish(RegistryEvent.MetricsRegisterEvent event) {
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.R_SUCCEED);
|
||||
event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_REGISTER, event.getTimePair().calc());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventError(RegistryEvent.MetricsRegisterEvent event) {
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.R_FAILED);
|
||||
event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_REGISTER, event.getTimePair().calc());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* 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.metrics.registry.event;
|
||||
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.listener.MetricsLifeListener;
|
||||
|
||||
import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_SUBSCRIBE;
|
||||
|
||||
public class MetricsSubscribeListener implements MetricsLifeListener<RegistryEvent.MetricsSubscribeEvent> {
|
||||
|
||||
@Override
|
||||
public boolean isSupport(MetricsEvent event) {
|
||||
return event instanceof RegistryEvent.MetricsSubscribeEvent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEvent(RegistryEvent.MetricsSubscribeEvent event) {
|
||||
if (!event.isAvailable()) {
|
||||
return;
|
||||
}
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.S_TOTAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventFinish(RegistryEvent.MetricsSubscribeEvent event) {
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.S_SUCCEED);
|
||||
event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_SUBSCRIBE, event.getTimePair().calc());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEventError(RegistryEvent.MetricsSubscribeEvent event) {
|
||||
event.getCollector().increment(event.getSource().getApplicationName(), RegistryEvent.Type.S_FAILED);
|
||||
event.getCollector().addRT(event.getSource().getApplicationName(), OP_TYPE_SUBSCRIBE, event.getTimePair().calc());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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.metrics.registry.event;
|
||||
|
||||
import org.apache.dubbo.metrics.event.MetricsEvent;
|
||||
import org.apache.dubbo.metrics.event.TimeCounter;
|
||||
import org.apache.dubbo.metrics.model.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Registry related events
|
||||
*/
|
||||
public class RegistryEvent extends MetricsEvent implements TimeCounter {
|
||||
private final TimePair timePair;
|
||||
private final RegistryMetricsCollector collector;
|
||||
private final boolean available;
|
||||
|
||||
public RegistryEvent(ApplicationModel applicationModel, TimePair timePair) {
|
||||
super(applicationModel);
|
||||
this.timePair = timePair;
|
||||
this.collector = applicationModel.getBeanFactory().getBean(RegistryMetricsCollector.class);
|
||||
this.available = this.collector != null && collector.isCollectEnabled();
|
||||
}
|
||||
|
||||
public ApplicationModel getSource() {
|
||||
return (ApplicationModel) source;
|
||||
}
|
||||
|
||||
public RegistryMetricsCollector getCollector() {
|
||||
return collector;
|
||||
}
|
||||
|
||||
public boolean isAvailable() {
|
||||
return available;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimePair getTimePair() {
|
||||
return timePair;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
R_TOTAL(MetricsKey.REGISTER_METRIC_REQUESTS),
|
||||
R_SUCCEED(MetricsKey.REGISTER_METRIC_REQUESTS_SUCCEED),
|
||||
R_FAILED(MetricsKey.REGISTER_METRIC_REQUESTS_FAILED),
|
||||
|
||||
S_TOTAL(MetricsKey.SUBSCRIBE_METRIC_NUM),
|
||||
S_SUCCEED(MetricsKey.SUBSCRIBE_METRIC_NUM_SUCCEED),
|
||||
S_FAILED(MetricsKey.SUBSCRIBE_METRIC_NUM_FAILED),
|
||||
|
||||
D_VALID(MetricsKey.DIRECTORY_METRIC_NUM_VALID),
|
||||
D_UN_VALID(MetricsKey.DIRECTORY_METRIC_NUM_UN_VALID),
|
||||
D_DISABLE(MetricsKey.DIRECTORY_METRIC_NUM_DISABLE),
|
||||
D_CURRENT(MetricsKey.DIRECTORY_METRIC_NUM_CURRENT, false),
|
||||
D_RECOVER_DISABLE(MetricsKey.DIRECTORY_METRIC_NUM_RECOVER_DISABLE),
|
||||
|
||||
N_TOTAL(MetricsKey.NOTIFY_METRIC_REQUESTS),
|
||||
N_LAST_NUM(MetricsKey.NOTIFY_METRIC_NUM_LAST),
|
||||
;
|
||||
|
||||
|
||||
private final MetricsKey metricsKey;
|
||||
private final boolean isIncrement;
|
||||
|
||||
|
||||
Type(MetricsKey metricsKey) {
|
||||
this(metricsKey, true);
|
||||
}
|
||||
|
||||
Type(MetricsKey metricsKey, boolean isIncrement) {
|
||||
this.metricsKey = metricsKey;
|
||||
this.isIncrement = isIncrement;
|
||||
}
|
||||
|
||||
public MetricsKey getMetricsKey() {
|
||||
return metricsKey;
|
||||
}
|
||||
|
||||
public boolean isIncrement() {
|
||||
return isIncrement;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MetricsRegisterEvent extends RegistryEvent {
|
||||
|
||||
public MetricsRegisterEvent(ApplicationModel applicationModel, TimePair timePair) {
|
||||
super(applicationModel, timePair);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MetricsSubscribeEvent extends RegistryEvent {
|
||||
|
||||
public MetricsSubscribeEvent(ApplicationModel applicationModel, TimePair timePair) {
|
||||
super(applicationModel, timePair);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class MetricsNotifyEvent extends RegistryEvent {
|
||||
|
||||
private final Map<String, Integer> lastNumMap;
|
||||
|
||||
public MetricsNotifyEvent(ApplicationModel applicationModel, TimePair timePair, Map<String, Integer> lastNumMap) {
|
||||
super(applicationModel, timePair);
|
||||
this.lastNumMap = lastNumMap;
|
||||
}
|
||||
|
||||
public Map<String, Integer> getLastNotifyNum() {
|
||||
return lastNumMap;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MetricsDirectoryEvent extends RegistryEvent {
|
||||
|
||||
private final RegistryEvent.Type type;
|
||||
private final int size;
|
||||
|
||||
public MetricsDirectoryEvent(ApplicationModel applicationModel, RegistryEvent.Type type) {
|
||||
this(applicationModel, type, 1);
|
||||
}
|
||||
|
||||
public MetricsDirectoryEvent(ApplicationModel applicationModel, RegistryEvent.Type type, int size) {
|
||||
super(applicationModel, TimePair.empty());
|
||||
this.type = type;
|
||||
this.size = size;
|
||||
}
|
||||
|
||||
public RegistryEvent.Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.metrics.registry.event;
|
||||
|
||||
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
|
||||
|
||||
public final class RegistryMetricsEventMulticaster extends SimpleMetricsEventMulticaster {
|
||||
|
||||
public RegistryMetricsEventMulticaster() {
|
||||
super.addListener(new MetricsRegisterListener());
|
||||
super.addListener(new MetricsSubscribeListener());
|
||||
super.addListener(new MetricsNotifyListener());
|
||||
super.addListener(new MetricsDirectoryListener());
|
||||
|
||||
setAvailable();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
registry-collector=org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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.metrics.registry.metrics.collector;
|
||||
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.model.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
|
||||
import static org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite.OP_TYPE_REGISTER;
|
||||
|
||||
|
||||
class RegistryMetricsCollectorTest {
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
|
||||
applicationModel = frameworkModel.newApplication();
|
||||
ApplicationConfig config = new ApplicationConfig();
|
||||
config.setName("MockMetrics");
|
||||
|
||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
||||
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
applicationModel.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPushMetrics() throws InterruptedException {
|
||||
|
||||
TimePair timePair = TimePair.start();
|
||||
GlobalMetricsEventMulticaster eventMulticaster = applicationModel.getBeanFactory().getOrRegisterBean(GlobalMetricsEventMulticaster.class);
|
||||
RegistryMetricsCollector collector = applicationModel.getBeanFactory().getOrRegisterBean(RegistryMetricsCollector.class);
|
||||
collector.setCollectEnabled(true);
|
||||
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
|
||||
List<MetricSample> metricSamples = collector.collect();
|
||||
|
||||
// push success +1
|
||||
Assertions.assertEquals(metricSamples.size(), 1);
|
||||
Assertions.assertTrue(metricSamples.get(0) instanceof GaugeMetricSample);
|
||||
|
||||
eventMulticaster.publishFinishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, timePair));
|
||||
// push finish rt +1
|
||||
metricSamples = collector.collect();
|
||||
//num(total+success) + rt(5) = 7
|
||||
Assertions.assertEquals(metricSamples.size(), 7);
|
||||
long c1 = timePair.calc();
|
||||
TimePair lastTimePair = TimePair.start();
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, lastTimePair));
|
||||
Thread.sleep(50);
|
||||
// push error rt +1
|
||||
eventMulticaster.publishErrorEvent(new RegistryEvent.MetricsRegisterEvent(applicationModel, lastTimePair));
|
||||
long c2 = lastTimePair.calc();
|
||||
metricSamples = collector.collect();
|
||||
|
||||
// num(total+success+error) + rt(5)
|
||||
Assertions.assertEquals(metricSamples.size(), 8);
|
||||
|
||||
// calc rt
|
||||
for (MetricSample sample : metricSamples) {
|
||||
Map<String, String> tags = sample.getTags();
|
||||
Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationModel.getApplicationName());
|
||||
}
|
||||
Map<String, Long> sampleMap = metricSamples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
|
||||
Number number = ((GaugeMetricSample) k).getSupplier().get();
|
||||
return number.longValue();
|
||||
}));
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_LAST).targetKey()), lastTimePair.calc());
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MIN).targetKey()), Math.min(c1, c2));
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MAX).targetKey()), Math.max(c1, c2));
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_AVG).targetKey()), (c1 + c2) / 2);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_SUM).targetKey()), c1 + c2);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.metrics.registry.metrics.collector;
|
||||
|
||||
import org.apache.dubbo.config.ApplicationConfig;
|
||||
import org.apache.dubbo.metrics.model.MetricsKey;
|
||||
import org.apache.dubbo.metrics.model.MetricsKeyWrapper;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.apache.dubbo.metrics.registry.collector.RegistryMetricsCollector;
|
||||
import org.apache.dubbo.metrics.registry.collector.stat.RegistryStatComposite;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.FrameworkModel;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
|
||||
|
||||
class RegistryMetricsSampleTest {
|
||||
|
||||
private ApplicationModel applicationModel;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
FrameworkModel frameworkModel = FrameworkModel.defaultModel();
|
||||
applicationModel = frameworkModel.newApplication();
|
||||
ApplicationConfig config = new ApplicationConfig();
|
||||
config.setName("MockMetrics");
|
||||
applicationModel.getApplicationConfigManager().setApplication(config);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
applicationModel.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRegisterMetrics() {
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRTMetrics() {
|
||||
RegistryMetricsCollector collector = new RegistryMetricsCollector(applicationModel);
|
||||
collector.setCollectEnabled(true);
|
||||
String applicationName = applicationModel.getApplicationName();
|
||||
collector.addRT(applicationName, RegistryStatComposite.OP_TYPE_REGISTER, 10L);
|
||||
collector.addRT(applicationName, RegistryStatComposite.OP_TYPE_REGISTER, 0L);
|
||||
|
||||
List<MetricSample> samples = collector.collect();
|
||||
for (MetricSample sample : samples) {
|
||||
Map<String, String> tags = sample.getTags();
|
||||
Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationName);
|
||||
}
|
||||
|
||||
Map<String, Long> sampleMap = samples.stream().collect(Collectors.toMap(MetricSample::getName, k -> {
|
||||
Number number = ((GaugeMetricSample) k).getSupplier().get();
|
||||
return number.longValue();
|
||||
}));
|
||||
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_LAST).targetKey()), 0L);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MIN).targetKey()), 0L);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_MAX).targetKey()), 10L);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_AVG).targetKey()), 5L);
|
||||
Assertions.assertEquals(sampleMap.get(new MetricsKeyWrapper(RegistryStatComposite.OP_TYPE_REGISTER, MetricsKey.GENERIC_METRIC_RT_SUM).targetKey()), 10L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testListener() {
|
||||
RegistryMetricsCollector collector = new RegistryMetricsCollector(applicationModel);
|
||||
collector.setCollectEnabled(true);
|
||||
String applicationName = applicationModel.getApplicationName();
|
||||
collector.increment(applicationName,RegistryEvent.Type.R_TOTAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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.metrics.registry.metrics.model;
|
||||
|
||||
import org.apache.dubbo.metrics.model.MethodMetric;
|
||||
import org.apache.dubbo.rpc.RpcInvocation;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_APPLICATION_NAME;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_GROUP_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_HOSTNAME;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_INTERFACE_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_IP;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_METHOD_KEY;
|
||||
import static org.apache.dubbo.common.constants.MetricsConstants.TAG_VERSION_KEY;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
|
||||
import static org.apache.dubbo.common.utils.NetUtils.getLocalHostName;
|
||||
|
||||
class MethodMetricTest {
|
||||
|
||||
private static final String applicationName = null;
|
||||
private static String interfaceName;
|
||||
private static String methodName;
|
||||
private static String group;
|
||||
private static String version;
|
||||
private static RpcInvocation invocation;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
interfaceName = "org.apache.dubbo.MockInterface";
|
||||
methodName = "mockMethod";
|
||||
group = "mockGroup";
|
||||
version = "1.0.0";
|
||||
invocation = new RpcInvocation(methodName, interfaceName, "serviceKey", null, null);
|
||||
invocation.setTargetServiceUniqueName(group + "/" + interfaceName + ":" + version);
|
||||
invocation.setAttachment(GROUP_KEY, group);
|
||||
invocation.setAttachment(VERSION_KEY, version);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
MethodMetric metric = new MethodMetric(applicationName, invocation);
|
||||
Assertions.assertEquals(metric.getInterfaceName(), interfaceName);
|
||||
Assertions.assertEquals(metric.getMethodName(), methodName);
|
||||
Assertions.assertEquals(metric.getGroup(), group);
|
||||
Assertions.assertEquals(metric.getVersion(), version);
|
||||
|
||||
Map<String, String> tags = metric.getTags();
|
||||
Assertions.assertEquals(tags.get(TAG_IP), getLocalHost());
|
||||
Assertions.assertEquals(tags.get(TAG_HOSTNAME), getLocalHostName());
|
||||
Assertions.assertEquals(tags.get(TAG_APPLICATION_NAME), applicationName);
|
||||
|
||||
Assertions.assertEquals(tags.get(TAG_INTERFACE_KEY), interfaceName);
|
||||
Assertions.assertEquals(tags.get(TAG_METHOD_KEY), methodName);
|
||||
Assertions.assertEquals(tags.get(TAG_GROUP_KEY), group);
|
||||
Assertions.assertEquals(tags.get(TAG_VERSION_KEY), version);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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.metrics.registry.metrics.model.sample;
|
||||
|
||||
import org.apache.dubbo.metrics.model.MetricsCategory;
|
||||
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
|
||||
import org.apache.dubbo.metrics.model.sample.MetricSample;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
class GaugeMetricSampleTest {
|
||||
|
||||
private static String name;
|
||||
private static String description;
|
||||
private static Map<String, String> tags;
|
||||
private static MetricsCategory category;
|
||||
private static String baseUnit;
|
||||
private static Supplier<Number> supplier;
|
||||
|
||||
@BeforeAll
|
||||
public static void setup() {
|
||||
name = "test";
|
||||
description = "test";
|
||||
tags = new HashMap<>();
|
||||
category = MetricsCategory.REQUESTS;
|
||||
baseUnit = "byte";
|
||||
supplier = () -> 1;
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
GaugeMetricSample sample = new GaugeMetricSample(name, description, tags, category, baseUnit, supplier);
|
||||
Assertions.assertEquals(sample.getName(), name);
|
||||
Assertions.assertEquals(sample.getDescription(), description);
|
||||
Assertions.assertEquals(sample.getTags(), tags);
|
||||
Assertions.assertEquals(sample.getType(), MetricSample.Type.GAUGE);
|
||||
Assertions.assertEquals(sample.getCategory(), category);
|
||||
Assertions.assertEquals(sample.getBaseUnit(), baseUnit);
|
||||
Assertions.assertEquals(sample.getSupplier().get(), 1);
|
||||
sample.setSupplier(() -> 2);
|
||||
Assertions.assertEquals(sample.getSupplier().get(), 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
<modules>
|
||||
<module>dubbo-metrics-api</module>
|
||||
<module>dubbo-metrics-default</module>
|
||||
<module>dubbo-metrics-registry</module>
|
||||
<module>dubbo-metrics-metadata</module>
|
||||
<module>dubbo-metrics-prometheus</module>
|
||||
</modules>
|
||||
|
|
|
|||
|
|
@ -98,5 +98,12 @@
|
|||
<version>${project.parent.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-registry</artifactId>
|
||||
<version>${project.parent.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -16,6 +16,32 @@
|
|||
*/
|
||||
package org.apache.dubbo.registry.client.event.listener;
|
||||
|
||||
import org.apache.dubbo.common.ProtocolServiceKey;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.URLBuilder;
|
||||
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||
import org.apache.dubbo.metadata.MetadataInfo;
|
||||
import org.apache.dubbo.metadata.MetadataInfo.ServiceInfo;
|
||||
import org.apache.dubbo.metrics.event.SimpleMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.registry.NotifyListener;
|
||||
import org.apache.dubbo.registry.client.DefaultServiceInstance;
|
||||
import org.apache.dubbo.registry.client.ServiceDiscovery;
|
||||
import org.apache.dubbo.registry.client.ServiceInstance;
|
||||
import org.apache.dubbo.registry.client.event.RetryServiceInstancesChangedEvent;
|
||||
import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
|
||||
import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
|
||||
import org.apache.dubbo.registry.client.metadata.ServiceInstanceNotificationCustomizer;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -32,28 +58,6 @@ import java.util.concurrent.Semaphore;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.apache.dubbo.common.ProtocolServiceKey;
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.URLBuilder;
|
||||
import org.apache.dubbo.common.constants.CommonConstants;
|
||||
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
|
||||
import org.apache.dubbo.common.logger.LoggerFactory;
|
||||
import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
|
||||
import org.apache.dubbo.common.utils.CollectionUtils;
|
||||
import org.apache.dubbo.common.utils.ConcurrentHashSet;
|
||||
import org.apache.dubbo.metadata.MetadataInfo;
|
||||
import org.apache.dubbo.metadata.MetadataInfo.ServiceInfo;
|
||||
import org.apache.dubbo.registry.NotifyListener;
|
||||
import org.apache.dubbo.registry.client.DefaultServiceInstance;
|
||||
import org.apache.dubbo.registry.client.ServiceDiscovery;
|
||||
import org.apache.dubbo.registry.client.ServiceInstance;
|
||||
import org.apache.dubbo.registry.client.event.RetryServiceInstancesChangedEvent;
|
||||
import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
|
||||
import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
|
||||
import org.apache.dubbo.registry.client.metadata.ServiceInstanceNotificationCustomizer;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.ScopeModelUtil;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
|
||||
import static org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_FAILED_REFRESH_ADDRESS;
|
||||
|
|
@ -87,6 +91,7 @@ public class ServiceInstancesChangedListener {
|
|||
private final ScheduledExecutorService scheduler;
|
||||
private volatile boolean hasEmptyMetadata;
|
||||
private final Set<ServiceInstanceNotificationCustomizer> serviceInstanceNotificationCustomizers;
|
||||
private final ApplicationModel applicationModel;
|
||||
|
||||
|
||||
public ServiceInstancesChangedListener(Set<String> serviceNames, ServiceDiscovery serviceDiscovery) {
|
||||
|
|
@ -99,6 +104,7 @@ public class ServiceInstancesChangedListener {
|
|||
ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(serviceDiscovery == null || serviceDiscovery.getUrl() == null ? null : serviceDiscovery.getUrl().getScopeModel());
|
||||
this.scheduler = applicationModel.getBeanFactory().getBean(FrameworkExecutorRepository.class).getMetadataRetryExecutor();
|
||||
this.serviceInstanceNotificationCustomizers = applicationModel.getExtensionLoader(ServiceInstanceNotificationCustomizer.class).getSupportedExtensionInstances();
|
||||
this.applicationModel = applicationModel;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -398,6 +404,13 @@ public class ServiceInstancesChangedListener {
|
|||
* race condition is protected by onEvent/doOnEvent
|
||||
*/
|
||||
protected void notifyAddressChanged() {
|
||||
|
||||
ScopeBeanFactory beanFactory = applicationModel.getFrameworkModel().getBeanFactory();
|
||||
SimpleMetricsEventMulticaster eventMulticaster = beanFactory.getOrRegisterBean(SimpleMetricsEventMulticaster.class);
|
||||
|
||||
TimePair timePair = TimePair.start();
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsNotifyEvent(applicationModel, timePair, null));
|
||||
Map<String, Integer> lastNumMap = new HashMap<>();
|
||||
// 1 different services
|
||||
listeners.forEach((serviceKey, listenerSet) -> {
|
||||
// 2 multiple subscription listener of the same service
|
||||
|
|
@ -407,8 +420,11 @@ public class ServiceInstancesChangedListener {
|
|||
List<URL> urls = toUrlsWithEmpty(getAddresses(listenerWithKey.getProtocolServiceKey(), notifyListener.getConsumerUrl()));
|
||||
logger.info("Notify service " + listenerWithKey.getProtocolServiceKey() + " with urls " + urls.size());
|
||||
notifyListener.notify(urls);
|
||||
lastNumMap.put(serviceKey, urls.size());
|
||||
}
|
||||
});
|
||||
eventMulticaster.publishFinishEvent(new RegistryEvent.MetricsNotifyEvent(applicationModel, timePair, lastNumMap));
|
||||
|
||||
}
|
||||
|
||||
protected List<URL> toUrlsWithEmpty(List<URL> urls) {
|
||||
|
|
|
|||
|
|
@ -16,19 +16,6 @@
|
|||
*/
|
||||
package org.apache.dubbo.registry.integration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.dubbo.common.URL;
|
||||
import org.apache.dubbo.common.URLBuilder;
|
||||
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
|
||||
|
|
@ -43,6 +30,9 @@ import org.apache.dubbo.common.utils.CollectionUtils;
|
|||
import org.apache.dubbo.common.utils.NetUtils;
|
||||
import org.apache.dubbo.common.utils.StringUtils;
|
||||
import org.apache.dubbo.common.utils.UrlUtils;
|
||||
import org.apache.dubbo.metrics.event.GlobalMetricsEventMulticaster;
|
||||
import org.apache.dubbo.metrics.model.TimePair;
|
||||
import org.apache.dubbo.metrics.registry.event.RegistryEvent;
|
||||
import org.apache.dubbo.registry.AddressListener;
|
||||
import org.apache.dubbo.remoting.Constants;
|
||||
import org.apache.dubbo.rpc.Invoker;
|
||||
|
|
@ -53,8 +43,22 @@ import org.apache.dubbo.rpc.cluster.Router;
|
|||
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
|
||||
import org.apache.dubbo.rpc.cluster.router.state.BitList;
|
||||
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
|
||||
import org.apache.dubbo.rpc.model.ApplicationModel;
|
||||
import org.apache.dubbo.rpc.model.ModuleModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DISABLED_KEY;
|
||||
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
|
||||
|
|
@ -110,11 +114,18 @@ public class RegistryDirectory<T> extends DynamicDirectory<T> {
|
|||
super(serviceType, url);
|
||||
moduleModel = getModuleModel(url.getScopeModel());
|
||||
consumerConfigurationListener = getConsumerConfigurationListener(moduleModel);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void subscribe(URL url) {
|
||||
ApplicationModel applicationModel = url.getApplicationModel();
|
||||
GlobalMetricsEventMulticaster eventMulticaster = applicationModel.getBeanFactory().getBean(GlobalMetricsEventMulticaster.class);
|
||||
TimePair timePair = TimePair.start();
|
||||
|
||||
eventMulticaster.publishEvent(new RegistryEvent.MetricsSubscribeEvent(applicationModel, timePair));
|
||||
super.subscribe(url);
|
||||
eventMulticaster.publishFinishEvent(new RegistryEvent.MetricsSubscribeEvent(applicationModel, timePair));
|
||||
if (moduleModel.getModelEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
|
||||
consumerConfigurationListener.addNotifyListener(this);
|
||||
referenceConfigurationListener = new ReferenceConfigurationListener(moduleModel, this, url);
|
||||
|
|
@ -233,7 +244,7 @@ public class RegistryDirectory<T> extends DynamicDirectory<T> {
|
|||
// use local reference to avoid NPE as this.cachedInvokerUrls will be set null by destroyAllInvokers().
|
||||
Set<URL> localCachedInvokerUrls = this.cachedInvokerUrls;
|
||||
if (invokerUrls.isEmpty()) {
|
||||
if(CollectionUtils.isNotEmpty(localCachedInvokerUrls)){
|
||||
if (CollectionUtils.isNotEmpty(localCachedInvokerUrls)) {
|
||||
// 1-4 Empty address.
|
||||
logger.warn(REGISTRY_EMPTY_ADDRESS, "configuration ", "",
|
||||
"Service" + serviceKey + " received empty address list with no EMPTY protocol set, trigger empty protection.");
|
||||
|
|
|
|||
|
|
@ -148,6 +148,11 @@
|
|||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-default</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-registry</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.dubbo</groupId>
|
||||
<artifactId>dubbo-metrics-metadata</artifactId>
|
||||
|
|
|
|||
Loading…
Reference in New Issue