При использовании Globalize на серверной стороне ключевая стоимость формируется не только за счёт форматирования дат, чисел и сообщений, но и за счёт подготовки локализационных данных CLDR (Unicode Common Locale Data Repository), компиляции форматтеров и разборщиков, а также построения структур, ускоряющих повторные операции.
Серверное кеширование в таком контексте решает сразу несколько задач:
В Globalize можно выделить несколько уровней данных, которые имеют смысл сохранять в памяти или внешних кешах.
CLDR представляет собой базовый слой локализации. Он включает:
Загрузка CLDR — одна из самых дорогих операций при старте приложения. При серверной архитектуре с несколькими воркерами важно избегать повторного парсинга этих данных в каждом процессе.
Globalize создаёт специализированные функции форматирования:
Каждый такой форматтер может быть закеширован как готовая функция, исключающая повторную компиляцию.
Разбор строк обратно в числа или даты также требует предварительной подготовки. Парсеры для каждой локали включают:
Если используется система сообщений Globalize, то интерполяция и plural rules могут быть заранее обработаны и сохранены в виде готовых функций.
Самый быстрый уровень кеширования — память процесса Node.js. Он подходит для:
Ключевая идея — избегать повторной инициализации:
import Globalize from "globalize";
import cldrData from "./cldr-data";
const cache = new Map();
function getGlobalize(locale) {
if (cache.has(locale)) {
return cache.get(locale);
}
Globalize.load(cldrData);
const instance = new Globalize(locale);
cache.set(locale, instance);
return instance;
}
Основная проблема такого подхода — дублирование памяти при масштабировании на несколько процессов.
При использовании кластеризации Node.js важно разделять:
Правильная стратегия:
Redis используется для хранения:
Однако Globalize-объекты нельзя напрямую сериализовать. Поэтому кешируются:
Пример подхода:
async function formatCurrencyCached(redis, locale, value, currency) {
const key = `currency:${locale}:${currency}:${value}`;
const cached = await redis.get(key);
if (cached) return cached;
const g = getGlobalize(locale);
const result = g.formatCurrency(value, currency);
await redis.set(key, result, "EX", 60 * 10);
return result;
}
На уровне CDN можно кешировать уже сформированные ответы API, особенно если:
Пример сценария:
/api/products?locale=ru-RU
Ответ может кешироваться на edge-уровне, включая:
Инициализация включает:
При большом количестве локалей стоимость растёт линейно по числу языков, но нелинейно по объёму CLDR.
Оптимизация:
Базовый ключ кеша:
locale + feature + parameters
Примеры:
ru-RU:number:currency:USDen-GB:date:longfr-FR:plural:messagesТакое разделение позволяет:
Каждая локаль должна быть изолирована, чтобы избежать:
Globalize-инстансы и форматтеры содержат:
Они не сериализуются напрямую в JSON.
Решение:
Основная сложность — обновление CLDR или правил локали.
Стратегии:
cacheKey = locale + cldrVersion
При обновлении CLDR старая версия автоматически игнорируется.
Используется для:
При деплое:
В Node.js часто используется:
Проблема: каждый процесс содержит свой кеш.
Решения:
При запуске сервиса выполняется:
Пример:
async function warmup(locales) {
for (const locale of locales) {
const g = getGlobalize(locale);
g.formatNumber(1000);
g.formatDate(new Date());
g.formatCurrency(10, "USD");
}
}
Основные метрики:
Оптимизационные эффекты кеширования:
Эффективная архитектура включает:
Каждый уровень снижает нагрузку на следующий, обеспечивая предсказуемое поведение системы при масштабировании.