Статьи

Java: ChronicleMap Part 3, Быстрые микросервисы

Стандартные карты Java необходимо инициализировать при запуске. Узнайте, как использовать ChronicleMaps, которые можно инициализировать из файла, и значительно сократить время запуска микросервиса, а также о том, как обмениваться картами между JVM.

Встроенные реализации Map , такие как HashMap и ConcurrentHashMap работают быстро, но их необходимо инициализировать с отображениями, прежде чем их можно будет использовать для поиска значений. Кроме того, они ограничены в размере практическими средствами, такими как размер кучи и объем оперативной памяти. Наконец, они являются локальными для JVM, в которой он работает.

Процесс инициализации может замедлить критический запуск для микросервисов, особенно при чтении сопоставлений из удаленного интерфейса REST или удаленной базы данных. В этой статье вы узнаете, как запускать приложения для микросервисов в считанные секунды, а не минуты, используя экземпляры ChronicleMap отображаемые в памяти, и как можно совместно использовать Карты между JVM в этой третьей статье из серии статей о CronicleMap.

Подробнее об основах CronicleMap читайте в первой статье .

Подробнее об объектах с отображенными файлами CronicleMap можно прочитать во второй статье .

Создание общей карты

Как описано во второй статье этой серии, мы можем легко создать карту с отображенным файлом следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
private static Map<Long, Point> createFileMapped() {
    try {
        return ChronicleMap
            .of(Long.class, Point.class)
            .averageValueSize(8)
            .valueMarshaller(PointSerializer.getInstance())
            .entries(10_000_000)
            .createPersistedTo(new File("my-map"));
 
    } catch (IOException ioe) {
        throw new RuntimeException(ioe);
    }
}

созданный
Теперь к объектам Map может обращаться любая JVM, имеющая доступ к файлу «my-map». Обновления карт будут переданы участвующим JVM через общий файл.

Инициализация карты

Как также показано во второй статье , мы могли бы создать и инициализировать
Map как это:

01
02
03
04
05
06
07
08
09
10
11
12
final Map<Long, Point> m3 = LongStream.range(0, 10_000_000)
    .boxed()
        .collect(
            toMap(
                Function.identity(),
                FillMaps::pointFrom,
                (u, v) -> {
                    throw new IllegalStateException();
                },
                FillMaps::createFileMapped
            )
        );

При работе на моем ноутбуке (MacBook Pro, середина 2015 г., 16 ГБ, 2,2 ГГц Intel Core i7) на создание и заполнение требуется около 10 секунд.
Map с 10 миллионами записей.

Если бы содержимое Map было извлечено извне (в отличие от локального создания методом pointFrom() ), заполнение Map вероятно, займет гораздо больше времени. Например, если мы получаем пропускную способность REST со скоростью 50 Мбит / с и каждое представление точки JSON потребляет 25 байтов, тогда для заполнения Map потребуется около 60 секунд.

Запуск новой JVM

Теперь, когда уже существует сопоставленный файл, мы можем начать прямо с этого файла, как показано в следующем фрагменте:

1
2
3
4
5
6
return ChronicleMap
    .of(Long.class, Point.class)
    .averageValueSize(8)
    .valueMarshaller(PointSerializer.getInstance())
    .entries(10_000_000)
    .createOrRecoverPersistedTo(new File("my-map"));

Это создаст Map непосредственно из существующего файла «my-map».

Запуск этого на моем ноутбуке даст время запуска 5 секунд. Это можно сравнить с 60-секундным примером REST, что дает сокращение времени запуска на 90%.

Запуск нескольких JVM на одном узле

Мы можем выбрать запуск нескольких JVM на одном физическом серверном узле. Таким образом, мы извлекаем выгоду из способности ОС делать сопоставления файла доступными для каждой JVM, предоставляя доступ к общей памяти. Это является эффективным средством связи с низкими задержками между JVM. Тот факт, что существует общий пул отображаемой памяти, делает управление памятью намного более эффективным по сравнению с ситуацией, когда каждая JVM / OS должна поддерживать свои собственные отдельные отображения.

Резюме

ChronicleMaps могут быть разделены между участвующими JVM через общие файлы
Время запуска может быть значительно сокращено с помощью общих файлов

Если JVM работают на одном физическом компьютере, производительность и эффективность еще более улучшаются

Совместно используемые файлы через ChronicleMap обеспечивают низкое время ожидания для связи между JVM

См. Оригинальную статью здесь: Java: ChronicleMap Part 3, Быстрые микросервисы

Мнения, высказанные участниками Java Code Geeks, являются их собственными.