tp90

关于tp90的概念,见tp90和tp99是指什么性能指标,求大神解释下?

springboot配置

springboot可以利用metrics来搞定

@Order(Ordered.HIGHEST_PRECEDENCE)
public final class DropwizardMetricsFilter extends OncePerRequestFilter {

    private static final String ATTRIBUTE_STOP_WATCH = DropwizardMetricsFilter.class.getName()
            + ".StopWatch";

    private static final int UNDEFINED_HTTP_STATUS = 999;

    private static final String UNKNOWN_PATH_SUFFIX = "/unmapped";

    private static final Log logger = LogFactory.getLog(DropwizardMetricsFilter.class);

    private static final Set<PatternReplacer> STATUS_REPLACERS;

    static {
        Set<PatternReplacer> replacements = new LinkedHashSet<>();
        replacements.add(new PatternReplacer("[{}]", 0, "-"));
        replacements.add(new PatternReplacer("**", Pattern.LITERAL, "-star-star-"));
        replacements.add(new PatternReplacer("*", Pattern.LITERAL, "-star-"));
        replacements.add(new PatternReplacer("/-", Pattern.LITERAL, "/"));
        replacements.add(new PatternReplacer("-/", Pattern.LITERAL, "/"));
        STATUS_REPLACERS = Collections.unmodifiableSet(replacements);
    }

    private static final Set<PatternReplacer> KEY_REPLACERS;

    static {
        Set<PatternReplacer> replacements = new LinkedHashSet<PatternReplacer>();
        replacements.add(new PatternReplacer("/", Pattern.LITERAL, "."));
        replacements.add(new PatternReplacer("..", Pattern.LITERAL, "."));
        KEY_REPLACERS = Collections.unmodifiableSet(replacements);
    }

    private final MetricRegistry metricRegistry;

    public DropwizardMetricsFilter(MetricRegistry metricRegistry) {
        this.metricRegistry = metricRegistry;
    }

    @Override
    protected boolean shouldNotFilterAsyncDispatch() {
        return false;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        StopWatch stopWatch = createStopWatchIfNecessary(request);
        String path = new UrlPathHelper().getPathWithinApplication(request);
        int status = HttpStatus.INTERNAL_SERVER_ERROR.value();
        try {
            chain.doFilter(request, response);
            status = getStatus(response);
        } finally {
            if (!request.isAsyncStarted()) {
                stopWatch.stop();
                request.removeAttribute(ATTRIBUTE_STOP_WATCH);
                recordTime(request, path, status, stopWatch.getTotalTimeMillis());
            }
        }
    }

    private StopWatch createStopWatchIfNecessary(HttpServletRequest request) {
        StopWatch stopWatch = (StopWatch) request.getAttribute(ATTRIBUTE_STOP_WATCH);
        if (stopWatch == null) {
            stopWatch = new StopWatch();
            stopWatch.start();
            request.setAttribute(ATTRIBUTE_STOP_WATCH, stopWatch);
        }
        return stopWatch;
    }

    private int getStatus(HttpServletResponse response) {
        try {
            return response.getStatus();
        } catch (Exception ex) {
            return UNDEFINED_HTTP_STATUS;
        }
    }

    private void recordTime(HttpServletRequest request, String path, int status, long time) {
        String suffix = getFinalStatus(request, path, status);
        String timerName = getKey("timer." + request.getMethod() + "." + status + suffix);
        try {
            Timer timer = this.metricRegistry.timer(timerName);
            timer.update(time, TimeUnit.MILLISECONDS);
        } catch (Exception ex) {
            logger.warn("Unable to submit timer '" + timerName + "'", ex);
        }
    }

    private String getFinalStatus(HttpServletRequest request, String path, int status) {
        Object bestMatchingPattern = request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        if (bestMatchingPattern != null) {
            return fixSpecialCharacters(bestMatchingPattern.toString());
        }
        HttpStatus.Series series = getSeries(status);
        if (HttpStatus.Series.CLIENT_ERROR.equals(series) || HttpStatus.Series.REDIRECTION.equals(series)) {
            return UNKNOWN_PATH_SUFFIX;
        }
        return path;
    }

    private String fixSpecialCharacters(String value) {
        String result = value;
        for (PatternReplacer replacer : STATUS_REPLACERS) {
            result = replacer.apply(result);
        }
        if (result.endsWith("-")) {
            result = result.substring(0, result.length() - 1);
        }
        if (result.startsWith("-")) {
            result = result.substring(1);
        }
        return result;
    }

    private HttpStatus.Series getSeries(int status) {
        try {
            return HttpStatus.valueOf(status).series();
        } catch (Exception ex) {
            return null;
        }
    }

    private String getKey(String string) {
        // graphite compatible metric names
        String key = string;
        for (PatternReplacer replacer : KEY_REPLACERS) {
            key = replacer.apply(key);
        }
        if (key.endsWith(".")) {
            key = key + "root";
        }
        if (key.startsWith("_")) {
            key = key.substring(1);
        }
        return key;
    }

    private static class PatternReplacer {

        private final Pattern pattern;
        private final String replacement;

        PatternReplacer(String regex, int flags, String replacement) {
            this.pattern = Pattern.compile(regex, flags);
            this.replacement = replacement;
        }

        public String apply(String input) {
            return this.pattern.matcher(input)
                    .replaceAll(Matcher.quoteReplacement(this.replacement));
        }

    }
}

禁用原生filter

@SpringBootApplication(exclude = MetricFilterAutoConfiguration.class)

启用DropwizardMetricsFilter

@Bean
    public DropwizardMetricsFilter metricFilter(MetricRegistry metricRegistry) {
        return new DropwizardMetricsFilter(metricRegistry);
    }

截图

clipboard.png

问题

有个问题就是,使用graphite的话,磁盘空间占用太多了,跑几千个请求,一下子占到1G多了,暂时没找到怎么定时清理。目前这个方案还是不适合放到生产环境上,以免把磁盘给爆掉。这种性能监控,还是比较适合走大数据的方案。

docs


codecraft
11.9k 声望2k 粉丝

当一个代码的工匠回首往事时,不因虚度年华而悔恨,也不因碌碌无为而羞愧,这样,当他老的时候,可以很自豪告诉世人,我曾经将代码注入生命去打造互联网的浪潮之巅,那是个很疯狂的时代,我在一波波的浪潮上留下...