redis.tmpl 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. {{template "header.tmpl" .}}
  2. <style type="text/css">
  3. #filterform{
  4. margin: 10px 0px;
  5. }
  6. #filterform .form-group{
  7. margin-right: 20px;
  8. }
  9. </style>
  10. </head>
  11. <body>
  12. {{template "navbar.tmpl" .}}
  13. <div class="container-fluid">
  14. <h4 class="text-center">Redis服务列表 <small>[<a href="#" id="add_btn"><i class="glyphicon glyphicon-plus"></i> 点击这里添加</a>]</small></h4>
  15. <hr />
  16. <table class="table table-bordered" style="margin-bottom:0px;">
  17. <thead>
  18. <tr>
  19. <th>ID</th>
  20. <th>服务地址</th>
  21. <th>备注名</th>
  22. <th>连接密码</th>
  23. <th>连接超时(秒)&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="连接超时(单位:秒)" data-content="检测Redis状态时如果连接操作超过该值将会被认为Redis状态异常。" onclick="return false;">?</a></th>
  24. <th>最大失败次数&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="最大失败次数" data-content="如果Redis状态检测失败连续失败次数达到该值将会触发报警。" onclick="return false;">?</a></th>
  25. <th>最小剩余内存&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="最小剩余内存" data-content="Redis最小可用的内存空间值,低于该值将会触发自动扩容操作。" onclick="return false;">?</a></th>
  26. <th>单次扩容大小&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="单次扩容大小" data-content="Redis剩余不足需要扩容时将会增加该数值指定大小的内存空间。" onclick="return false;">?</a></th>
  27. <th>最大内存使用&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="最大内存使用" data-content="自动扩容的内存上限,Redis的内存使用达到该值将不再自动扩容。" onclick="return false;">?</a></th>
  28. <th>最大连接数&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="最大连接数" data-content="Redis的最大并发连接数,达到该值将会触发报警。" onclick="return false;">?</a></th>
  29. <th>最大新增淘汰数&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="最大新增淘汰数" data-content="上次检测之后增加的淘汰记录数上限,达到该值后将触发报警。" onclick="return false;">?</a></th>
  30. <th>最大QPS&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="最大QPS" data-content="Redis的最大QPS值,达到该值将会触发报警。" onclick="return false;">?</a></th>
  31. <th>报警邮箱列表&nbsp;<a href="#" data-toggle="popover" data-trigger="focus" title="报警邮箱列表" data-content="接收报警邮件的邮箱地址列表,与邮件组合并后作为接收报警邮箱的邮箱列表。" onclick="return false;">?</a></th>
  32. <th>状态</th>
  33. <th>操作</th>
  34. </tr>
  35. </thead>
  36. <tbody id="list"></tbody>
  37. </table>
  38. </div>
  39. <script type="text/javascript">
  40. var $SESS = {{.Sess}};
  41. $(function(){
  42. //加载列表
  43. function redis_list() {
  44. var list = $('#list');
  45. list.empty();
  46. $.post('/syscfg/redis_list', {}, function(resp){
  47. if (resp && resp.errno == 0 && resp.data) {
  48. var html = '';
  49. for (var i=0; i<resp.data.length; i++) {
  50. var item = resp.data[i];
  51. html += '<tr>';
  52. html += '<td>' + item.Id + '</td>';
  53. html += '<td>' + item.Address + '</td>';
  54. html += '<td>' + (item.Remark == '' ? '<i class="text-muted">无</i>' : item.Remark) + '</td>';
  55. html += '<td>' + (item.Password == '' ? '<i class="text-muted">无</i>' : item.Password) + '</td>';
  56. html += '<td>' + item.MaxConnectWait + '</td>';
  57. html += '<td>' + item.MaxStatusFailed + '</td>';
  58. html += '<td>' + size2str(item.MinMemoryFree) + '</td>';
  59. html += '<td>' + size2str(item.StepMemoryIncrease) + '</td>';
  60. html += '<td>' + size2str(item.MaxMemoryUsage) + '</td>';
  61. html += '<td>' + numberFormat(item.MaxConnection) + '</td>';
  62. html += '<td>' + item.MaxEviIncreased + '</td>';
  63. html += '<td>' + numberFormat(item.MaxQPS) + '</td>';
  64. html += '<td>' + (item.MailList == '' ? '<i class="text-muted">无</i>' : item.MailList) + '</td>';
  65. html += '<td' + (item.Disabled ? ' class="text-danger"' : '') + '>' + (item.Disabled ? '禁用' : '正常') + '</td>';
  66. html += '<td>';
  67. html += ' <button class="btn btn-xs btn-primary" type="button" data-value="' + item.Id + '">编辑</button>&nbsp;';
  68. html += ' <button class="btn btn-xs btn-danger" type="button" data-value="' + item.Id + '">删除</button>';
  69. html += '</td>';
  70. html += '</tr>';
  71. }
  72. list.html(html);
  73. //修改
  74. $('.btn-primary', list).click(function(){
  75. var id = $(this).attr('data-value');
  76. $.get('/syscfg/redis_get', {'id': id}, function(resp){
  77. if (resp && resp.errno == 0) {
  78. redis_set(resp.data);
  79. }
  80. }, 'json');
  81. return false;
  82. });
  83. //删除
  84. $('.btn-danger', list).click(function(){
  85. var id = $(this).attr('data-value');
  86. $.alert({
  87. 'content': '确定要删除该记录吗?',
  88. 'btncancel': true,
  89. 'callback': function() {
  90. $.post('/syscfg/redis_del', {'id': id}, function(resp){
  91. if (resp && resp.errno == 0) {
  92. redis_list();
  93. } else {
  94. $.alert({'content': resp.error ? resp.error : '操作失败!'});
  95. }
  96. }, 'json');
  97. }
  98. });
  99. });
  100. }
  101. }, 'json');
  102. return false;
  103. }
  104. //添加或修改记录
  105. function redis_set(record){
  106. record = $.extend({
  107. 'Id': 0,
  108. 'Address': '',
  109. 'Remark': '',
  110. 'Password': '',
  111. 'MaxConnectWait': 5,
  112. 'MaxStatusFailed': 1,
  113. 'MinMemoryFree': 10*1024*1024,
  114. 'StepMemoryIncrease': 100*1024*1024,
  115. 'MaxMemoryUsage': 500*1024*1024,
  116. 'MaxConnection': 1024,
  117. 'MaxEviIncreased': 1,
  118. 'MaxQPS': 30000,
  119. 'MailList': '',
  120. 'Disabled': false
  121. }, record);
  122. var html = `<form class="form-horizontal">
  123. <div class="form-group id-group" style="display:none;">
  124. <label class="col-md-4 control-label">ID</label>
  125. <div class="col-md-8">
  126. <input type="text" class="form-control" name="Id" maxlength="20" value="${record.Id}" readonly="readonly" />
  127. </div>
  128. </div>
  129. <div class="form-group">
  130. <label class="col-md-4 control-label">服务地址(IP:端口)</label>
  131. <div class="col-md-8">
  132. <input type="text" class="form-control" name="Address" maxlength="20" value="${record.Address}" placeholder="IP或域名:端口" />
  133. </div>
  134. </div>
  135. <div class="form-group">
  136. <label class="col-md-4 control-label">备注名称</label>
  137. <div class="col-md-8">
  138. <input type="text" class="form-control" name="Remark" maxlength="20" value="${record.Remark}" placeholder="用于后台展示" />
  139. </div>
  140. </div>
  141. <div class="form-group">
  142. <label class="col-md-4 control-label">连接密码</label>
  143. <div class="col-md-8">
  144. <input type="text" class="form-control" name="Password" maxlength="20" value="${record.Password}" placeholder="未设置密码时留空" />
  145. </div>
  146. </div>
  147. <div class="form-group">
  148. <label class="col-md-4 control-label">连接超时时长(秒)</label>
  149. <div class="col-md-8">
  150. <div class="input-group" style="width:100px;">
  151. <input type="text" class="form-control" name="MaxConnectWait" maxlength="2" value="${record.MaxConnectWait}" />
  152. <div class="input-group-addon">秒</div>
  153. </div>
  154. <p class="help-block">连接等待时长超过该值将当作失败处理</p>
  155. </div>
  156. </div>
  157. <div class="form-group">
  158. <label class="col-md-4 control-label">最大状态检测失败次数</label>
  159. <div class="col-md-8">
  160. <div class="input-group" style="width:100px;">
  161. <input type="text" class="form-control" name="MaxStatusFailed" maxlength="2" value="${record.MaxStatusFailed}" />
  162. <div class="input-group-addon">次</div>
  163. </div>
  164. <p class="help-block">连续失败次数达到该值将会触发报警</p>
  165. </div>
  166. </div>
  167. <div class="form-group">
  168. <label class="col-md-4 control-label">最小可用内存空间</label>
  169. <div class="col-md-8">
  170. <div class="input-group">
  171. <input type="text" class="form-control" name="MinMemoryFree" maxlength="10" value="${record.MinMemoryFree}" />
  172. <div class="input-group-btn" data-toggle="buttons">
  173. <label class="btn btn-default active" data-value="1"><input type="radio" autocomplete="off" /> Byte</label>
  174. <label class="btn btn-default" data-value="1024"><input type="radio" autocomplete="off" /> KB</label>
  175. <label class="btn btn-default" data-value="1048576"><input type="radio" autocomplete="off" /> MB</label>
  176. <label class="btn btn-default" data-value="1073741824"><input type="radio" autocomplete="off" /> GB</label>
  177. </div>
  178. </div>
  179. <p class="help-block">正整数,低于该值将自动扩容,设置0跳过该检查项</p>
  180. </div>
  181. </div>
  182. <div class="form-group">
  183. <label class="col-md-4 control-label">单次扩容大小</label>
  184. <div class="col-md-8">
  185. <div class="input-group">
  186. <input type="text" class="form-control" name="StepMemoryIncrease" maxlength="10" value="${record.StepMemoryIncrease}" />
  187. <div class="input-group-btn" data-toggle="buttons">
  188. <label class="btn btn-default active" data-value="1"><input type="radio" autocomplete="off" /> Byte</label>
  189. <label class="btn btn-default" data-value="1024"><input type="radio" autocomplete="off" /> KB</label>
  190. <label class="btn btn-default" data-value="1048576"><input type="radio" autocomplete="off" /> MB</label>
  191. <label class="btn btn-default" data-value="1073741824"><input type="radio" autocomplete="off" /> GB</label>
  192. </div>
  193. </div>
  194. <p class="help-block">正整数,剩余空间不足需要扩容时将增加该值指定大小的内存</p>
  195. </div>
  196. </div>
  197. <div class="form-group">
  198. <label class="col-md-4 control-label">最大使用内存上限</label>
  199. <div class="col-md-8">
  200. <div class="input-group">
  201. <input type="text" class="form-control" name="MaxMemoryUsage" maxlength="10" value="${record.MaxMemoryUsage}" />
  202. <div class="input-group-btn" data-toggle="buttons">
  203. <label class="btn btn-default active" data-value="1"><input type="radio" autocomplete="off" /> Byte</label>
  204. <label class="btn btn-default" data-value="1024"><input type="radio" autocomplete="off" /> KB</label>
  205. <label class="btn btn-default" data-value="1048576"><input type="radio" autocomplete="off" /> MB</label>
  206. <label class="btn btn-default" data-value="1073741824"><input type="radio" autocomplete="off" /> GB</label>
  207. </div>
  208. </div>
  209. <p class="help-block">正整数,已用内存达到该值将不再自动扩容</p>
  210. </div>
  211. </div>
  212. <div class="form-group">
  213. <label class="col-md-4 control-label">最大客户端并发连接数</label>
  214. <div class="col-md-8">
  215. <div class="input-group" style="width:150px;">
  216. <input type="text" class="form-control" name="MaxConnection" maxlength="10" value="${record.MaxConnection}" />
  217. <div class="input-group-addon">个</div>
  218. </div>
  219. <p class="help-block">超过该值将会触发报警</p>
  220. </div>
  221. </div>
  222. <div class="form-group">
  223. <label class="col-md-4 control-label">最大新增淘汰记录数</label>
  224. <div class="col-md-8">
  225. <div class="input-group" style="width:100px;">
  226. <input type="text" class="form-control" name="MaxEviIncreased" maxlength="5" value="${record.MaxEviIncreased}" />
  227. <div class="input-group-addon">个</div>
  228. </div>
  229. <p class="help-block">超过该值将会触发报警</p>
  230. </div>
  231. </div>
  232. <div class="form-group">
  233. <label class="col-md-4 control-label">最大QPS上限值</label>
  234. <div class="col-md-8">
  235. <div class="input-group" style="width:150px;">
  236. <input type="text" class="form-control" name="MaxQPS" maxlength="10" value="${record.MaxQPS}" />
  237. <div class="input-group-addon">次/s</div>
  238. </div>
  239. <p class="help-block">超过该值将会触发报警</p>
  240. </div>
  241. </div>
  242. <div class="form-group">
  243. <label class="col-md-4 control-label">报警邮件接收邮箱列表<br />(多个之间使用“;”间隔)</label>
  244. <div class="col-md-8">
  245. <textarea class="form-control" name="MailList" rows="4" maxlength="1000">${record.MailList}</textarea>
  246. </div>
  247. </div>
  248. <div class="form-group">
  249. <label class="col-md-4 control-label">状态</label>
  250. <div class="col-md-8">
  251. <select class="form-control" name="Disabled" style="width:100px;">
  252. <option value="0">正常</option>
  253. <option value="1">禁用</option>
  254. </select>
  255. </div>
  256. </div>
  257. </form>`;
  258. $.alert({
  259. 'title': record.Id == 0 ? '添加新配置' : '修改配置',
  260. 'content': html,
  261. 'init': function(dlg) {
  262. var form = $('form', dlg).get(0);
  263. form.Disabled.value = record.Disabled ? '1' : '0';
  264. $(form.MinMemoryFree).change(function(){
  265. this.value = numberFormat(this.value);
  266. });
  267. $(form.MaxMemoryUsage).change(function(){
  268. this.value = numberFormat(this.value);
  269. });
  270. $(form.StepMemoryIncrease).change(function(){
  271. this.value = numberFormat(this.value);
  272. });
  273. $(form.MinMemoryFree).change();
  274. $(form.MaxMemoryUsage).change();
  275. $(form.StepMemoryIncrease).change();
  276. if (record.Id == 0) {
  277. $('.id-group', dlg).hide();
  278. } else {
  279. $('.id-group', dlg).show();
  280. }
  281. },
  282. 'callback': function(dlg){
  283. var form = $('form', dlg).get(0);
  284. var MinMemoryFreeTimes = parseInt($('label.active', $(form.MinMemoryFree).parent()).attr('data-value'));
  285. var MaxMemoryUsageTimes = parseInt($('label.active', $(form.MaxMemoryUsage).parent()).attr('data-value'));
  286. var StepMemoryIncreaseTimes = parseInt($('label.active', $(form.StepMemoryIncrease).parent()).attr('data-value'));
  287. console.debug(MinMemoryFreeTimes, MaxMemoryUsageTimes, StepMemoryIncreaseTimes);
  288. form.MinMemoryFree.value = parseInt(form.MinMemoryFree.value.replace(/,/g, '')) * MinMemoryFreeTimes;
  289. form.MaxMemoryUsage.value = parseInt(form.MaxMemoryUsage.value.replace(/,/g, '')) * MaxMemoryUsageTimes;
  290. form.StepMemoryIncrease.value = parseInt(form.StepMemoryIncrease.value.replace(/,/g, '')) * StepMemoryIncreaseTimes;
  291. $('.input-group-btn label', form).removeClass('active');
  292. $('.input-group-btn :first-child', form).addClass('active');
  293. if (form.Address.value == '') {
  294. $.alert({'content': '请填写Redis的服务地址!'});
  295. } else if (!/[0-9A-Za-z.\-]+:\d{3,5}$/.test(form.Address.value)) {
  296. $.alert({'content': 'Redis服务地址格式不正确!'});
  297. } else if (form.Remark.value == '') {
  298. $.alert({'content': '请填写备注名称!'});
  299. } else if (/\D/.test(form.MaxConnectWait.value)) {
  300. $.alert({'content': '请填写正确的连接超时时长!'});
  301. } else if (/\D/.test(form.MaxStatusFailed.value)) {
  302. $.alert({'content': '请填写正确的最大状态检测失败次数!'});
  303. } else if (/\D/.test(form.MinMemoryFree.value)) {
  304. $.alert({'content': '请填写正确的最小可用内存空间(字节)!'});
  305. } else if (/\D/.test(form.StepMemoryIncrease.value)) {
  306. $.alert({'content': '请填写正确的单次扩容大小!'});
  307. } else if (/\D/.test(form.MaxMemoryUsage.value)) {
  308. $.alert({'content': '请填写正确的最大使用内存上限!'});
  309. } else if (/\D/.test(form.MaxConnection.value)) {
  310. $.alert({'content': '请填写正确的最大客户端并发连接数!'});
  311. } else if (/\D/.test(form.MaxEviIncreased.value)) {
  312. $.alert({'content': '请填写正确的最大新增淘汰记录数!'});
  313. } else if (/\D/.test(form.MaxQPS.value)) {
  314. $.alert({'content': '请填写正确的最大QPS上限值!'});
  315. } else if (form.MailList.value == '') {
  316. $.alert({'content': '请填写报警邮件接收邮箱列表!'});
  317. } else {
  318. $.post('/syscfg/redis_set', $(form).serialize(), function(resp){
  319. if (resp && resp.errno == 0) {
  320. redis_list();
  321. } else {
  322. $.alert({'content': resp.error ? resp.error : '操作失败!'});
  323. }
  324. }, 'json');
  325. return true;
  326. }
  327. return false;
  328. },
  329. 'btncancel': true
  330. });
  331. return false;
  332. }
  333. redis_list(); //加载页面
  334. $('#add_btn').click(redis_set); //添加按钮
  335. $('[data-toggle="popover"]').popover(); //tips
  336. });
  337. </script>
  338. </body>
  339. </html>