Authored by 陈峰

cache 清除开发完成

... ... @@ -8,11 +8,14 @@ const influx = require('influx');
let client = influx({
hosts: [{
host: 'influxdblog.yohoops.org',
//host: 'influxdblog.yohoops.org',
//port: 8086,
host: '127.0.0.1',
port: 8086,
protocol: 'http'
}],
database: 'udp'
//database: 'udp'
database: 'test'
});
const db = {
... ...
... ... @@ -8,6 +8,7 @@ import DeployModel from './deploy';
import UserModel from './user';
import HotfixModel from './hotfix';
import OperationLoggerModel from './operation_logger';
import PageCacheModel from './page_cache';
shelljs.mkdir('-p', config.dbDir);
... ... @@ -18,8 +19,10 @@ const DeployInfo = new DeployModel();
const User = new UserModel();
const Hotfix = new HotfixModel();
const OperationLogger = new OperationLoggerModel();
const PageCache = new PageCacheModel();
User.init();
PageCache.init();
export {
Server,
... ... @@ -28,5 +31,6 @@ export {
DeployInfo,
User,
Hotfix,
OperationLogger
OperationLogger,
PageCache
};
\ No newline at end of file
... ...
/**
*
* @author: chenfeng<feng.chen@yoho.cn>
* @date: 16/10/14
*/
'use strict';
import Model from './model';
import ssh from 'ssh2';
class PageCahe extends Model {
constructor() {
super('page_cache');
}
replaceUrl(uri) {
return uri.replace(/\./g, '\\.').replace(/\//g, '\\/');
}
async removeCache(keys, storeTableName) {
let self = this;
let servers = await self.findAll();
for (var i = 0; i < servers.length; i++) {
try {
await self._removeAllNginxCache(servers[i], keys, storeTableName);
} catch (err) {
console.log(err)
}
}
}
async removeAllCache(storeTableName) {
let self = this;
let servers = await self.findAll();
for (var i = 0; i < servers.length; i++) {
try {
let server = servers[i];
if (server.cachepath && storeTableName) {
await self._connStart(async (conn) => {
let scirpt = `rm -rf ${server.cachepath}/${storeTableName}`;
await self._evalScript(conn, scirpt);
}, server);
}
} catch (err) {
console.log(err)
}
}
}
async _removeAllNginxCache(server, keys, storeTableName) {
let self = this;
let limit = 2;
let block = parseInt(keys.length / limit, 10) + (keys.length % limit ? 1 : 0);
let blockIndex = 0;
await self._connStart(async (conn) => {
for (var i = blockIndex; i < block; i++) {
blockIndex = i;
let items = keys.slice(i * limit, i * limit + 2);
let scirpt = self._joinRemoveScript(server, items, storeTableName);
self._evalScript(conn, scirpt);
}
}, server)
}
_checkDangerScirpt(scirpt) {
if (scirpt.test(/rm -rf \/($| )/)) {
return false;
}
}
_connStart(callback, server) {
//ssh掉线重连
return new Promise((resolve, reject) => {
let connStart = (err) => {
let conn = new ssh.Client();
conn.on('ready', async() => {
await callback(conn)
resolve();
}).on('error', () => {
console.log(`error ${server.host}, ${err}`);
if (err < 20) {
connStart(++err);
} else {
reject('limit error');
}
}).connect({
host: server.host,
username: server.username,
password: server.password,
port: server.port
});
}
connStart(0, 0);
});
}
_evalScript(conn, scirpt) {
let self = this;
return new Promise((resolve) => {
console.log(scirpt)
resolve();
// let result = conn.exec(scirpt, (err, stream) => {
// if (!err) {
// resolve();
// }
// });
})
}
_joinRemoveScript(server, keys, storeTableName) {
let script = 'rm';
keys.forEach((key) => {
let level1 = key.key.substr(key.key.length - 1, 1);
let level2 = key.key.substr(key.key.length - 3, 2);
script += ` ${server.cachepath}/${storeTableName}/${level1}/${level2}/${key.key}`;
});
return script;
}
async init() {
let count = await this.count({});
if (count === 0) {
await this.insert({
host: '127.0.0.1',
username: 'chenfeng',
password: '1',
port: 22,
tag: 'nginx1',
cachepath: '/usr/local/nginx'
});
}
}
}
export default PageCahe;
... ...
/**
*
* @author: chenfeng<feng.chen@yoho.cn>
* @date: 16/10/13
*/
'use strict';
import Router from 'koa-router';
import InfluxDB from '../../logger/influxdb';
import sh from 'shelljs';
import {
PageCache
} from '../../models';
const r = new Router();
const pageCahe = {
async query(ctx) {
let data = {
storeList: [{
tableName: 'ngx_cache_pc',
name: 'PC'
}, {
tableName: 'ngx_cache_wap',
name: 'Wap'
}],
count: 0
};
await ctx.render('action/page_cache', data);
},
async clear(ctx) {
let queryUri = ctx.request.body.query_uri;
let storeTableName = ctx.request.body.table_name;
if (queryUri && storeTableName) {
queryUri = PageCache.replaceUrl(queryUri);
let sql = `select FIRST(cache_status) from ${storeTableName} where full_path =~ /${queryUri}.*/ group by "key"`;
let result = await InfluxDB.query(sql);
PageCache.removeCache(result[0], storeTableName);
}
},
async clearAll(ctx) {
let storeTableName = ctx.request.body.table_name;
if (storeTableName) {
PageCache.removeAllCache(storeTableName);
}
}
}
r.get('/query', pageCahe.query);
r.post('/clear', pageCahe.clear);
r.post('/clear/all', pageCahe.clearAll);
export default r;
... ...
... ... @@ -9,6 +9,7 @@ import monitor from './actions/monitor';
import users from './actions/users';
import hotfix from './actions/hotfix';
import operationLog from './actions/operation_log';
import pageCahe from './actions/page_cache';
const noAuth = new Router();
const base = new Router();
... ... @@ -34,6 +35,7 @@ export default function (app) {
base.use('/users', users.routes(), users.allowedMethods());
base.use('/hotfix', hotfix.routes(), hotfix.allowedMethods());
base.use('/operation', operationLog.routes(), operationLog.allowedMethods());
base.use('/page_cache', pageCahe.routes(), pageCahe.allowedMethods());
base.use('', index.routes(), index.allowedMethods());
... ...
<div class="pageheader">
<div class="media">
<div class="pageicon pull-left">
<i class="fa fa-th-list"></i>
</div>
<div class="media-body">
<ul class="breadcrumb">
<li><a href="/"><i class="glyphicon glyphicon-home"></i></a></li>
<li><a href="/servers">缓存管理</a></li>
</ul>
<h4>清理缓存</h4>
</div>
</div>
<!-- media -->
</div>
<div class="contentpanel">
<div class="row cache-panel">
<div class="panel panel-default">
<div class="panel-body">
<div class="col-sm-6">
<div class="operations mb20">
</div>
<div class="query">
<textarea name="" id="uri" cols="30" rows="20" class="form-control" placeholder="支持多条换行输入">http://m.yohobuy.com</textarea>
</div>
</div>
</div>
<div class="panel-footer">
<select id="stores" class="form-control input-sm selcet-auto pull-left mr20">
{{#each storeList}}
<option value="{{tableName}}">{{name}}</option>
{{/each}}
</select>
<button class="btn btn-warning btn-clear">清除</button>
<button class="btn btn-danger btn-all-clear pull-right">全网刷新</button>
</div>
</div>
</div>
</div>
<script>
var posing = false;
$(document).on('ready pjax:success', function() {
$('.btn-success').click(function() {
if (posing) {
return;
}
posing = true;
$('.page-count>span').text('查询中..');
$('.btn-search').addClass('disabled');
var tableName = $('#stores').val();
var uri = $('#uri').val();
if (uri && tableName) {
$.post('/page_cache/search', {
query_uri: uri,
table_name: tableName
}, function (res) {
posing = false;
$('.btn-search').removeClass('disabled');
if (res.code === 200) {
$('.page-count>span').text(res.data);
} else {
$('.page-count>span').text('查询失败');
}
})
}
});
$('.btn-clear').click(function() {
var tableName = $('#stores').val();
var uri = $('#uri').val();
if (uri && tableName) {
$.post('/page_cache/clear', {
query_uri: uri,
table_name: tableName
}, function(res) {
});
}
})
$('.btn-all-clear').click(function() {
var tableName = $('#stores').val();
if (tableName) {
$.post('/page_cache/clear/all', {
table_name: tableName
}, function(res) {
});
}
})
});
</script>
\ No newline at end of file
... ...
... ... @@ -25,6 +25,11 @@
<li><a href="/monitor/log">实时日志</a></li>
</ul>
</li>
<li class="parent"><a href=""><i class="fa fa-history"></i> <span>缓存管理</span></a>
<ul class="children">
<li><a href="/page_cache/query">清理缓存</a></li>
</ul>
</li>
{{#if is_master}}
<li class="parent"><a href=""><i class="fa fa-gears"></i> <span>系统管理</span></a>
<ul class="children">
... ...
0 info it worked if it ends with ok
1 verbose cli [ '/usr/local/bin/node',
1 verbose cli '/usr/local/bin/npm',
1 verbose cli 'run',
1 verbose cli 'babel',
1 verbose cli 'app.js' ]
2 info using npm@3.8.9
3 info using node@v6.2.0
4 verbose run-script [ 'prebabel', 'babel', 'postbabel' ]
5 info lifecycle yoho-node-ci@0.0.1~prebabel: yoho-node-ci@0.0.1
6 silly lifecycle yoho-node-ci@0.0.1~prebabel: no script for prebabel, continuing
7 info lifecycle yoho-node-ci@0.0.1~babel: yoho-node-ci@0.0.1
8 verbose lifecycle yoho-node-ci@0.0.1~babel: unsafe-perm in lifecycle true
9 verbose lifecycle yoho-node-ci@0.0.1~babel: PATH: /usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/chenfeng/Documents/source/yoho/yoho-node-ci/node_modules/.bin:/usr/local/bin:/usr/local/lib/node_modules/npm/bin/node-gyp-bin:/Users/chenfeng/Documents/source/yoho/yoho-node-ci/node_modules/.bin:/usr/local/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/share/dotnet:/Users/chenfeng/Documents/tools/android-sdk-macosx/platform-tools:/Users/chenfeng/Documents/tools/android-sdk-macosx/tools:/usr/local/nginx/sbin
10 verbose lifecycle yoho-node-ci@0.0.1~babel: CWD: /Users/chenfeng/Documents/source/yoho/yoho-node-ci
11 silly lifecycle yoho-node-ci@0.0.1~babel: Args: [ '-c', 'babel-node "app.js"' ]
12 silly lifecycle yoho-node-ci@0.0.1~babel: Returned: code: 1 signal: null
13 info lifecycle yoho-node-ci@0.0.1~babel: Failed to exec babel script
14 verbose stack Error: yoho-node-ci@0.0.1 babel: `babel-node "app.js"`
14 verbose stack Exit status 1
14 verbose stack at EventEmitter.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/lifecycle.js:245:16)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at EventEmitter.emit (events.js:191:7)
14 verbose stack at ChildProcess.<anonymous> (/usr/local/lib/node_modules/npm/lib/utils/spawn.js:24:14)
14 verbose stack at emitTwo (events.js:106:13)
14 verbose stack at ChildProcess.emit (events.js:191:7)
14 verbose stack at maybeClose (internal/child_process.js:850:16)
14 verbose stack at Process.ChildProcess._handle.onexit (internal/child_process.js:215:5)
15 verbose pkgid yoho-node-ci@0.0.1
16 verbose cwd /Users/chenfeng/Documents/source/yoho/yoho-node-ci
17 error Darwin 16.0.0
18 error argv "/usr/local/bin/node" "/usr/local/bin/npm" "run" "babel" "app.js"
19 error node v6.2.0
20 error npm v3.8.9
21 error code ELIFECYCLE
22 error yoho-node-ci@0.0.1 babel: `babel-node "app.js"`
22 error Exit status 1
23 error Failed at the yoho-node-ci@0.0.1 babel script 'babel-node "app.js"'.
23 error Make sure you have the latest version of node.js and npm installed.
23 error If you do, this is most likely a problem with the yoho-node-ci package,
23 error not with npm itself.
23 error Tell the author that this fails on your system:
23 error babel-node "app.js"
23 error You can get information on how to open an issue for this project with:
23 error npm bugs yoho-node-ci
23 error Or if that isn't available, you can get their info via:
23 error npm owner ls yoho-node-ci
23 error There is likely additional logging output above.
24 verbose exit [ 1, true ]
... ...
... ... @@ -95,4 +95,7 @@ body .mainwrapper .leftpanel {
.project-env {
cursor: pointer;
}
.selcet-auto {
width: auto;
}
\ No newline at end of file
... ...