Сделать мое приложение на порядок быстрее потратив на это пару часов.
Пережить нагрузку в
«черную пятницу».
Статика (HTTP запросы)
Получение данных
Результаты вычислений
Шаблоны
var app = express();
app.get('/', (req, res) => {
fetch()
});
fetch()
|
|
var app = express();
app.get('/', (req, res) => {
fetch()
.then(calculate)
});
fetch() |
calculate() |
|
|
var app = express();
app.get('/', (req, res) => {
fetch()
.then(calculate)
.then(data => res.json(data));
});
app.listen(3000);
var cache;
app.get('/', (req, res) => {
if (cache) { return res.json(cache); }
fetch()
.then(calculate)
.then(data => cache = data)
.then(data => res.json(data));
});
Уменьшили время ответа
var cache;
app.get('/', (req, res) => {
cache = cache ||
fetch().then(calculate);
cache
.then(data => res.json(data))
.catch(() => cache = null);
});
Уменьшили время ответа
Уменьшили нагрузку
var LRU = require('lru-cache');
var cache = LRU({ maxAge: 3000 });
app.get('/', (req, res) => {
if (!cache.has('coffee')) {
var data = fetch().then(calculate);
cache.set('coffee', data);
}
cache.get('coffee')
.then(data => res.json(data))
.catch(() => cache.del('coffee'));
});
Уменьшили время ответа
Уменьшили нагрузку
Контролируем время жизни
var Redis = require('ioredis');
var cache = new Redis();
cache.get('coffee')
.then(data => {
if (data) { return data; }
return fetch().then(calculate)
.then(data => {
cache.set('coffee', data, 'EX', 3);
return data;
});
})
.then(data => res.json(data));
Уменьшили время ответа
Уменьшили нагрузку
Контролируем время жизни
Общий кэш для всех инстансов
1. Прочитать шаблон
2. Скомпилировать
3. Применить
var _ = require('lodash');
var str = '<%= date %>: "<%= error.message %>"';
module.exports = _.template(str);
var template = require('./template');
app.get('/', (req, res) => {
var myError = Error(':-(');
console.log(template({
date: new Date(),
error: myError
}));
});
// Tue Jun 21 2016 13:48:02 GMT+0500 (YEKT): ":-("
{{# cache 'menu'}}
<h1>Coffee</h1>
<ul>
{{#each items}}
<li>{{name}}</li>
{{/each}}
</ul>
{{/cache}}
Handlebars.registerHelper('cache', (key, options) => {
if (!cache.has(key)) {
cache.set(key, options.fn(options.data.root));
}
return cache.get(key);
});
«... кажется, эти данные нам нужны всегда и обновляются они редко ...»
HitRate = 'из кэша' / 'число запросов'
Запрос | Кэш | Эффективность |
/ |
'coffee' |
~99% |
/:region |
'Indonesia', 'Africa', ... |
~98% |
/:uid |
'user1', 'user2', ..., 'user100500' |
~1% |
Кэшировать популярные данные
Не кэшировать песональные данные
Не кэшировать сложные комбинации
// ...
app.listen(3000);
var data = fetch().then(calculate);
cache.set('coffee', data);
<script>
var data = {
'/coffee': { ... },
'/favorite': { ... },
'/userData': { ... }
};
</script>
function request(url) {
return data[url]
? Promise.resolve(data[url])
: $.get(url);
}
function memoize(key, maxAge, fn) {
if (cache.has(key)) {
return Promise.resolve(cache.get(key));
}
return Promise.resolve()
.then(fn)
.then(results => {
cache.set(key, result, maxAge);
return result;
});
}
Легко менять реализацию кэша
Настрока кэширования моделей
cookie
sessionStorage
localStorage
function setItem(key, maxAge, value) {
var data = JSON.stringify({
expire: Date.now() + maxAge,
value: value
});
localStorage.setItem(key, data);
}
function getItem(key, maxAge, value) {
var store = localStorage.getItem(key);
var data = JSON.parse(store);
if(data.expire > Date.now()) {
return data.value;
}
}
cache.set('speaker', {
name: 'Жигалов Сергей',
twitter: '@sergey_zhigalov',
email: 'zhigalov@yandex-team.ru'
});
cache.set('assistant', {
name: 'Мокеев Евгений'
});