Преглед на файлове

Add basic monitoring command API for cluster token server

- Also add top-K frequent parameter statistic support

Signed-off-by: Eric Zhao <sczyh16@gmail.com>
master
Eric Zhao преди 5 години
родител
ревизия
f82fcd696f
променени са 5 файла, в които са добавени 315 реда и са изтрити 1 реда
  1. +112
    -0
      sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/flow/statistic/ClusterMetricNode.java
  2. +106
    -0
      sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/flow/statistic/ClusterMetricNodeGenerator.java
  3. +52
    -0
      sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/flow/statistic/metric/ClusterParamMetric.java
  4. +43
    -0
      sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/server/command/handler/FetchClusterMetricCommandHandler.java
  5. +2
    -1
      sentinel-cluster/sentinel-cluster-server-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler

+ 112
- 0
sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/flow/statistic/ClusterMetricNode.java Целия файл

@@ -0,0 +1,112 @@
/*
* Copyright 1999-2018 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.cluster.flow.statistic;

import java.util.Map;

/**
* @author Eric Zhao
* @since 1.4.1
*/
public class ClusterMetricNode {

private long timestamp;

private String resourceName;
private long flowId;

private double passQps;
private double blockQps;
private long rt;

private Map<Object, Double> topParams;

public long getTimestamp() {
return timestamp;
}

public ClusterMetricNode setTimestamp(long timestamp) {
this.timestamp = timestamp;
return this;
}

public String getResourceName() {
return resourceName;
}

public ClusterMetricNode setResourceName(String resourceName) {
this.resourceName = resourceName;
return this;
}

public long getFlowId() {
return flowId;
}

public ClusterMetricNode setFlowId(long flowId) {
this.flowId = flowId;
return this;
}

public double getPassQps() {
return passQps;
}

public ClusterMetricNode setPassQps(double passQps) {
this.passQps = passQps;
return this;
}

public double getBlockQps() {
return blockQps;
}

public ClusterMetricNode setBlockQps(double blockQps) {
this.blockQps = blockQps;
return this;
}

public long getRt() {
return rt;
}

public ClusterMetricNode setRt(long rt) {
this.rt = rt;
return this;
}

public Map<Object, Double> getTopParams() {
return topParams;
}

public ClusterMetricNode setTopParams(Map<Object, Double> topParams) {
this.topParams = topParams;
return this;
}

@Override
public String toString() {
return "ClusterMetricNode{" +
"timestamp=" + timestamp +
", resourceName='" + resourceName + '\'' +
", flowId=" + flowId +
", passQps=" + passQps +
", blockQps=" + blockQps +
", rt=" + rt +
", topParams=" + topParams +
'}';
}
}

+ 106
- 0
sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/flow/statistic/ClusterMetricNodeGenerator.java Целия файл

@@ -0,0 +1,106 @@
/*
* Copyright 1999-2018 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.cluster.flow.statistic;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.rule.ClusterParamFlowRuleManager;
import com.alibaba.csp.sentinel.cluster.flow.statistic.data.ClusterFlowEvent;
import com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterMetric;
import com.alibaba.csp.sentinel.cluster.flow.statistic.metric.ClusterParamMetric;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowRule;
import com.alibaba.csp.sentinel.util.TimeUtil;

/**
* @author Eric Zhao
* @since 1.4.1
*/
public class ClusterMetricNodeGenerator {

public static Map<String, List<ClusterMetricNode>> generateCurrentNodeMap(String namespace) {
Map<String, List<ClusterMetricNode>> map = new HashMap<>();
Set<Long> flowIds = ClusterFlowRuleManager.getFlowIdSet(namespace);
Set<Long> paramFlowIds = ClusterParamFlowRuleManager.getFlowIdSet(namespace);
for (Long id : flowIds) {
ClusterMetricNode node = flowToMetricNode(id);
if (node == null) {
continue;
}
putToMap(map, node);
}
for (Long id : paramFlowIds) {
ClusterMetricNode node = paramToMetricNode(id);
if (node == null) {
continue;
}
putToMap(map, node);
}

return map;
}

private static void putToMap(Map<String, List<ClusterMetricNode>> map, ClusterMetricNode node) {
List<ClusterMetricNode> nodeList = map.get(node.getResourceName());
if (nodeList == null) {
nodeList = new ArrayList<>();
map.put(node.getResourceName(), nodeList);
}
nodeList.add(node);
}

public static ClusterMetricNode flowToMetricNode(long flowId) {
FlowRule rule = ClusterFlowRuleManager.getFlowRuleById(flowId);
if (rule == null) {
return null;
}
ClusterMetric metric = ClusterMetricStatistics.getMetric(flowId);
if (metric == null) {
return new ClusterMetricNode().setFlowId(flowId)
.setResourceName(rule.getResource());
}
return new ClusterMetricNode()
.setFlowId(flowId)
.setResourceName(rule.getResource())
.setBlockQps(metric.getAvg(ClusterFlowEvent.BLOCK))
.setPassQps(metric.getAvg(ClusterFlowEvent.PASS))
.setTimestamp(TimeUtil.currentTimeMillis());
}

public static ClusterMetricNode paramToMetricNode(long flowId) {
ParamFlowRule rule = ClusterParamFlowRuleManager.getParamRuleById(flowId);
if (rule == null) {
return null;
}
ClusterParamMetric metric = ClusterParamMetricStatistics.getMetric(flowId);
if (metric == null) {
return new ClusterMetricNode().setFlowId(flowId)
.setResourceName(rule.getResource())
.setTimestamp(TimeUtil.currentTimeMillis())
.setTopParams(new HashMap<Object, Double>(0));
}
return new ClusterMetricNode()
.setFlowId(flowId)
.setResourceName(rule.getResource())
.setTimestamp(TimeUtil.currentTimeMillis())
.setTopParams(metric.getTopValues(5));
}
}

+ 52
- 0
sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/flow/statistic/metric/ClusterParamMetric.java Целия файл

@@ -15,8 +15,16 @@
*/
package com.alibaba.csp.sentinel.cluster.flow.statistic.metric;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.alibaba.csp.sentinel.cluster.flow.statistic.data.ClusterFlowEvent;
import com.alibaba.csp.sentinel.slots.statistic.base.LongAdder;
import com.alibaba.csp.sentinel.slots.statistic.cache.CacheMap;
import com.alibaba.csp.sentinel.util.AssertUtil;
@@ -79,4 +87,48 @@ public class ClusterParamMetric {
public double getAvg(Object value) {
return getSum(value) / metric.getIntervalInSecond();
}

public Map<Object, Double> getTopValues(int number) {
metric.currentWindow();
List<CacheMap<Object, LongAdder>> buckets = metric.values();

Map<Object, Long> result = new HashMap<>(buckets.size());

for (CacheMap<Object, LongAdder> b : buckets) {
Set<Object> subSet = b.keySet(true);
for (Object o : subSet) {
Long count = result.get(o);
if (count == null) {
count = getCount(b.get(o));
} else {
count += getCount(b.get(o));
}
result.put(o, count);
}
}

// After merge, get the top set one.
Set<Entry<Object, Long>> set = result.entrySet();
List<Entry<Object, Long>> list = new ArrayList<>(set);
Collections.sort(list, new Comparator<Entry<Object, Long>>() {
@Override
public int compare(Entry<Object, Long> a,
Entry<Object, Long> b) {
return (int)(b.getValue() == null ? 0 : b.getValue()) - (int)(a.getValue() == null ? 0 : a.getValue());
}
});

Map<Object, Double> doubleResult = new HashMap<Object, Double>();

int size = list.size() > number ? number : list.size();
for (int i = 0; i < size; i++) {
Map.Entry<Object, Long> x = list.get(i);
if (x.getValue() == 0) {
break;
}
doubleResult.put(x.getKey(), ((double)x.getValue()) / metric.getIntervalInSecond());
}

return doubleResult;
}
}

+ 43
- 0
sentinel-cluster/sentinel-cluster-server-default/src/main/java/com/alibaba/csp/sentinel/cluster/server/command/handler/FetchClusterMetricCommandHandler.java Целия файл

@@ -0,0 +1,43 @@
/*
* Copyright 1999-2018 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.cluster.server.command.handler;

import com.alibaba.csp.sentinel.cluster.flow.statistic.ClusterMetricNodeGenerator;
import com.alibaba.csp.sentinel.command.CommandHandler;
import com.alibaba.csp.sentinel.command.CommandRequest;
import com.alibaba.csp.sentinel.command.CommandResponse;
import com.alibaba.csp.sentinel.command.annotation.CommandMapping;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSON;

/**
* @author Eric Zhao
* @since 1.4.1
*/
@CommandMapping(name = "cluster/server/metricList")
public class FetchClusterMetricCommandHandler implements CommandHandler<String> {

@Override
public CommandResponse<String> handle(CommandRequest request) {
String namespace = request.getParam("namespace");
if (StringUtil.isEmpty(namespace)) {
return CommandResponse.ofFailure(new IllegalArgumentException("failed: namespace cannot be empty"));
}
return CommandResponse.ofSuccess(
JSON.toJSONString(ClusterMetricNodeGenerator.generateCurrentNodeMap(namespace))
);
}
}

+ 2
- 1
sentinel-cluster/sentinel-cluster-server-default/src/main/resources/META-INF/services/com.alibaba.csp.sentinel.command.CommandHandler Целия файл

@@ -6,4 +6,5 @@ com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterServerTrans
com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyServerNamespaceSetHandler
com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterFlowRulesCommandHandler
com.alibaba.csp.sentinel.cluster.server.command.handler.ModifyClusterParamFlowRulesCommandHandler
com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterServerInfoCommandHandler
com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterServerInfoCommandHandler
com.alibaba.csp.sentinel.cluster.server.command.handler.FetchClusterMetricCommandHandler

Loading…
Отказ
Запис