init
This commit is contained in:
		
							
								
								
									
										27
									
								
								sentinel/sentinel-extension/sentinel-metric-exporter/pom.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								sentinel/sentinel-extension/sentinel-metric-exporter/pom.xml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
<?xml version="1.0" encoding="UTF-8"?>
 | 
			
		||||
<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/xsd/maven-4.0.0.xsd">
 | 
			
		||||
    <parent>
 | 
			
		||||
        <artifactId>sentinel-extension</artifactId>
 | 
			
		||||
        <groupId>com.alibaba.csp</groupId>
 | 
			
		||||
        <version>1.8.3</version>
 | 
			
		||||
    </parent>
 | 
			
		||||
    <modelVersion>4.0.0</modelVersion>
 | 
			
		||||
    
 | 
			
		||||
    <artifactId>sentinel-metric-exporter</artifactId>
 | 
			
		||||
    <packaging>jar</packaging>
 | 
			
		||||
    
 | 
			
		||||
    <dependencies>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>com.alibaba.csp</groupId>
 | 
			
		||||
            <artifactId>sentinel-core</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
    
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>junit</groupId>
 | 
			
		||||
            <artifactId>junit</artifactId>
 | 
			
		||||
            <scope>test</scope>
 | 
			
		||||
        </dependency>
 | 
			
		||||
    </dependencies>
 | 
			
		||||
</project>
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.csp.sentinel.init.InitFunc;
 | 
			
		||||
import com.alibaba.csp.sentinel.log.RecordLog;
 | 
			
		||||
import com.alibaba.csp.sentinel.metric.collector.MetricCollector;
 | 
			
		||||
import com.alibaba.csp.sentinel.metric.exporter.MetricExporter;
 | 
			
		||||
import com.alibaba.csp.sentinel.metric.exporter.jmx.JMXMetricExporter;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The{@link MetricExporterInit} work on load Metric exporters.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 19:58
 | 
			
		||||
 * @since 1.8.3
 | 
			
		||||
 */
 | 
			
		||||
public class MetricExporterInit implements InitFunc {
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * the list of metric exporters.
 | 
			
		||||
     */
 | 
			
		||||
    private static List<MetricExporter> metricExporters = new ArrayList<>();
 | 
			
		||||
    
 | 
			
		||||
    /*
 | 
			
		||||
      load metric exporters.
 | 
			
		||||
     */
 | 
			
		||||
    static {
 | 
			
		||||
        // now we use this simple way to load MetricExporter.
 | 
			
		||||
        metricExporters.add(new JMXMetricExporter());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public void init() throws Exception {
 | 
			
		||||
        RecordLog.info("[MetricExporterInit] MetricExporter start init.");
 | 
			
		||||
        // start the metric exporters.
 | 
			
		||||
        for (MetricExporter metricExporter : metricExporters) {
 | 
			
		||||
           try {
 | 
			
		||||
               metricExporter.start();
 | 
			
		||||
           } catch (Exception e) {
 | 
			
		||||
               RecordLog.warn("[MetricExporterInit] MetricExporterInit start the metricExport[{}] failed, will ignore it.",
 | 
			
		||||
                       metricExporter.getClass().getName(), e);
 | 
			
		||||
           }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        // add shutdown hook.
 | 
			
		||||
        Runtime.getRuntime().addShutdownHook(new Thread(
 | 
			
		||||
                () -> metricExporters.forEach(metricExporter -> {
 | 
			
		||||
                    try {
 | 
			
		||||
                        metricExporter.shutdown();
 | 
			
		||||
                    } catch (Exception e) {
 | 
			
		||||
                        RecordLog.warn("[MetricExporterInit] MetricExporterInit shutdown the metricExport[{}] failed, will ignore it.",
 | 
			
		||||
                                metricExporter.getClass().getName(), e);
 | 
			
		||||
                    }
 | 
			
		||||
                })
 | 
			
		||||
        ));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,94 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric.collector;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.csp.sentinel.Constants;
 | 
			
		||||
import com.alibaba.csp.sentinel.node.ClusterNode;
 | 
			
		||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
 | 
			
		||||
import com.alibaba.csp.sentinel.slotchain.ResourceWrapper;
 | 
			
		||||
import com.alibaba.csp.sentinel.slots.clusterbuilder.ClusterBuilderSlot;
 | 
			
		||||
import com.alibaba.csp.sentinel.util.TimeUtil;
 | 
			
		||||
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The {@link MetricCollector} work on collecting metrics in {@link MetricNode}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 20:01
 | 
			
		||||
 * @since 1.8.3
 | 
			
		||||
 */
 | 
			
		||||
public class MetricCollector {
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * collect the metrics in {@link MetricNode}.
 | 
			
		||||
     *
 | 
			
		||||
     * @return the metric grouped by resource name.
 | 
			
		||||
     */
 | 
			
		||||
    public Map<String, MetricNode> collectMetric() {
 | 
			
		||||
        final long currentTime = TimeUtil.currentTimeMillis();
 | 
			
		||||
        final long maxTime = currentTime - currentTime % 1000;
 | 
			
		||||
        final long minTime = maxTime - 1000;
 | 
			
		||||
        Map<String, MetricNode> metricNodeMap = new HashMap<>();
 | 
			
		||||
        for (Map.Entry<ResourceWrapper, ClusterNode> e : ClusterBuilderSlot.getClusterNodeMap().entrySet()) {
 | 
			
		||||
            ClusterNode node = e.getValue();
 | 
			
		||||
            List<MetricNode> metrics = getLastMetrics(node, minTime, maxTime);
 | 
			
		||||
            aggregate(metricNodeMap, metrics, node);
 | 
			
		||||
        }
 | 
			
		||||
        aggregate(metricNodeMap, getLastMetrics(Constants.ENTRY_NODE, minTime, maxTime), Constants.ENTRY_NODE);
 | 
			
		||||
        return metricNodeMap;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the last second {@link MetricNode} of {@link ClusterNode}
 | 
			
		||||
     * @param node {@link ClusterNode}
 | 
			
		||||
     * @param minTime the min time.
 | 
			
		||||
     * @param maxTime the max time.
 | 
			
		||||
     * @return the list of {@link MetricNode}
 | 
			
		||||
     */
 | 
			
		||||
    private List<MetricNode> getLastMetrics(ClusterNode node, long minTime, long maxTime) {
 | 
			
		||||
        return node.rawMetricsInMin(time -> time >= minTime && time < maxTime);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * aggregate the metrics, the metrics under the same resource will left the lasted value
 | 
			
		||||
     * @param metricNodeMap metrics map
 | 
			
		||||
     * @param metrics metrics info group by timestamp
 | 
			
		||||
     * @param node the node
 | 
			
		||||
     */
 | 
			
		||||
    private void aggregate(Map<String, MetricNode> metricNodeMap, List<MetricNode> metrics, ClusterNode node) {
 | 
			
		||||
        if (metrics == null || metrics.size() == 0) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        for (MetricNode metricNode : metrics) {
 | 
			
		||||
            String resource = node.getName();
 | 
			
		||||
            metricNode.setResource(resource);
 | 
			
		||||
            metricNode.setClassification(node.getResourceType());
 | 
			
		||||
            MetricNode existMetricNode = metricNodeMap.get(resource);
 | 
			
		||||
            // always keep the MetricNode is the last
 | 
			
		||||
            if (existMetricNode != null && existMetricNode.getTimestamp() > metricNode.getTimestamp()) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            metricNodeMap.put(resource, metricNode);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,49 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link MetricExporter} work on export metric to target monitor.
 | 
			
		||||
 * you can implement your export ways by this class.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 21:16
 | 
			
		||||
 */
 | 
			
		||||
public interface MetricExporter {
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * start the {@link MetricExporter}.
 | 
			
		||||
     *
 | 
			
		||||
     * @throws Exception start exception.
 | 
			
		||||
     */
 | 
			
		||||
    void start() throws Exception;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * export the data to target monitor by the implement.
 | 
			
		||||
     *
 | 
			
		||||
     * @throws Exception export exception.
 | 
			
		||||
     */
 | 
			
		||||
    void export() throws Exception;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * shutdown the {@link MetricExporter}.
 | 
			
		||||
     *
 | 
			
		||||
     * @throws Exception shutdown exception.
 | 
			
		||||
     */
 | 
			
		||||
    void shutdown() throws Exception;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,88 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.csp.sentinel.concurrent.NamedThreadFactory;
 | 
			
		||||
import com.alibaba.csp.sentinel.log.RecordLog;
 | 
			
		||||
import com.alibaba.csp.sentinel.metric.collector.MetricCollector;
 | 
			
		||||
import com.alibaba.csp.sentinel.metric.exporter.MetricExporter;
 | 
			
		||||
 | 
			
		||||
import java.util.concurrent.ScheduledExecutorService;
 | 
			
		||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
 | 
			
		||||
import java.util.concurrent.TimeUnit;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * The JMX metric exporter, mainly for write metric datas to JMX bean. It implement {@link MetricExporter}, provide method
 | 
			
		||||
 * start, export and shutdown. The mainly design for the jmx is refresh the JMX bean data scheduled.
 | 
			
		||||
 * {@link JMXExportTask} work on export data to {@link MetricBean}.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 20:02
 | 
			
		||||
 * @since 1.8.3
 | 
			
		||||
 */
 | 
			
		||||
public class JMXMetricExporter implements MetricExporter {
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * schedule executor.
 | 
			
		||||
     */
 | 
			
		||||
    private final ScheduledExecutorService jmxExporterSchedule;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * JMX metric writer, write metric datas to {@link MetricBean}.
 | 
			
		||||
     */
 | 
			
		||||
    private final MetricBeanWriter metricBeanWriter = new MetricBeanWriter();
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * global metrics collector.
 | 
			
		||||
     */
 | 
			
		||||
    private final MetricCollector metricCollector = new MetricCollector();
 | 
			
		||||
    
 | 
			
		||||
    public JMXMetricExporter() {
 | 
			
		||||
        jmxExporterSchedule = new ScheduledThreadPoolExecutor(1, new NamedThreadFactory("sentinel-metrics-jmx-exporter-task", true));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public void start() throws Exception {
 | 
			
		||||
        jmxExporterSchedule.scheduleAtFixedRate(new JMXExportTask(), 1, 1, TimeUnit.SECONDS);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public void export() throws Exception {
 | 
			
		||||
        metricBeanWriter.write(metricCollector.collectMetric());
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public void shutdown() throws Exception {
 | 
			
		||||
        jmxExporterSchedule.shutdown();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * JMXExportTask mainly work on execute the JMX metric export.
 | 
			
		||||
     */
 | 
			
		||||
    class JMXExportTask implements Runnable {
 | 
			
		||||
        
 | 
			
		||||
        @Override
 | 
			
		||||
        public void run() {
 | 
			
		||||
            try {
 | 
			
		||||
                export();
 | 
			
		||||
            } catch (Exception e) {
 | 
			
		||||
                RecordLog.warn("[JMX Metric Exporter] export to JMX MetricBean failed.", e);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,121 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.csp.sentinel.log.RecordLog;
 | 
			
		||||
 | 
			
		||||
import javax.management.JMException;
 | 
			
		||||
import javax.management.MBeanServer;
 | 
			
		||||
import javax.management.MBeanServerFactory;
 | 
			
		||||
import javax.management.ObjectName;
 | 
			
		||||
import java.lang.management.ManagementFactory;
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.concurrent.ConcurrentHashMap;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This class provides a unified interface for registering/unregistering of Metric MBean.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 20:02
 | 
			
		||||
 * @since 1.8.3
 | 
			
		||||
 */
 | 
			
		||||
public class MBeanRegistry {
 | 
			
		||||
    
 | 
			
		||||
    private static volatile MBeanRegistry instance = new MBeanRegistry();
 | 
			
		||||
    
 | 
			
		||||
    private Map<MetricBean, String> mapBean2Name= new ConcurrentHashMap<>(8);
 | 
			
		||||
    
 | 
			
		||||
    private Map<String, MetricBean> mapName2Bean = new ConcurrentHashMap<>(8);
 | 
			
		||||
    
 | 
			
		||||
    private MBeanServer mBeanServer;
 | 
			
		||||
    
 | 
			
		||||
    public static MBeanRegistry getInstance() {
 | 
			
		||||
        return instance;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    public MBeanRegistry() {
 | 
			
		||||
        try {
 | 
			
		||||
            mBeanServer = ManagementFactory.getPlatformMBeanServer();
 | 
			
		||||
        } catch (Error e) {
 | 
			
		||||
            // Account for running within IKVM and create a new MBeanServer
 | 
			
		||||
            // if the PlatformMBeanServer does not exist.
 | 
			
		||||
            mBeanServer =  MBeanServerFactory.createMBeanServer();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Registers a new MBean with the platform MBean server.
 | 
			
		||||
     * @param bean the bean being registered
 | 
			
		||||
     * @param mBeanName the mBeanName
 | 
			
		||||
     * @throws JMException MBean can not register exception
 | 
			
		||||
     */
 | 
			
		||||
    public void register(MetricBean bean, String mBeanName) throws JMException {
 | 
			
		||||
        assert bean != null;
 | 
			
		||||
        try {
 | 
			
		||||
            ObjectName oname = new ObjectName(mBeanName);
 | 
			
		||||
            mBeanServer.registerMBean(bean, oname);
 | 
			
		||||
            mapBean2Name.put(bean, mBeanName);
 | 
			
		||||
            mapName2Bean.put(mBeanName, bean);
 | 
			
		||||
        } catch (JMException e) {
 | 
			
		||||
            RecordLog.warn("[MBeanRegistry] Failed to register MBean " + mBeanName, e);
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * unregister the MetricBean
 | 
			
		||||
     * @param bean MetricBean
 | 
			
		||||
     */
 | 
			
		||||
    public void unRegister(MetricBean bean) {
 | 
			
		||||
        assert bean != null;
 | 
			
		||||
        String beanName = mapBean2Name.get(bean);
 | 
			
		||||
        if (beanName == null) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        try {
 | 
			
		||||
            ObjectName objectName = new ObjectName(beanName);
 | 
			
		||||
            mBeanServer.unregisterMBean(objectName);
 | 
			
		||||
            mapBean2Name.remove(bean);
 | 
			
		||||
            mapName2Bean.remove(beanName);
 | 
			
		||||
        } catch (JMException e) {
 | 
			
		||||
            RecordLog.warn("[MBeanRegistry] UnRegister the MetricBean fail", e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * find the MBean by BeanName
 | 
			
		||||
     * @param mBeanName mBeanName
 | 
			
		||||
     * @return MetricMBean
 | 
			
		||||
     */
 | 
			
		||||
    public MetricBean findMBean(String mBeanName) {
 | 
			
		||||
        if (mBeanName == null) {
 | 
			
		||||
            return null;
 | 
			
		||||
        }
 | 
			
		||||
        return mapName2Bean.get(mBeanName);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * list all MBeans which is registered into MBeanRegistry
 | 
			
		||||
     * @return MetricBeans
 | 
			
		||||
     */
 | 
			
		||||
    public List<MetricBean> listAllMBeans() {
 | 
			
		||||
        return new ArrayList<>(mapName2Bean.values());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,154 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * the MetricBean for JMX expose.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 20:02
 | 
			
		||||
 * @since 1.8.3
 | 
			
		||||
 */
 | 
			
		||||
public class MetricBean implements MetricMXBean {
 | 
			
		||||
    
 | 
			
		||||
    private String resource;
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * Resource classification (e.g. SQL or RPC)
 | 
			
		||||
     */
 | 
			
		||||
    private int classification;
 | 
			
		||||
    
 | 
			
		||||
    private long timestamp;
 | 
			
		||||
    
 | 
			
		||||
    private long passQps;
 | 
			
		||||
    
 | 
			
		||||
    private long blockQps;
 | 
			
		||||
    
 | 
			
		||||
    private long successQps;
 | 
			
		||||
    
 | 
			
		||||
    private long exceptionQps;
 | 
			
		||||
    
 | 
			
		||||
    private long rt;
 | 
			
		||||
    
 | 
			
		||||
    private long occupiedPassQps;
 | 
			
		||||
 | 
			
		||||
    private int concurrency;
 | 
			
		||||
 | 
			
		||||
    private long version;
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public String getResource() {
 | 
			
		||||
        return resource;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getClassification() {
 | 
			
		||||
        return classification;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getTimestamp() {
 | 
			
		||||
        return timestamp;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getPassQps() {
 | 
			
		||||
        return passQps;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getBlockQps() {
 | 
			
		||||
        return blockQps;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getSuccessQps() {
 | 
			
		||||
        return successQps;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getExceptionQps() {
 | 
			
		||||
        return exceptionQps;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getRt() {
 | 
			
		||||
        return rt;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getOccupiedPassQps() {
 | 
			
		||||
        return occupiedPassQps;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getConcurrency() {
 | 
			
		||||
        return concurrency;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public long getVersion() {
 | 
			
		||||
        return version;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * set the version to current Mbean.
 | 
			
		||||
     *
 | 
			
		||||
     * @param version current version.
 | 
			
		||||
     */
 | 
			
		||||
    public void setVersion(long version) {
 | 
			
		||||
        this.version = version;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * reset the MBean value to the initialized value.
 | 
			
		||||
     */
 | 
			
		||||
    public void reset() {
 | 
			
		||||
        this.blockQps = 0;
 | 
			
		||||
        this.passQps = 0;
 | 
			
		||||
        this.timestamp = System.currentTimeMillis();
 | 
			
		||||
        this.exceptionQps = 0;
 | 
			
		||||
        this.occupiedPassQps = 0;
 | 
			
		||||
        this.successQps = 0;
 | 
			
		||||
        this.rt = 0;
 | 
			
		||||
        this.concurrency = 0;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * set the MetricBean's value which from MetricNode.
 | 
			
		||||
     *
 | 
			
		||||
     * @param metricNode metric Node for write file
 | 
			
		||||
     */
 | 
			
		||||
    public void setValueFromNode(MetricNode metricNode) {
 | 
			
		||||
        if (metricNode == null) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this.successQps = metricNode.getSuccessQps();
 | 
			
		||||
        this.blockQps = metricNode.getBlockQps();
 | 
			
		||||
        this.passQps = metricNode.getPassQps();
 | 
			
		||||
        this.occupiedPassQps = metricNode.getOccupiedPassQps();
 | 
			
		||||
        this.exceptionQps = metricNode.getExceptionQps();
 | 
			
		||||
        this.timestamp = metricNode.getTimestamp();
 | 
			
		||||
        this.classification = metricNode.getClassification();
 | 
			
		||||
        this.concurrency = metricNode.getConcurrency();
 | 
			
		||||
        this.resource = metricNode.getResource();
 | 
			
		||||
        this.rt = metricNode.getRt();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,97 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.csp.sentinel.config.SentinelConfig;
 | 
			
		||||
import com.alibaba.csp.sentinel.log.RecordLog;
 | 
			
		||||
import com.alibaba.csp.sentinel.node.metric.MetricNode;
 | 
			
		||||
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.Objects;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * the metric bean writer, it provides {@link MetricBeanWriter#write} method for register the
 | 
			
		||||
 * MetricBean in {@link MBeanRegistry} or update the value of MetricBean
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 20:02
 | 
			
		||||
 * @since 1.8.3
 | 
			
		||||
 */
 | 
			
		||||
public class MetricBeanWriter {
 | 
			
		||||
    
 | 
			
		||||
    private final MBeanRegistry mBeanRegistry = MBeanRegistry.getInstance();
 | 
			
		||||
    
 | 
			
		||||
    private static final String DEFAULT_APP_NAME = "sentinel-application";
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
     * write the MetricNode value to MetricBean
 | 
			
		||||
     * if the MetricBean is not registered into {@link MBeanRegistry},
 | 
			
		||||
     * it will be created and registered into {@link MBeanRegistry}.
 | 
			
		||||
     * else it will update the value of MetricBean.
 | 
			
		||||
     * Notes. if the MetricNode is null, then {@link MetricBean} will be reset.
 | 
			
		||||
     * @param map metricNode value group by resource
 | 
			
		||||
     * @throws Exception write failed exception
 | 
			
		||||
     */
 | 
			
		||||
    public synchronized void write(Map<String, MetricNode> map) throws Exception {
 | 
			
		||||
        if (map == null || map.isEmpty()) {
 | 
			
		||||
            List<MetricBean> metricNodes = mBeanRegistry.listAllMBeans();
 | 
			
		||||
            if (metricNodes == null || metricNodes.isEmpty()) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            for (MetricBean metricNode : metricNodes) {
 | 
			
		||||
                metricNode.reset();
 | 
			
		||||
            }
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        String appName = SentinelConfig.getAppName();
 | 
			
		||||
        if (appName == null) {
 | 
			
		||||
            appName = DEFAULT_APP_NAME;
 | 
			
		||||
        }
 | 
			
		||||
        long version = System.currentTimeMillis();
 | 
			
		||||
        // set or update the new value
 | 
			
		||||
        for (MetricNode metricNode : map.values()) {
 | 
			
		||||
            final String mBeanName = "Sentinel:type=" + appName + ",name=\"" + metricNode.getResource()
 | 
			
		||||
                    +"\",classification=\"" + metricNode.getClassification() +"\"";
 | 
			
		||||
            MetricBean metricBean = mBeanRegistry.findMBean(mBeanName);
 | 
			
		||||
            if (metricBean != null) {
 | 
			
		||||
                metricBean.setValueFromNode(metricNode);
 | 
			
		||||
                metricBean.setVersion(version);
 | 
			
		||||
            } else {
 | 
			
		||||
                metricBean = new MetricBean();
 | 
			
		||||
                metricBean.setValueFromNode(metricNode);
 | 
			
		||||
                metricBean.setVersion(version);
 | 
			
		||||
                mBeanRegistry.register(metricBean, mBeanName);
 | 
			
		||||
                RecordLog.info("[MetricBeanWriter] Registering with JMX as Metric MBean [{}]", mBeanName);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // reset the old value
 | 
			
		||||
        List<MetricBean> metricBeans = mBeanRegistry.listAllMBeans();
 | 
			
		||||
        if (metricBeans == null || metricBeans.isEmpty()) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        for (MetricBean metricBean : metricBeans) {
 | 
			
		||||
            if (!Objects.equals(metricBean.getVersion(), version)) {
 | 
			
		||||
                metricBean.reset();
 | 
			
		||||
                mBeanRegistry.unRegister(metricBean);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,50 @@
 | 
			
		||||
/*
 | 
			
		||||
 *  Copyright 1999-2021 Alibaba Group Holding Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 *  Licensed 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 com.alibaba.csp.sentinel.metric.exporter.jmx;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * the Metric JMX Bean interface.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 20:02
 | 
			
		||||
 * @since 1.8.3
 | 
			
		||||
 */
 | 
			
		||||
public interface MetricMXBean {
 | 
			
		||||
    
 | 
			
		||||
    long getTimestamp();
 | 
			
		||||
    
 | 
			
		||||
    long getOccupiedPassQps();
 | 
			
		||||
    
 | 
			
		||||
    long getSuccessQps();
 | 
			
		||||
    
 | 
			
		||||
    long getPassQps();
 | 
			
		||||
    
 | 
			
		||||
    long getExceptionQps();
 | 
			
		||||
    
 | 
			
		||||
    long getBlockQps();
 | 
			
		||||
    
 | 
			
		||||
    long getRt();
 | 
			
		||||
    
 | 
			
		||||
    String getResource();
 | 
			
		||||
    
 | 
			
		||||
    int getClassification();
 | 
			
		||||
    
 | 
			
		||||
    int getConcurrency();
 | 
			
		||||
 | 
			
		||||
    long getVersion();
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1 @@
 | 
			
		||||
com.alibaba.csp.sentinel.metric.MetricExporterInit
 | 
			
		||||
@@ -0,0 +1,34 @@
 | 
			
		||||
package com.alibaba.cps.sentinel.metric.exporter;
 | 
			
		||||
 | 
			
		||||
import com.alibaba.csp.sentinel.metric.exporter.jmx.MBeanRegistry;
 | 
			
		||||
import com.alibaba.csp.sentinel.metric.exporter.jmx.MetricBean;
 | 
			
		||||
import org.junit.Assert;
 | 
			
		||||
import org.junit.Test;
 | 
			
		||||
 | 
			
		||||
import javax.management.JMException;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * {@link com.alibaba.csp.sentinel.metric.exporter.jmx.MBeanRegistry} unit test.
 | 
			
		||||
 *
 | 
			
		||||
 * @author chenglu
 | 
			
		||||
 * @date 2021-07-01 23:07
 | 
			
		||||
 */
 | 
			
		||||
public class MBeanRegistryTest {
 | 
			
		||||
    
 | 
			
		||||
    @Test
 | 
			
		||||
    public void testMBeanRegistry() throws JMException {
 | 
			
		||||
        MBeanRegistry mBeanRegistry = MBeanRegistry.getInstance();
 | 
			
		||||
    
 | 
			
		||||
        MetricBean metricBean = new MetricBean();
 | 
			
		||||
        String mBeanName = "Sentinel:type=test,name=test";
 | 
			
		||||
        mBeanRegistry.register(metricBean, mBeanName);
 | 
			
		||||
        
 | 
			
		||||
        MetricBean mb1 = mBeanRegistry.findMBean(mBeanName);
 | 
			
		||||
        Assert.assertEquals(mb1, metricBean);
 | 
			
		||||
        
 | 
			
		||||
        mBeanRegistry.unRegister(metricBean);
 | 
			
		||||
    
 | 
			
		||||
        MetricBean mb2 = mBeanRegistry.findMBean(mBeanName);
 | 
			
		||||
        Assert.assertNull(mb2);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user