标签:数据保存 exec size data avg sys 业务 信息 ble
对于非业务通用框架的开发,做需求分析的时候,除了功能性需求分析之外,还需要考虑框架的非功能性需求。
设计开发一个小的框架,能够获取接口调用的各种统计信息,比如,响应时间的最大值(max)、最小值(min)、平均值(avg)、百分位值(percentile)、接口调用次数(count)、频率(tps) 等,并且支持将统计结果以各种显示格式(比如:JSON 格式、网页格式、自定义显示格式等)输出到各种终端(Console 命令行、HTTP 网页、Email、日志文件、自定义输出终端等),以方便查看。
功能性需求
接口统计信息:包括接口响应时间的统计信息,以及接口调用次数的统计信息等。
统计信息的类型:max、min、avg、percentile、count、tps 等。
统计信息显示格式:Json、Html、自定义显示格式。
统计信息显示终端:Console、Email、HTTP 网页、日志、自定义显示终端。
线框图,原型设计
隐藏性需求
非功能性需求分析
对于复杂框架的设计,几个小技巧,其中包括:
//应用场景:统计下面两个接口(注册和登录)的响应时间和访问次数
public class UserController {
public void register(UserVo user) {
//...
}
public UserVo login(String telephone, String password) {
//...
}
}
要输出接口的响应时间的最大值、平均值和接口调用次数,我们首先要采集每次接口请求的响应时间,并且存储起来,然后按照某个时间间隔做聚合统计,最后才是将结果输出。
public class Metrics {
// Map的key是接口名称,value对应接口请求的响应时间或时间戳;
private Map<String, List<Double>> responseTimes = new HashMap<>();
private Map<String, List<Double>> timestamps = new HashMap<>();
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
public void recordResponseTime(String apiName, double responseTime) {
responseTimes.putIfAbsent(apiName, new ArrayList<>());
responseTimes.get(apiName).add(responseTime);
}
public void recordTimestamp(String apiName, double timestamp) {
timestamps.putIfAbsent(apiName, new ArrayList<>());
timestamps.get(apiName).add(timestamp);
}
public void startRepeatedReport(long period, TimeUnit unit){
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Gson gson = new Gson();
Map<String, Map<String, Double>> stats = new HashMap<>();
for (Map.Entry<String, List<Double>> entry : responseTimes.entrySet()) {
String apiName = entry.getKey();
List<Double> apiRespTimes = entry.getValue();
stats.putIfAbsent(apiName, new HashMap<>());
stats.get(apiName).put("max", max(apiRespTimes));
stats.get(apiName).put("avg", avg(apiRespTimes));
}
for (Map.Entry<String, List<Double>> entry : timestamps.entrySet()) {
String apiName = entry.getKey();
List<Double> apiTimestamps = entry.getValue();
stats.putIfAbsent(apiName, new HashMap<>());
stats.get(apiName).put("count", (double)apiTimestamps.size());
}
System.out.println(gson.toJson(stats));
}
}, 0, period, unit);
}
private double max(List<Double> dataset) {//省略代码实现}
private double avg(List<Double> dataset) {//省略代码实现}
}
统计注册、登录接口的响应时间和访问次数
//应用场景:统计下面两个接口(注册和登录)的响应时间和访问次数
public class UserController {
private Metrics metrics = new Metrics();
public UserController() {
metrics.startRepeatedReport(60, TimeUnit.SECONDS);
}
public void register(UserVo user) {
long startTimestamp = System.currentTimeMillis();
metrics.recordTimestamp("regsiter", startTimestamp);
//...
long respTime = System.currentTimeMillis() - startTimestamp;
metrics.recordResponseTime("register", respTime);
}
public UserVo login(String telephone, String password) {
long startTimestamp = System.currentTimeMillis();
metrics.recordTimestamp("login", startTimestamp);
//...
long respTime = System.currentTimeMillis() - startTimestamp;
metrics.recordResponseTime("login", respTime);
}
}
设计模式简记-实战二:针对非业务的通过框架开发,如何做需求分析设计
标签:数据保存 exec size data avg sys 业务 信息 ble
原文地址:https://www.cnblogs.com/wod-Y/p/12785761.html