实现健康检查配置、立即执行健康检查

This commit is contained in:
GoEdgeLab
2020-10-17 21:15:22 +08:00
parent 282900d611
commit bbe6253346
28 changed files with 500 additions and 115 deletions

View File

@@ -0,0 +1,168 @@
Vue.component("health-check-config-box", {
props: ["v-health-check-config"],
data: function () {
let healthCheckConfig = this.vHealthCheckConfig
let urlProtocol = "http"
let urlPort = ""
let urlRequestURI = "/"
if (healthCheckConfig == null) {
healthCheckConfig = {
isOn: false,
url: "",
interval: {count: 60, unit: "second"},
statusCodes: [200],
timeout: {count: 10, unit: "second"},
countTries: 3,
tryDelay: {count: 100, unit: "ms"}
}
let that = this
setTimeout(function () {
that.changeURL()
}, 500)
} else {
let url = new URL(healthCheckConfig.url)
urlProtocol = url.protocol.substring(0, url.protocol.length - 1)
urlPort = url.port
urlRequestURI = url.pathname
if (url.search.length > 0) {
urlRequestURI += url.search
}
}
return {
healthCheck: healthCheckConfig,
advancedVisible: false,
urlProtocol: urlProtocol,
urlPort: urlPort,
urlRequestURI: urlRequestURI
}
},
watch: {
urlRequestURI: function () {
if (this.urlRequestURI.length > 0 && this.urlRequestURI[0] != "/") {
this.urlRequestURI = "/" + this.urlRequestURI
}
this.changeURL()
},
urlPort: function (v) {
let port = parseInt(v)
if (!isNaN(port)) {
this.urlPort = port.toString()
} else {
this.urlPort = ""
}
this.changeURL()
},
urlProtocol: function () {
this.changeURL()
},
"healthCheck.countTries": function (v) {
let count = parseInt(v)
if (!isNaN(count)) {
this.healthCheck.countTries = count
} else {
this.healthCheck.countTries = 0
}
}
},
methods: {
showAdvanced: function () {
this.advancedVisible = !this.advancedVisible
},
changeURL: function () {
this.healthCheck.url = this.urlProtocol + "://${host}" + ((this.urlPort.length > 0) ? ":" + this.urlPort : "") + this.urlRequestURI
},
changeStatus: function (values) {
this.healthCheck.statusCodes = values.$map(function (k, v) {
let status = parseInt(v)
if (isNaN(status)) {
return 0
} else {
return status
}
})
console.log(this.healthCheck.statusCodes)
}
},
template: `<div>
<input type="hidden" name="healthCheckJSON" :value="JSON.stringify(healthCheck)"/>
<table class="ui table definition selectable">
<tbody>
<tr>
<td class="title">是否启用</td>
<td>
<div class="ui checkbox">
<input type="checkbox" value="1" v-model="healthCheck.isOn"/>
<label></label>
</div>
</td>
</tr>
</tbody>
<tbody v-show="healthCheck.isOn">
<tr>
<td>URL *</td>
<td>
<div class="ui fields inline">
<div class="ui field">
<select class="ui dropdown" v-model="urlProtocol">
<option value="http">http://</option>
<option value="https">https://</option>
</select>
</div>
<div class="ui field">
<var style="color:grey">\${host}</var>
</div>
<div class="ui field">:</div>
<div class="ui field">
<input type="text" maxlength="5" style="width:5.4em" placeholder="端口" v-model="urlPort"/>
</div>
<div class="ui field">
<input type="text" v-model="urlRequestURI" placeholder="/" style="width:23em"/>
</div>
</div>
<div class="ui divider"></div>
<p class="comment" v-if="healthCheck.url.length > 0">拼接后的URL<code-label>{{healthCheck.url}}</code-label>,其中\${host}指的是节点地址。</p>
</td>
</tr>
<tr>
<td>检测时间间隔</td>
<td>
<time-duration-box :v-value="healthCheck.interval"></time-duration-box>
</td>
</tr>
</tbody>
<tbody v-show="healthCheck.isOn">
<tr>
<td colspan="2"><more-options-angle @change="showAdvanced"></more-options-angle></td>
</tr>
</tbody>
<tbody v-show="advancedVisible && healthCheck.isOn">
<tr>
<td>允许的状态码</td>
<td>
<values-box :values="healthCheck.statusCodes" maxlength="3" @change="changeStatus"></values-box>
</td>
</tr>
<tr>
<td>超时时间</td>
<td>
<time-duration-box :v-value="healthCheck.timeout"></time-duration-box>
</td>
</tr>
<tr>
<td>连续尝试次数</td>
<td>
<input type="text" v-model="healthCheck.countTries" style="width: 5em" maxlength="2"/>
</td>
</tr>
<tr>
<td>每次尝试间隔</td>
<td>
<time-duration-box :v-value="healthCheck.tryDelay"></time-duration-box>
</td>
</tr>
</tbody>
</table>
<div class="margin"></div>
</div>`
})

View File

@@ -37,10 +37,12 @@ Vue.component("values-box", {
} else {
this.vValues.push(this.value);
}
this.cancel();
this.cancel()
this.$emit("change", this.vValues)
},
remove: function (index) {
this.vValues.$remove(index);
this.vValues.$remove(index)
this.$emit("change", this.vValues)
},
cancel: function () {
this.isUpdating = false;

View File

@@ -8,6 +8,8 @@ Vue.component("node-ip-addresses-box", {
methods: {
// 添加IP地址
addIPAddress: function () {
window.UPDATING_NODE_IP_ADDRESS = null
let that = this;
teaweb.popup("/nodes/ipAddresses/createPopup", {
callback: function (resp) {
@@ -18,8 +20,10 @@ Vue.component("node-ip-addresses-box", {
// 修改地址
updateIPAddress: function (index, address) {
window.UPDATING_NODE_IP_ADDRESS = address
let that = this;
teaweb.popup("/nodes/ipAddresses/updatePopup?addressId=" + address.id, {
teaweb.popup("/nodes/ipAddresses/updatePopup", {
callback: function (resp) {
Vue.set(that.ipAddresses, index, resp.data.ipAddress);
}
@@ -32,11 +36,13 @@ Vue.component("node-ip-addresses-box", {
}
},
template: `<div>
<input type="hidden" name="ipAddresses" :value="JSON.stringify(ipAddresses)"/>
<input type="hidden" name="ipAddressesJSON" :value="JSON.stringify(ipAddresses)"/>
<div v-if="ipAddresses.length > 0">
<div>
<div v-for="(address, index) in ipAddresses" class="ui label small">
{{address.ip}}<span class="small" v-if="address.name.length > 0">{{address.name}}</span>
{{address.ip}}
<span class="small" v-if="address.name.length > 0">{{address.name}}<span v-if="!address.canAccess">,不可访问</span></span>
<span class="small" v-if="address.name.length == 0 && !address.canAccess">(不可访问)</span>
<a href="" title="修改" @click.prevent="updateIPAddress(index, address)"><i class="icon pencil small"></i></a>
<a href="" title="删除" @click.prevent="removeIPAddress(index)"><i class="icon remove"></i></a>
</div>
@@ -46,6 +52,5 @@ Vue.component("node-ip-addresses-box", {
<div>
<button class="ui button small" type="button" @click.prevent="addIPAddress()">+</button>
</div>
<p class="comment">添加已经绑定的IP地址仅做记录用。</p>
</div>`
})

View File

@@ -1,7 +1,5 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "menu"}
<form class="ui form segment" action="/clusters/cluster">
@@ -61,7 +59,10 @@
<span v-if="node.ipAddresses.length == 0">-</span>
<div v-else class="address-box">
<div v-for="addr in node.ipAddresses" style="margin-bottom:0.3em">
<div class="ui label tiny">{{addr.ip}} <span class="small">{{addr.name}}</span></div>
<div class="ui label tiny">{{addr.ip}}
<span class="small" v-if="addr.name.length > 0">{{addr.name}}<span v-if="!addr.canAccess">,不可访问</span></span>
<span class="small" v-if="addr.name.length == 0 && !addr.canAccess">(不可访问)</span>
</div>
</div>
</div>
</td>
@@ -98,5 +99,4 @@
</table>
<div class="page" v-html="page"></div>
</div>
<div class="page" v-html="page"></div>

View File

@@ -1,7 +1,5 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "menu"}
<p>可以通过节点安装包中的<code-label>configs/cluster.yaml</code-label>直接自动注册节点。</p>
<table class="ui table definition selectable">
@@ -16,5 +14,4 @@ clusterId: "{{cluster.uniqueId}}"
secret: "{{cluster.secret}}"</pre>
</td>
</tr>
</table>
</div>
</table>

View File

@@ -1,4 +1,6 @@
<second-menu>
<menu-item :href="'/clusters/cluster?clusterId=' + clusterId">节点列表</menu-item>
<span class="item">|</span>
<menu-item :href="'/clusters/cluster/node?clusterId=' + clusterId + '&nodeId=' + nodeId" code="node">节点详情</menu-item>
<menu-item :href="'/clusters/cluster/node/logs?clusterId=' + clusterId + '&nodeId=' + nodeId" code="log">运行日志</menu-item>
<menu-item :href="'/clusters/cluster/node/update?clusterId=' + clusterId + '&nodeId=' + nodeId" code="update">修改设置</menu-item>

View File

@@ -1,7 +1,5 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "/clusters/cluster/menu"}
<form class="ui form" data-tea-action="$" data-tea-success="success">
@@ -41,5 +39,4 @@
</tr>
</table>
<submit-btn></submit-btn>
</form>
</div>
</form>

View File

@@ -1,7 +1,5 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "node_menu"}
<!-- 已安装 -->
@@ -53,5 +51,4 @@ secret: "{{node.secret}}"</pre>
</table>
<a href="" @click.prevent="updateNodeIsInstalled(true)">[修改为已安装状态]</a>
</div>
</div>
</div>

View File

@@ -1,7 +1,5 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "node_menu"}
<p class="comment" v-if="logs.length == 0">暂时还没有日志。</p>
@@ -19,5 +17,4 @@
</tr>
</table>
<div class="page" v-html="page"></div>
</div>
<div class="page" v-html="page"></div>

View File

@@ -1,7 +1,5 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "node_menu"}
<h3>节点详情</h3>
@@ -19,8 +17,10 @@
<td>
<div v-if="node.ipAddresses.length > 0">
<div>
<div v-for="(address, index) in node.ipAddresses" class="ui label small">
{{address.ip}}<span class="small">{{address.name}}</span>
<div v-for="(address, index) in node.ipAddresses" class="ui label tiny">
{{address.ip}}
<span class="small" v-if="address.name.length > 0">{{address.name}}<span v-if="!address.canAccess">,不可访问</span></span>
<span class="small" v-if="address.name.length == 0 && !address.canAccess">(不可访问)</span>
</div>
</div>
</div>
@@ -97,5 +97,4 @@
<a v-else :href="'/clusters/cluster/installNode?clusterId=' + clusterId + '&nodeId=' + nodeId" class="underline" title="点击进入安装界面"><span class="red">未安装</span></a>
</td>
</tr>
</table>
</div>
</table>

View File

@@ -1,7 +1,5 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
{$template "node_menu"}
<h3>修改节点</h3>
@@ -76,5 +74,4 @@
</tbody>
</table>
<submit-btn></submit-btn>
</form>
</div>
</form>

View File

@@ -0,0 +1,10 @@
{$layout}
{$template "/left_menu"}
<div class="right-box">
<form class="ui form" data-tea-action="$" data-tea-success="success">
<input type="hidden" name="clusterId" :value="clusterId"/>
<health-check-config-box :v-health-check-config="healthCheckConfig"></health-check-config-box>
<submit-btn></submit-btn> &nbsp; <a href="" @click.prevent="run()">立即检查</a>
</form>
</div>

View File

@@ -0,0 +1,11 @@
Tea.context(function () {
this.success = NotifyReloadSuccess("保存成功")
this.run = function () {
teaweb.confirm("确定要对当前集群下的所有节点进行健康检查吗?", function () {
teaweb.popup("/clusters/cluster/settings/healthRun?clusterId=" + this.clusterId, {
})
})
}
})

View File

@@ -0,0 +1,27 @@
{$layout "layout_popup"}
<h3>健康检查</h3>
<span class="red" v-if="isRequesting">正在执行中,请等待执行完毕...</span>
<form class="ui form" v-if="!isRequesting">
<p>成功节点:<span class="green">{{countSuccess}}</span> &nbsp; 失败节点:<span class="red">{{countFail}}</span></p>
<table class="ui table selectable">
<thead>
<tr>
<th>节点</th>
<th>结果</th>
<th>耗时</th>
</tr>
</thead>
<tr v-for="result in results">
<td>{{result.node.name}}<span class="small" v-if="result.nodeAddr != null && result.nodeAddr.length > 0">{{result.nodeAddr}}</span></td>
<td>
<span v-if="!result.isOk" class="red">失败:{{result.error}}</span>
<span v-else class="green">成功</span>
</td>
<td>{{result.costMs}}ms</td>
</tr>
</table>
<button class="ui button primary" type="button" @click.prevent="success">完成</button>
</form>

View File

@@ -0,0 +1,39 @@
Tea.context(function () {
this.success = NotifyPopup
this.isRequesting = false
this.results = []
this.countSuccess = 0
this.countFail = 0
this.$delay(function () {
this.run()
})
this.run = function () {
this.isRequesting = true
this.$post("$")
.params({
clusterId: this.clusterId
})
.success(function (resp) {
this.results = resp.data.results
let that = this
this.results.forEach(function (v) {
v.costMs = Math.ceil(v.costMs)
if (isNaN(v.costMs)) {
v.costMs = 0
}
if (v.isOk) {
that.countSuccess++
} else {
that.countFail++
}
})
})
.done(function () {
this.isRequesting = false
})
}
})

View File

@@ -10,6 +10,16 @@
<input type="text" name="ip" maxlength="128" ref="focus"/>
</td>
</tr>
<tr>
<td>是否可以访问</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="canAccess" value="1" checked="checked"/>
<label></label>
</div>
<p class="comment">是否为可以公开访问的IP。</p>
</td>
</tr>
<tr>
<td class="title">备注</td>
<td>

View File

@@ -11,6 +11,16 @@
<input type="text" name="ip" maxlength="128" ref="focus" v-model="address.ip"/>
</td>
</tr>
<tr>
<td>是否可以访问</td>
<td>
<div class="ui checkbox">
<input type="checkbox" name="canAccess" value="1" v-model="address.canAccess"/>
<label></label>
</div>
<p class="comment">是否为可以公开访问的IP。</p>
</td>
</tr>
<tr>
<td class="title">备注</td>
<td>

View File

@@ -1,3 +1,5 @@
Tea.context(function (){
Tea.context(function () {
this.success = NotifyPopup;
this.address = window.parent.UPDATING_NODE_IP_ADDRESS
});