package com.dianping.pigeon.remoting.invoker.process.statistics; import java.io.Serializable; import java.util.Calendar; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import com.dianping.pigeon.config.ConfigManagerLoader; import com.dianping.pigeon.log.Logger; import com.dianping.pigeon.log.LoggerLoader; import com.dianping.pigeon.remoting.common.domain.InvocationRequest; import com.dianping.pigeon.remoting.common.util.ContextUtils; public class InvokerCapacityBucket implements Serializable { /** * */ private static final long serialVersionUID = 1L; private static final Logger logger = LoggerLoader.getLogger(InvokerCapacityBucket.class); private AtomicInteger requests = new AtomicInteger(); private Map<Integer, AtomicInteger> totalRequestsInSecond = new ConcurrentHashMap<Integer, AtomicInteger>(); private Map<Integer, AtomicInteger> totalRequestsInDay = new ConcurrentHashMap<Integer, AtomicInteger>(); private Map<Integer, AtomicInteger> totalRequestsInMinute = new ConcurrentHashMap<Integer, AtomicInteger>(); public static final boolean enableDayStats = ConfigManagerLoader.getConfigManager().getBooleanValue( "pigeon.invokerstat.day.enable", true); public static final boolean enableMinuteStats = ConfigManagerLoader.getConfigManager().getBooleanValue( "pigeon.invokerstat.minute.enable", true); public static final boolean enableMethodStats = ConfigManagerLoader.getConfigManager().getBooleanValue( "pigeon.invokerstat.method.enable", true); private Map<String, String> requestCall = new ConcurrentHashMap<String, String>(); public static void init() { } public InvokerCapacityBucket(String address) { preFillData(); } public void flowIn(InvocationRequest request) { Calendar now = Calendar.getInstance(); requests.incrementAndGet(); incrementTotalRequestsInSecond(now.get(Calendar.SECOND)); if (enableMinuteStats) { incrementTotalRequestsInMinute(now.get(Calendar.MINUTE)); } if (enableDayStats) { incrementTotalRequestsInDay(now.get(Calendar.DATE)); } if (enableMethodStats) { String callUrl = request.getServiceName() + "#" + request.getMethodName(); if (!requestCall.containsKey(callUrl)) { String currentServiceUrl = (String) ContextUtils.getLocalContext("CurrentServiceUrl"); requestCall.put(callUrl, currentServiceUrl == null ? "" : currentServiceUrl); } } } public void flowOut(InvocationRequest request) { requests.decrementAndGet(); } public int getCurrentRequests() { return requests.get(); } public Map<Integer, AtomicInteger> getTotalRequestsInSecond() { return totalRequestsInSecond; } public int getRequestsInSecond(int second) { AtomicInteger counter = totalRequestsInSecond.get(second); return counter != null ? counter.get() : 0; } public int getRequestsInLastSecond() { Calendar cal = Calendar.getInstance(); cal.add(Calendar.SECOND, -1); int lastSecond = cal.get(Calendar.SECOND); AtomicInteger counter = totalRequestsInSecond.get(lastSecond); return counter != null ? counter.get() : 0; } public int getRequestsInCurrentSecond() { Calendar cal = Calendar.getInstance(); int lastSecond = cal.get(Calendar.SECOND); AtomicInteger counter = totalRequestsInSecond.get(lastSecond); return counter != null ? counter.get() : 0; } public int getRequestsInLastMinute() { Calendar cal = Calendar.getInstance(); cal.add(Calendar.MINUTE, -1); int lastMinute = cal.get(Calendar.MINUTE); lastMinute = lastMinute >= 0 ? lastMinute : lastMinute + 60; AtomicInteger counter = totalRequestsInMinute.get(lastMinute); return counter != null ? counter.get() : 0; } public int getRequestsInLastDay() { Calendar cal = Calendar.getInstance(); cal.add(Calendar.DATE, -1); int lastDay = cal.get(Calendar.DATE); AtomicInteger counter = totalRequestsInDay.get(lastDay); return counter != null ? counter.get() : 0; } public int getRequestsInToday() { Calendar cal = Calendar.getInstance(); int day = cal.get(Calendar.DATE); AtomicInteger counter = totalRequestsInDay.get(day); return counter != null ? counter.get() : 0; } private void incrementTotalRequestsInDay(int day) { AtomicInteger counter = totalRequestsInDay.get(day); if (counter != null) { counter.incrementAndGet(); } else { logger.warn("Impossible case happended, day[" + day + "]'s request counter is null."); } } private void incrementTotalRequestsInMinute(int minute) { AtomicInteger counter = totalRequestsInMinute.get(minute); if (counter != null) { counter.incrementAndGet(); } else { logger.warn("Impossible case happended, day[" + minute + "]'s request counter is null."); } } private void incrementTotalRequestsInSecond(int second) { AtomicInteger counter = totalRequestsInSecond.get(second); if (counter != null) { counter.incrementAndGet(); } else { logger.warn("Impossible case happended, second[" + second + "]'s request counter is null."); } } /** * 重置过期的每秒请求数计数器 */ public void resetRequestsInSecondCounter() { int second = Calendar.getInstance().get(Calendar.SECOND); int prev3Sec = second - 10; for (int i = 1; i <= 30; i++) { int prevSec = prev3Sec - i; prevSec = prevSec >= 0 ? prevSec : prevSec + 60; AtomicInteger counter = totalRequestsInSecond.get(prevSec); if (counter != null) { counter.set(0); } } } public void resetRequestsInDayCounter() { if (enableDayStats) { int day = Calendar.getInstance().get(Calendar.DATE); int prev3Sec = day - 10; for (int i = 1; i <= 15; i++) { int prevSec = prev3Sec - i; prevSec = prevSec >= 0 ? prevSec : prevSec + 31; AtomicInteger counter = totalRequestsInDay.get(prevSec); if (counter != null) { counter.set(0); } } } } public void resetRequestsInMinuteCounter() { if (enableMinuteStats) { int min = Calendar.getInstance().get(Calendar.MINUTE); int prev3Sec = min - 10; for (int i = 1; i <= 30; i++) { int prevSec = prev3Sec - i; prevSec = prevSec >= 0 ? prevSec : prevSec + 60; AtomicInteger counter = totalRequestsInMinute.get(prevSec); if (counter != null) { counter.set(0); } } } } private void preFillData() { for (int sec = 0; sec < 60; sec++) { totalRequestsInSecond.put(sec, new AtomicInteger()); } if (enableMinuteStats) { for (int min = 0; min < 60; min++) { totalRequestsInMinute.put(min, new AtomicInteger()); } } if (enableDayStats) { for (int day = 1; day < 32; day++) { totalRequestsInDay.put(day, new AtomicInteger()); } } } public String toString() { StringBuilder sb = new StringBuilder(); sb.append("requests-current:").append(requests).append(",requests-currentsecond:") .append(getRequestsInCurrentSecond()).append(",requests-lastsecond:").append(getRequestsInLastSecond()); if (enableMinuteStats) { sb.append(",requests-lastminute:").append(getRequestsInLastMinute()); } if (enableDayStats) { sb.append(",requests-lastday:").append(getRequestsInLastDay()).append(",requests-today:") .append(getRequestsInToday()).toString(); } if (enableMethodStats) { sb.append(",methods:[").append(requestCall).append("]"); } return sb.toString(); } }