All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.rocketmq.store.StoreStatsService Maven / Gradle / Ivy
/**
* Copyright (C) 2010-2013 Alibaba Group Holding Limited
*
* 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.rocketmq.store;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.rocketmq.common.ServiceThread;
import com.alibaba.rocketmq.common.constant.LoggerName;
/**
* 存储层内部统计服务
*
* @author shijia.wxr
* @since 2013-7-21
*/
public class StoreStatsService extends ServiceThread {
private static final Logger log = LoggerFactory.getLogger(LoggerName.StoreLoggerName);
// 采样频率,1秒钟采样一次
private static final int FrequencyOfSampling = 1000;
// 采样最大记录数,超过则将之前的删除掉
private static final int MaxRecordsOfSampling = 60 * 10;
// 打印TPS数据间隔时间,单位秒,1分钟
private static int PrintTPSInterval = 60 * 1;
// putMessage,失败次数
private final AtomicLong putMessageFailedTimes = new AtomicLong(0);
// putMessage,调用总数
private final Map putMessageTopicTimesTotal =
new ConcurrentHashMap(128);
// putMessage,Message Size Total
private final Map putMessageTopicSizeTotal =
new ConcurrentHashMap(128);
// getMessage,调用总数
private final AtomicLong getMessageTimesTotalFound = new AtomicLong(0);
private final AtomicLong getMessageTransferedMsgCount = new AtomicLong(0);
private final AtomicLong getMessageTimesTotalMiss = new AtomicLong(0);
// putMessage,耗时分布
private final AtomicLong[] putMessageDistributeTime = new AtomicLong[7];
// put最近10分钟采样
private final LinkedList putTimesList = new LinkedList();
// get最近10分钟采样
private final LinkedList getTimesFoundList = new LinkedList();
private final LinkedList getTimesMissList = new LinkedList();
private final LinkedList transferedMsgCountList = new LinkedList();
// 启动时间
private long messageStoreBootTimestamp = System.currentTimeMillis();
// putMessage,写入整个消息耗时,含加锁竟争时间(单位毫秒)
private volatile long putMessageEntireTimeMax = 0;
// getMessage,读取一批消息耗时,含加锁竟争时间(单位毫秒)
private volatile long getMessageEntireTimeMax = 0;
// for putMessageEntireTimeMax
private ReentrantLock lockPut = new ReentrantLock();
// for getMessageEntireTimeMax
private ReentrantLock lockGet = new ReentrantLock();
// DispatchMessageService,缓冲区最大值
private volatile long dispatchMaxBuffer = 0;
// 针对采样线程加锁
private ReentrantLock lockSampling = new ReentrantLock();
private long lastPrintTimestamp = System.currentTimeMillis();
public StoreStatsService() {
for (int i = 0; i < this.putMessageDistributeTime.length; i++) {
putMessageDistributeTime[i] = new AtomicLong(0);
}
}
public long getPutMessageEntireTimeMax() {
return putMessageEntireTimeMax;
}
public void setPutMessageEntireTimeMax(long value) {
// 微秒
if (value <= 0) {
this.putMessageDistributeTime[0].incrementAndGet();
}
// 几毫秒
else if (value < 10) {
this.putMessageDistributeTime[1].incrementAndGet();
}
// 几十毫秒
else if (value < 100) {
this.putMessageDistributeTime[2].incrementAndGet();
}
// 几百毫秒(500毫秒以内)
else if (value < 500) {
this.putMessageDistributeTime[3].incrementAndGet();
}
// 几百毫秒(500毫秒以上)
else if (value < 1000) {
this.putMessageDistributeTime[4].incrementAndGet();
}
// 几秒
else if (value < 10000) {
this.putMessageDistributeTime[5].incrementAndGet();
}
// 大等于10秒
else {
this.putMessageDistributeTime[6].incrementAndGet();
}
if (value > this.putMessageEntireTimeMax) {
this.lockPut.lock();
this.putMessageEntireTimeMax =
value > this.putMessageEntireTimeMax ? value : this.putMessageEntireTimeMax;
this.lockPut.unlock();
}
}
public long getGetMessageEntireTimeMax() {
return getMessageEntireTimeMax;
}
public void setGetMessageEntireTimeMax(long value) {
if (value > this.getMessageEntireTimeMax) {
this.lockGet.lock();
this.getMessageEntireTimeMax =
value > this.getMessageEntireTimeMax ? value : this.getMessageEntireTimeMax;
this.lockGet.unlock();
}
}
public long getDispatchMaxBuffer() {
return dispatchMaxBuffer;
}
public void setDispatchMaxBuffer(long value) {
this.dispatchMaxBuffer = value > this.dispatchMaxBuffer ? value : this.dispatchMaxBuffer;
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder(1024);
Long totalTimes = getPutMessageTimesTotal();
if (0 == totalTimes) {
totalTimes = 1L;
}
sb.append("\truntime: " + this.getFormatRuntime() + "\r\n");
sb.append("\tputMessageEntireTimeMax: " + this.putMessageEntireTimeMax + "\r\n");
sb.append("\tputMessageTimesTotal: " + totalTimes + "\r\n");
sb.append("\tputMessageSizeTotal: " + this.getPutMessageSizeTotal() + "\r\n");
sb.append("\tputMessageDistributeTime: " + this.getPutMessageDistributeTimeStringInfo(totalTimes)
+ "\r\n");
sb.append("\tputMessageAverageSize: " + (this.getPutMessageSizeTotal() / totalTimes.doubleValue())
+ "\r\n");
sb.append("\tdispatchMaxBuffer: " + this.dispatchMaxBuffer + "\r\n");
sb.append("\tgetMessageEntireTimeMax: " + this.getMessageEntireTimeMax + "\r\n");
sb.append("\tputTps: " + this.getPutTps() + "\r\n");
sb.append("\tgetFoundTps: " + this.getGetFoundTps() + "\r\n");
sb.append("\tgetMissTps: " + this.getGetMissTps() + "\r\n");
sb.append("\tgetTotalTps: " + this.getGetTotalTps() + "\r\n");
sb.append("\tgetTransferedTps: " + this.getGetTransferedTps() + "\r\n");
return sb.toString();
}
private String getPutMessageDistributeTimeStringInfo(Long total) {
final StringBuilder sb = new StringBuilder(512);
for (AtomicLong i : this.putMessageDistributeTime) {
long value = i.get();
double ratio = value / total.doubleValue();
sb.append("\r\n\t\t");
sb.append(value + "(" + (ratio * 100) + "%)");
}
return sb.toString();
}
private String getFormatRuntime() {
final long MILLISECOND = 1;
final long SECOND = 1000 * MILLISECOND;
final long MINUTE = 60 * SECOND;
final long HOUR = 60 * MINUTE;
final long DAY = 24 * HOUR;
final MessageFormat TIME = new MessageFormat("[ {0} days, {1} hours, {2} minutes, {3} seconds ]");
long time = System.currentTimeMillis() - this.messageStoreBootTimestamp;
long days = time / DAY;
long hours = (time % DAY) / HOUR;
long minutes = (time % HOUR) / MINUTE;
long seconds = (time % MINUTE) / SECOND;
return TIME.format(new Long[] { days, hours, minutes, seconds });
}
private String getPutTps() {
StringBuilder sb = new StringBuilder();
// 10秒钟
sb.append(this.getPutTps(10));
sb.append(" ");
// 1分钟
sb.append(this.getPutTps(60));
sb.append(" ");
// 10分钟
sb.append(this.getPutTps(600));
return sb.toString();
}
private String getPutTps(int time) {
String result = "";
this.lockSampling.lock();
try {
CallSnapshot last = this.putTimesList.getLast();
if (this.putTimesList.size() > time) {
CallSnapshot lastBefore = this.putTimesList.get(this.putTimesList.size() - (time + 1));
result += CallSnapshot.getTPS(lastBefore, last);
}
}
finally {
this.lockSampling.unlock();
}
return result;
}
private String getGetFoundTps() {
StringBuilder sb = new StringBuilder();
// 10秒钟
sb.append(this.getGetFoundTps(10));
sb.append(" ");
// 1分钟
sb.append(this.getGetFoundTps(60));
sb.append(" ");
// 10分钟
sb.append(this.getGetFoundTps(600));
return sb.toString();
}
private String getGetFoundTps(int time) {
String result = "";
this.lockSampling.lock();
try {
CallSnapshot last = this.getTimesFoundList.getLast();
if (this.getTimesFoundList.size() > time) {
CallSnapshot lastBefore =
this.getTimesFoundList.get(this.getTimesFoundList.size() - (time + 1));
result += CallSnapshot.getTPS(lastBefore, last);
}
}
finally {
this.lockSampling.unlock();
}
return result;
}
private String getGetMissTps() {
StringBuilder sb = new StringBuilder();
// 10秒钟
sb.append(this.getGetMissTps(10));
sb.append(" ");
// 1分钟
sb.append(this.getGetMissTps(60));
sb.append(" ");
// 10分钟
sb.append(this.getGetMissTps(600));
return sb.toString();
}
private String getGetMissTps(int time) {
String result = "";
this.lockSampling.lock();
try {
CallSnapshot last = this.getTimesMissList.getLast();
if (this.getTimesMissList.size() > time) {
CallSnapshot lastBefore =
this.getTimesMissList.get(this.getTimesMissList.size() - (time + 1));
result += CallSnapshot.getTPS(lastBefore, last);
}
}
finally {
this.lockSampling.unlock();
}
return result;
}
private String getGetTransferedTps() {
StringBuilder sb = new StringBuilder();
// 10秒钟
sb.append(this.getGetTransferedTps(10));
sb.append(" ");
// 1分钟
sb.append(this.getGetTransferedTps(60));
sb.append(" ");
// 10分钟
sb.append(this.getGetTransferedTps(600));
return sb.toString();
}
private String getGetTransferedTps(int time) {
String result = "";
this.lockSampling.lock();
try {
CallSnapshot last = this.transferedMsgCountList.getLast();
if (this.transferedMsgCountList.size() > time) {
CallSnapshot lastBefore =
this.transferedMsgCountList.get(this.transferedMsgCountList.size() - (time + 1));
result += CallSnapshot.getTPS(lastBefore, last);
}
}
finally {
this.lockSampling.unlock();
}
return result;
}
private String getGetTotalTps() {
StringBuilder sb = new StringBuilder();
// 10秒钟
sb.append(this.getGetTotalTps(10));
sb.append(" ");
// 1分钟
sb.append(this.getGetTotalTps(60));
sb.append(" ");
// 10分钟
sb.append(this.getGetTotalTps(600));
return sb.toString();
}
private String getGetTotalTps(int time) {
this.lockSampling.lock();
double found = 0;
double miss = 0;
try {
{
CallSnapshot last = this.getTimesFoundList.getLast();
if (this.getTimesFoundList.size() > time) {
CallSnapshot lastBefore =
this.getTimesFoundList.get(this.getTimesFoundList.size() - (time + 1));
found = CallSnapshot.getTPS(lastBefore, last);
}
}
{
CallSnapshot last = this.getTimesMissList.getLast();
if (this.getTimesMissList.size() > time) {
CallSnapshot lastBefore =
this.getTimesMissList.get(this.getTimesMissList.size() - (time + 1));
miss = CallSnapshot.getTPS(lastBefore, last);
}
}
}
finally {
this.lockSampling.unlock();
}
return Double.toString(found + miss);
}
public long getPutMessageTimesTotal() {
long rs = 0;
for (AtomicLong data : putMessageTopicTimesTotal.values()) {
rs += data.get();
}
return rs;
}
public long getPutMessageSizeTotal() {
long rs = 0;
for (AtomicLong data : putMessageTopicSizeTotal.values()) {
rs += data.get();
}
return rs;
}
public HashMap getRuntimeInfo() {
HashMap result = new HashMap(64);
Long totalTimes = getPutMessageTimesTotal();
if (0 == totalTimes) {
totalTimes = 1L;
}
result.put("bootTimestamp", String.valueOf(this.messageStoreBootTimestamp));
result.put("runtime", this.getFormatRuntime());
result.put("putMessageEntireTimeMax", String.valueOf(this.putMessageEntireTimeMax));
result.put("putMessageTimesTotal", String.valueOf(totalTimes));
result.put("putMessageSizeTotal", String.valueOf(this.getPutMessageSizeTotal()));
result.put("putMessageDistributeTime",
String.valueOf(this.getPutMessageDistributeTimeStringInfo(totalTimes)));
result.put("putMessageAverageSize",
String.valueOf((this.getPutMessageSizeTotal() / totalTimes.doubleValue())));
result.put("dispatchMaxBuffer", String.valueOf(this.dispatchMaxBuffer));
result.put("getMessageEntireTimeMax", String.valueOf(this.getMessageEntireTimeMax));
result.put("putTps", String.valueOf(this.getPutTps()));
result.put("getFoundTps", String.valueOf(this.getGetFoundTps()));
result.put("getMissTps", String.valueOf(this.getGetMissTps()));
result.put("getTotalTps", String.valueOf(this.getGetTotalTps()));
result.put("getTransferedTps", String.valueOf(this.getGetTransferedTps()));
return result;
}
public void run() {
log.info(this.getServiceName() + " service started");
while (!this.isStoped()) {
try {
this.waitForRunning(FrequencyOfSampling);
this.sampling();
this.printTps();
}
catch (Exception e) {
log.warn(this.getServiceName() + " service has exception. ", e);
}
}
log.info(this.getServiceName() + " service end");
}
private void sampling() {
this.lockSampling.lock();
try {
this.putTimesList.add(new CallSnapshot(System.currentTimeMillis(), getPutMessageTimesTotal()));
if (this.putTimesList.size() > (MaxRecordsOfSampling + 1)) {
this.putTimesList.removeFirst();
}
this.getTimesFoundList.add(new CallSnapshot(System.currentTimeMillis(),
this.getMessageTimesTotalFound.get()));
if (this.getTimesFoundList.size() > (MaxRecordsOfSampling + 1)) {
this.getTimesFoundList.removeFirst();
}
this.getTimesMissList.add(new CallSnapshot(System.currentTimeMillis(),
this.getMessageTimesTotalMiss.get()));
if (this.getTimesMissList.size() > (MaxRecordsOfSampling + 1)) {
this.getTimesMissList.removeFirst();
}
this.transferedMsgCountList.add(new CallSnapshot(System.currentTimeMillis(),
this.getMessageTransferedMsgCount.get()));
if (this.transferedMsgCountList.size() > (MaxRecordsOfSampling + 1)) {
this.transferedMsgCountList.removeFirst();
}
}
finally {
this.lockSampling.unlock();
}
}
/**
* 1分钟打印一次TPS
*/
private void printTps() {
if (System.currentTimeMillis() > (this.lastPrintTimestamp + PrintTPSInterval * 1000)) {
this.lastPrintTimestamp = System.currentTimeMillis();
log.info("put_tps {}", this.getPutTps(PrintTPSInterval));
log.info("get_found_tps {}", this.getGetFoundTps(PrintTPSInterval));
log.info("get_miss_tps {}", this.getGetMissTps(PrintTPSInterval));
log.info("get_transfered_tps {}", this.getGetTransferedTps(PrintTPSInterval));
}
}
@Override
public String getServiceName() {
return StoreStatsService.class.getSimpleName();
}
public AtomicLong getGetMessageTimesTotalFound() {
return getMessageTimesTotalFound;
}
public AtomicLong getGetMessageTimesTotalMiss() {
return getMessageTimesTotalMiss;
}
public AtomicLong getGetMessageTransferedMsgCount() {
return getMessageTransferedMsgCount;
}
public AtomicLong getPutMessageFailedTimes() {
return putMessageFailedTimes;
}
public AtomicLong getSinglePutMessageTopicSizeTotal(String topic) {
AtomicLong rs = putMessageTopicSizeTotal.get(topic);
if (null == rs) {
rs = new AtomicLong(0);
putMessageTopicSizeTotal.put(topic, rs);
}
return rs;
}
public AtomicLong getSinglePutMessageTopicTimesTotal(String topic) {
AtomicLong rs = putMessageTopicTimesTotal.get(topic);
if (null == rs) {
rs = new AtomicLong(0);
putMessageTopicTimesTotal.put(topic, rs);
}
return rs;
}
public Map getPutMessageTopicTimesTotal() {
return putMessageTopicTimesTotal;
}
public Map getPutMessageTopicSizeTotal() {
return putMessageTopicSizeTotal;
}
static class CallSnapshot {
public final long timestamp;
public final long callTimesTotal;
public CallSnapshot(long timestamp, long callTimesTotal) {
this.timestamp = timestamp;
this.callTimesTotal = callTimesTotal;
}
public static double getTPS(final CallSnapshot begin, final CallSnapshot end) {
long total = end.callTimesTotal - begin.callTimesTotal;
Long time = end.timestamp - begin.timestamp;
double tps = total / time.doubleValue();
return tps * 1000;
}
}
}