date_histogram是按照时间来构建集合(桶)Buckts的,当我们需要按照时间进行做一些数据统计的时候,就可以使用它来进行时间维度上构建指标分析.
    在前面几篇中我们用到的hitogram也是可以处理日期的,但是,它不能自动识别日期,只会把日期看做是数字,在聚合的时候是不知道日历时间间隔.

     // 查询
"query": {
"bool": {
"must": [{
"range": {
"@timestamp": {
"gte": 1533556800000,
"lte": 1533806520000
}
}
}]
}
},
// 不显示具体的内容
"size": 0,
// 聚合
"aggs": {
// 自己取的聚合名字
"group_by_grabTime": {
// es提供的时间处理函数
"date_histogram": {
// 需要聚合分组的字段名称, 类型需要为date, 格式没有要求
"field": "@timestamp",
// 按什么时间段聚合, 这里是5分钟, 可用的interval在上面给出
"interval": "5m",
// 设置时区, 这样就相当于东八区的时间
"time_zone":"+08:00",
// 返回值格式化,HH大写,不然不能区分上午、下午
"format": "yyyy-MM-dd HH",
// 为空的话则填充0
"min_doc_count": 0,
// 需要填充0的范围
"extended_bounds": {
"min": 1533556800000,
"max": 1533806520000
}
},
// 聚合
"aggs": {
// 自己取的名称
"group_by_status": {
// es提供
"terms": {
// 聚合字段名
"field": "LowStatusOfPrice"
}
}
}
}
}

语法解释

统计实例

    def getapplist(self):
body = {
"size": 0,
"aggs": {
"res": {
"terms": {
"field": "appname"
}
}
}
}
res = self.es.search(body=body)
applist = res["aggregations"]["res"]["buckets"]
namelist=[]
for app in applist:
if app["key"]:
namelist.append(app["key"]) data = {'code': 'SUCCESS', 'message': '', 'data': namelist}
return data

精确查找列表

    def getqpsdata(self,appname,startTime,endTime):
appname = "dzgzpt-wsys"
userChoiceTime_start = "2019-04-05 09:27:27.820"
userChoiceTime_end = "2019-06-27 09:27:41.986"
interval = tools.set_interval(userChoiceTime_start, userChoiceTime_end)
body = {
"size": 0,
"query": {
"filtered": {
"query": {
"query_string": {
"analyze_wildcard": True,
"query": "appname:" + appname
}
},
"filter": {
"bool": {
"must": [
{
"range": {
"@timestamp": {
"gte": tools.strtime_to_timestamp(userChoiceTime_start),
"lte": tools.strtime_to_timestamp(userChoiceTime_end)
}
}
}
]
}
}
}
},
"aggs": {
"res": {
"date_histogram": {
"field": "@timestamp",
"interval": "%s" % (interval),
"time_zone": "Asia/Shanghai",
"min_doc_count": 0,
"extended_bounds": {
"min": tools.strtime_to_timestamp(userChoiceTime_start),
"max": tools.strtime_to_timestamp(userChoiceTime_end)
}
}
}
}
} res = self.es.search(body=body)
qpslist = res["aggregations"]["res"]["buckets"]
qlist = []
for qps in qpslist:
qlist.append({"time": qps["key_as_string"], "value": qps["doc_count"]})
data = {'code': 'SUCCESS', 'message': '', 'data': qlist}
return data

按照时间段和指定字段过滤

  def interfacedata(self,appname,startTime,endTime):

        appname = "dzgzpt-wsys"
userChoiceTime_start = "2019-04-05 09:27:27.820"
userChoiceTime_end = "2019-06-27 09:27:41.986" body = {
"size": 0,
"query": {
"filtered": {
"query": {
"query_string": {
"analyze_wildcard": True,
"query": "appname:" + appname
}
},
"filter": {
"bool": {
"must": [
{
"range": {
"@timestamp": {
"gte": tools.strtime_to_timestamp(userChoiceTime_start),
"lte": tools.strtime_to_timestamp(userChoiceTime_end)
}
}
}
]
}
}
}
},
"aggs": {
"res": {
"terms": {
"field": "interface"
},
"aggs": {
"waste_time": {
"sum": {
"field": "waste_time"
}
},
"visit": {
"terms": {
"field": "success"
}
}
}
}
}
}
res = self.es.search(body=body)
ilist=[]
for interface in res["aggregations"]["res"]["buckets"]:
wastetime = str(interface["waste_time"]["value"])
requests = interface["doc_count"]
err_express = [i["doc_count"] for i in interface["visit"]["buckets"] if i["key"] == "false"]
errcount = err_express[0] if len(err_express) > 0 else 0
ilist.append({"interface": interface["key"], "responseTime": wastetime, "requestCount": requests, "errRequest": errcount}) data = {'code': 'SUCCESS', 'message': '', 'data': ilist}
return data

对指定字段进行时间段统计

    def getdelaydata(self,appname,startTime,endTime):
appname = "dzgzpt-wsys"
userChoiceTime_start = "2019-04-05 09:27:27.820"
userChoiceTime_end = "2019-06-27 09:27:41.986"
interval = tools.set_interval(userChoiceTime_start, userChoiceTime_end)
body = {
"size": 0,
"query": {
"filtered": {
"query": {
"query_string": {
"analyze_wildcard": True,
"query": "appname:" + appname
}
},
"filter": {
"bool": {
"must": [
{
"range": {
"@timestamp": {
"gte": tools.strtime_to_timestamp(userChoiceTime_start),
"lte": tools.strtime_to_timestamp(userChoiceTime_end)
}
}
}
]
}
}
}
},
"aggs": {
"res": {
"date_histogram": {
"field": "@timestamp",
"interval": "%s" % (interval),
"time_zone": "Asia/Shanghai",
"min_doc_count": 1,
"extended_bounds": {
"min": tools.strtime_to_timestamp(userChoiceTime_start),
"max": tools.strtime_to_timestamp(userChoiceTime_end)
}
},
"aggs":
{
"avg_wastetime":
{
"avg":
{
"field": "waste_time"
}
}
}
}
}
}
res = self.es.search(body=body)
delaylist = res["aggregations"]["res"]["buckets"]
dlist = []
for de in delaylist:
dlist.append({"time": de["key_as_string"], "value": de["avg_wastetime"]['value']})
data = {'code': 'SUCCESS', 'message': '', 'data': dlist}
return data

es使用scroll实现大数据分页

 created()
{
this.getddll_data();
},
methods: {
handleClick() { },
getddll_data()
{
return this.$http.getdlList({"pageIndex":this.currentPage},{notify:true})
.then((data) =>
{
this.dyllList=data.data;
this.total=data.total;
});
},
pageChange(pageIndex)
{
this.currentPage=pageIndex;
this.getddll_data();
}
}

html

    def callLinkdata(self,jylsh,startTime,endTime,pageIndex):
body = {
"query": {
"constant_score": {
"filter": {
"term": {
"jylsh": "5b64fceb42944a699ed6a140d853f74d"
}
}
}
}
} pageIndex=int(pageIndex)
#第一(次)页查询没有scroll_id
if pageIndex == 1:
res = self.es.search(body=body,scroll='1m',size=10)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
else:
res = self.es.search(body=body, scroll='1m', size=10)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
while pageIndex -1 > 0:
res = self.es.scroll(scroll_id=scroll_id, scroll='1m')
pageIndex-=1 reslist=[]
t=1;
for re in res["hits"]["hits"]:
re = re["_source"]
reslist.append({"ID":t,"csrq":re["logtime"],"yymc":re["appname"],"zt":re["success"],"ip":re["hostname"],"type":re["type"],"server":re["serviceId"]})
t+=1
data = {'type': 'SUCCESS', 'message': '', 'data': {"total":scroll_size,"data":reslist}}
return data

后端

实现条件过滤和排序列表

    def logListdata(self,jylsh,startTime,endTime,pageIndex):
body = {
"query": {
"filtered": {
"filter": {
"bool":{
"must":
[
{"term":{"jylsh": "5b64fceb42944a699ed6a140d853f74d"}},
{
"range": {
"@timestamp":
{
"gte": tools.strtime_to_timestamp("2019-05-23 14:19:20.559"),
"lte": tools.strtime_to_timestamp("2019-05-23 14:38:54.716")
}
}
}
]
}
}
}
},
"sort": {"@timestamp": { "order": "desc" }}
} pageIndex=int(pageIndex)
#第一(次)页查询没有scroll_id
if pageIndex == 1:
res = self.es.search(body=body,scroll='1m',size=10)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
else:
res = self.es.search(body=body, scroll='1m', size=10)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
while pageIndex -1 > 0:
res = self.es.scroll(scroll_id=scroll_id, scroll='1m')
pageIndex-=1 reslist=[]
t=1;
for re in res["hits"]["hits"]:
re = re["_source"]
reslist.append({"a":re["logtime"],"b":re["appname"],"c":re["hostname"],"d":re["message"]})
t+=1
data = {'type': 'SUCCESS', 'message': '', 'data': {"total":scroll_size,"data":reslist}}
return data

python处理前后端时间字符串统一格式

2019-06-21T08:23:58.169Z   #前端提交数据
2019-06-21 16:23:58.000 #后端数据格式要求 #格式化日期字符串
def formatDate(self,timestr):
timeStruct = time.strptime(timestr, "%Y-%m-%d %H:%M:%S.%f")
strTime = time.strftime("%Y-%m-%d %H:%M:%S", timeStruct)
return strTime def formartStartTime(self,startTime):
startTime=datetime.datetime.strptime(startTime, '%Y-%m-%dT%H:%M:%S.%fZ')+datetime.timedelta(hours=8)
startTime=startTime.strftime('%Y-%m-%d %H:%M:%S.%f')[:-7]
startTime=startTime+".000"
return startTime def formartEndTime(self,endTime):
endTime=datetime.datetime.strptime(endTime, '%Y-%m-%dT%H:%M:%S.%fZ')+datetime.timedelta(hours=8)
endTime=endTime.strftime('%Y-%m-%d %H:%M:%S.%f')[:-7]
endTime=endTime+".999"
return endTime #字符串转成日期格式
import datetime
detester = ‘2017-01-01'
date = datetime.datetime.strptime(detester,’%Y-%m-%d') #日期格式转成字符串
import datetime
date = datetime.now()
detester = date.strftime(‘%Y-%m-%d')

python和vue实现最终分页效果

<template>
<div class="topology-container">
<bee-breadcrumb/>
TraceID:
<el-input
v-model="input_TraceID"
size="medium"
placeholder="TraceID"
style="width:350px;margin-right:15px;margin-bottom:15px">
</el-input>
&nbsp;&nbsp;
<el-date-picker
v-model="value2"
type="datetimerange"
:picker-options="pickerOptions"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
align="right">
</el-date-picker>
&nbsp;&nbsp;
<el-button type="primary" @click="handleQuery">查询</el-button>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane label="调用链路" name="1">
<bee-table :data="dyllList"
:column-config="LINK_TABLE_COLUMN"
:pageIndex="currentPage1"
:pageSize="pageSize1"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:total="total1">
<template slot="operation" slot-scope="{scope}">
<div class="el-progress el-progress--line el-progress--text-inside">
<div class="el-progress-bar">
<div class="el-progress-bar__outer" style="height:16px !important;">
<div class="el-progress-bar__inner" :style="styleObject(scope.row.sjz)">
<div class="el-progress-bar__innerText" style='color:black;font-size:15px'>{{scope.row.sjz}}ms</div>
</div>
</div>
</div>
</div>
</template>
</bee-table>
</el-tab-pane>
<el-tab-pane label="日志详情" name="2">
<bee-table :data="logList"
:column-config="LOG_TABLE_COLUMN"
:pageIndex="currentPage2"
:pageSize="pageSize2"
@size-change="handleSizeChange2"
@current-change="handleCurrentChange2"
:total="total2">
</bee-table>
</el-tab-pane>
</el-tabs>
</div>
</template>
<script>
import BeeBreadcrumb from '@/common/component/BeeBreadcrumb'
import BeeTable from '@/common/component/BeeTable'
import utils from '@/common/utils'
import { LINK_TABLE_COLUMN,LOG_TABLE_COLUMN } from './constants' export default {
components: {
BeeBreadcrumb,
BeeTable
},
mounted() {
this.breadcrumbList = [ ];
},
created()
{
},
data()
{
return {
total1: 0, //总记录数
total2:0,
currentPage1:1, //初始页
currentPage2:1,
pageSize1:10, // 每页的数据
pageSize2:10,
dyllList: [],
logList:[],
tableLoading: false,
LINK_TABLE_COLUMN,
LOG_TABLE_COLUMN,
pickerOptions:utils.setTimeOPtions(),
value1: [new Date(2010, 10, 10, 10, 10), new Date(2010, 10, 11, 10, 10)],
value2: '',
tabname: "1",
input_TraceID:"",
startTime:"",
endTime:""
}
},
methods: {
styleObject(sjz) {
var color="#67c23a";
if (sjz<=19)
{
sjz=19;
}
else if(sjz>20 && sjz<=60)
{
color="#e6a23c";
}
else if(sjz>60 && sjz<100)
{
color="#f56c6c";
}
else if(sjz>=100)
{
sjz=100;
color="#f56c6c";
}
return {
width: sjz+'%',
backgroundColor:color
}
},
handleClick(tab, event)
{
this.tabname=tab["name"];
},
getddll_data()
{
return this.$http.getdlList(
{
"pageIndex":this.currentPage1,
"pageSize":this.pageSize1,
"jylsh":this.input_TraceID,
"startTime":this.startTime,
"endTime":this.endTime
},{notify:true})
.then((data) =>
{
this.dyllList=data.list;
this.total1=data.total;
});
},
handleCurrentChange(pageIndex)
{
this.currentPage1=pageIndex;
this.getddll_data();
},
handleSizeChange(pageSize) {
this.currentPage1 = 1;
this.pageSize1= pageSize;
this.getddll_data();
},
getlogs_data()
{
return this.$http.getlogList(
{
"pageIndex":this.currentPage2,
"pageSize":this.pageSize2,
"jylsh":this.input_TraceID,
"startTime":this.startTime,
"endTime":this.endTime
},{notify:true})
.then((data) =>
{
this.logList=data.list;
this.total2=data.total;
});
},
handleCurrentChange2(pageIndex)
{
this.currentPage2=pageIndex;
this.getlogs_data();
},
handleSizeChange2(pageSize) {
this.currentPage2 = 1;
this.pageSize2= pageSize;
this.getlogs_data();
},
handleQuery()
{
if(this.input_TraceID=="" || this.value2 == "")
{
this.$message({
showClose: true,
message: 'TraceID和查询日期不能为空!',
type: 'warning'
});
}
else
{
this.startTime=this.value2[0];
this.endTime=this.value2[1];
if(this.tabname=="1")
{
this.getddll_data();
}
else
{
this.getlogs_data();
}
}
}
},
computed: {
activeName: {
get() {
return this.$route.query.index || '1';
},
set() {}
}
}
}
</script>
<style lang="scss" scoped>
.topology-container
{
margin:8px;
}
</style>

vue

    #链路调用查询统计
def callLinkdata(self,jylsh,startTime,endTime,pageIndex,pageSize): pageIndex=int(pageIndex)
pageSize=int(pageSize)
startTime=self.formartStartTime(startTime)
endTime=self.formartEndTime(endTime) body = {
"query": {
"filtered": {
"filter": {
"bool":{
"must":
[
{"term":{"jylsh": jylsh}},
{
"range": {
"@timestamp":
{
"gte": tools.strtime_to_timestamp(startTime),
"lte": tools.strtime_to_timestamp(endTime)
}
}
}
]
}
}
}
},
"sort": {"@timestamp": { "order": "desc" }}
} #第一(次)页查询没有scroll_id
if pageIndex == 1:
res = self.es.search(body=body,scroll='1m',size=pageSize)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
else:
res = self.es.search(body=body, scroll='1m', size=pageSize)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
while pageIndex -1 > 0:
res = self.es.scroll(scroll_id=scroll_id, scroll='1m')
pageIndex-=1 reslist=[]
for re in res["hits"]["hits"]:
re = re["_source"]
reslist.append({"csrq":self.formatDate(re["logtime"]),"yymc":re["appname"],"zt":re["success"],"ip":re["hostname"],"type":re["type"],"server":re["serviceId"],"sjz":re["waste_time"]})
data = {'code': 'SUCCESS', 'message': '', 'data': {"total":scroll_size,"list":reslist}}
return data #日志详情列表
def logListdata(self,jylsh,startTime,endTime,pageIndex,pageSize):
pageIndex = int(pageIndex)
pageSize = int(pageSize)
startTime = self.formartStartTime(startTime)
endTime = self.formartEndTime(endTime) body = {
"query": {
"filtered": {
"filter": {
"bool":{
"must":
[
{"term":{"jylsh": jylsh}},
{
"range": {
"@timestamp":
{
"gte": tools.strtime_to_timestamp(startTime),
"lte": tools.strtime_to_timestamp(endTime)
}
}
}
]
}
}
}
},
"sort": {"@timestamp": { "order": "desc" }}
} #第一(次)页查询没有scroll_id
if pageIndex == 1:
res = self.es.search(body=body,scroll='1m',size=pageSize)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
else:
res = self.es.search(body=body, scroll='1m', size=pageSize)
scroll_size = res['hits']['total']
scroll_id = res['_scroll_id']
while pageIndex -1 > 0:
res = self.es.scroll(scroll_id=scroll_id, scroll='1m')
pageIndex-=1 reslist=[]
for re in res["hits"]["hits"]:
re = re["_source"]
reslist.append({"addTime":self.formatDate(re["logtime"]),"appname":re["appname"],"hostname":re["hostname"],"message":re["message"]})
data = {'code': 'SUCCESS', 'message': '', 'data': {"total":scroll_size,"list":reslist}}
return data #格式化日期字符串
def formatDate(self,timestr):
timeStruct = time.strptime(timestr, "%Y-%m-%d %H:%M:%S.%f")
strTime = time.strftime("%Y-%m-%d %H:%M:%S", timeStruct)
return strTime def formartStartTime(self,startTime):
startTime=datetime.datetime.strptime(startTime, '%Y-%m-%dT%H:%M:%S.%fZ')+datetime.timedelta(hours=8)
startTime=startTime.strftime('%Y-%m-%d %H:%M:%S.%f')[:-7]
startTime=startTime+".000"
return startTime def formartEndTime(self,endTime):
endTime=datetime.datetime.strptime(endTime, '%Y-%m-%dT%H:%M:%S.%fZ')+datetime.timedelta(hours=8)
endTime=endTime.strftime('%Y-%m-%d %H:%M:%S.%f')[:-7]
endTime=endTime+".999"
return endTime

python

处理不同时区的时间格式转换

showDetail(traceID){
this.$router.push({
path: '/chain',
query: {"traceID":traceID,"startTime":utils.converTimeFormat(this.startTtime),"endTime": utils.converTimeFormat(this.endTime)}
});
} converTimeFormat(d){
d.setHours(d.getHours()-8);
const resDate = d.getFullYear() + '-' + this.p((d.getMonth() + 1)) + '-' + this.p(d.getDate());
const resTime = this.p(d.getHours()) + ':' + this.p(d.getMinutes()) + ':' + this.p(d.getSeconds());
const datestr = resDate+" "+resTime;
return datestr;
},
p(s){
return s < 10 ? '0' + s : s;
} this.input_TraceID = this.$route.query.traceID || '';
const startTime=this.$route.query.startTime || '';
const endTime=this.$route.query.endTime || '';
if(this.input_TraceID){ let start = new Date(startTime);
start.setHours(start.getHours()+8);
let end =new Date(endTime);
end.setHours(end.getHours()+8);
this.value2 = [start,end]; this.startTime=startTime;
this.endTime=endTime;

js处理

    def formartStartTime(self,startTime):
try:
startTime=datetime.datetime.strptime(startTime, '%Y-%m-%dT%H:%M:%S.%fZ')+datetime.timedelta(hours=8)
except Exception as e:
startTime = datetime.datetime.strptime(startTime, '%Y-%m-%d %H:%M:%S')+datetime.timedelta(hours=8)
# startTime = datetime.datetime.strptime(startTime, '%Y-%m-%dT%H:%M:%S.%fZ') + datetime.timedelta(hours=8)
startTime=startTime.strftime('%Y-%m-%d %H:%M:%S.%f')[:-7]
startTime=startTime+".000"
return startTime

python处理

实现定时查询

[root]# crontab -e
每个整点执行一次 */ * * * cd /root/estasks;sh crontb.sh vi crontb.sh #! /bin/bash
python /root/estasks/messageSend.py
python /root/estasks/messageService.py
python /root/estasks/smsService.py echo $(date "+%Y-%m-%d %H:%M:%S") >> msg.log vi msg.log -- ::
-- ::
-- ::
-- ::

crontab语法特点

crontab本身是一个后台进程 它不能执行一个要求打开输入输出终端的命令

主机上执行
       docker exec -it 934073c77e8e /root/a.sh

crontab -e
      docker exec 934073c77e8e /root/a.sh
      这里docker命令不需要加-it,因为加-it就要开启了一个终端,而计划任务是无法进入任何终端

Elasticsearch使用DateHistogram聚合的更多相关文章

  1. java使用elasticsearch分组进行聚合查询(group by)-项目中实际应用

    java连接elasticsearch 进行聚合查询进行相应操作 一:对单个字段进行分组求和 1.表结构图片: 根据任务id分组,分别统计出每个任务id下有多少个文字标题 .SQL:select id ...

  2. python 使用 elasticsearch 常用方法(聚合)

    #记录聚合查询方法 from elasticsearch import Elasticsearch es = Elasticsearch(['xx.xx.xx.xx:9200']) #获取最小的年龄r ...

  3. 小试牛刀ElasticSearch大数据聚合统计

    ElasticSearch相信有不少朋友都了解,即使没有了解过它那相信对ELK也有所认识E即是ElasticSearch.ElasticSearch最开始更多用于检索,作为一搜索的集群产品简单易用绝对 ...

  4. Elasticsearch强大的聚合功能Facet

    在常规数据库中,我们都知道有一个sql就是group,分组.如果主表只有对应的一个列记录的分组的ID,那么还好统计,比如说每本书book表,有一个分类catId,记录是属于哪一类的书,那么直接按照ca ...

  5. elasticsearch按范围聚合

    范围聚合适用于对数据按照指定范围进行分类聚合的应用场景,from和to表示范围起始值的半开半闭区间(包含from值不包含to值),key表示别名 如 {:key=>"2h", ...

  6. elasticsearch 权威指南聚合阅读笔记(七)

    count(1) select clssId,count(1) from student group by  classId { "size":0, "aggs" ...

  7. 读《深入理解Elasticsearch》点滴-聚合-top_hits

    以下是官网手册(部分)(v5.1) 直接直接看官网手册 https://www.elastic.co/guide/en/elasticsearch/reference/5.1/search-aggre ...

  8. ElasticSearch Cardinality Aggregation聚合计算的误差

    使用ES不久,今天发现生产环境数据异常,其使用的ES版本是2.1.2,其它版本也类似.通过使用ES的HTTP API进行查询,发现得到的数据跟javaClient API 查询得到的数据不一致,于是对 ...

  9. elasticsearch 多字段聚合或者对字段子串聚合

    以下是字段子串聚合,截取 'your_field' 前八位进行聚合的 Script script = new Script("doc['your_field'].getValue().sub ...

随机推荐

  1. three.js 基础使用1

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  2. ERROR:Simulator861-Failed to link the design解决办法

    在安装目录下找到collect2.exe文件,删除就可以解决了.D:\install_dir\ISE2\14.7\ISE_DS\ISE\gnu\MinGW\5.0.0\nt\libexec\gcc\m ...

  3. shell脚本-练习1

  4. Java 并发系列之七:java 阻塞队列(7个)

    1. 基本概念 2. 实现原理 3. ArrayBlockingQueue 4. LinkedBlockingQueue 5. LinkedBlockingDeque 6. PriorityBlock ...

  5. 苹果 appstore 上架 ipv6 服务 配置

    前言 好久之前的事了,苹果审核突然要求ipv6,一片哀嚎. 研究了好久找到了基于阿里云经典网络Windows Server的配置方法. https://bbs.aliyun.com/read/2849 ...

  6. git使用问题与技巧

    1.修改gitolite管理员 如果gitolite原来的管理员已经没了,那么需要把当前的公钥放到服务器覆盖,然后替换目录下.ssh/authorized_keys内容 2.clone报告超过限制 w ...

  7. 【Gamma】PhyLab 测试报告

    PhyLab Gamma测试报告 测试中发现的bug Gamma阶段新Bug Bug 可能原因 部分错误码设置与原先抛异常的逻辑冲突 原先代码中使用了一些特殊的办法处理异常 Beta未发现Bug Bu ...

  8. Gamma阶段事后分析

    设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件要解决的是安卓游戏的自动化异常检测问题,定义的足够清楚,对于典型用户的描述和典型场景的描述也足 ...

  9. C#内存泄露与资源释放 经验总结

    本文链接:http://blog.csdn.net/yokeqi/article/details/41083939 C#相比其他语言,拥有强大的垃圾回收机制,但并不是这样,你就可以对内存管理放任不管, ...

  10. es6 Decorator修饰器

    1.类的修饰: 修饰器(Decorator)函数,用来修改类的行为.修饰器是一个对类进行处理的函数.修饰器函数的第一个参数,就是所要修饰的目标类. @testable class MyTestable ...