Как стать автором
Обновить
18
0
Андрей Чернов @ChernovAF

Java Architect

Отправить сообщение

Community-версия Ignite не поддерживает rolling update. То есть, если вы обновите серверные узлы, но не обновите клиентские, получите такую ошибку

Я правильно понял, что эта проблема решена в DataGrid-е, а в Apache Ignite решения до сих пор нет?

Так Сбер (а точнее СберТех) уже ппреименовал Ignite в DataGrid.

Такой проблемы нет, потому что:

  1. Очень много сессий в online (в СберБанк Онлайн полмиллиона-миллион). И все они равномерно распределены по мастер-узлам.

  2. Абсолютное большинство сессий всё-таки более-менее однородные (в пляне "тяжести" создаваемой нагрузки).

Поэтому нагрузка, создаваемая такими сессиями, очень равномерно нагружает CPU на всех мастер-узлах кластера.

Статья про backend.

Отставить негатив про frontend!

При создании каждой новой сессии запросы распределяются по мастер-узлам равномерно с помощью RoundRobin балансировки.

А запросы в рамках уже созданной сессии (прочитать/записать данные) идут строго в тот мастер-узел, где сессия была создана. Вот здесь уже используется sticky session.

В продакшене постоянно есть нескончаемый поток как первых запросов, так и вторых, поэтому RoundRobin и sticky session работают параллельно (в разных запросах).

Ребят, давайте по делу. Согласен, это боль, но она не относится к теме статьи.

Пробовал различные вариации JSON-сериализации и различные варианты бинарной сериализации - общая тенденция такова, что бинарные форматы быстрее за счёт того, что в них нет логически лишних данных для хранения разметки.

Конкретно, Fast JSON я нарочно не игнорировал - думаю, стоит попробовать "пропустить" через benchmark. Спасибо за наводку!

Вы понимаете, что все участвующие в сравнении библиотек предназначены для преобразования в формат отличный от byte[]?
Это неправда. Не путайте, пожалуйста, народ.

java.lang.Object с полями объекта

Ни одна из перечисленных библиотек не выполняет преобразований вида: Object -> JSON -> byte[].
Либо Object -> JSON, либо Object -> byte[]. В последнем случае как раз и наблюдается более высокая скорость, чем у Java Standard.

В моем понимании эти понятия связаны с выводом в поток и восстановлением объекта из потока.
У сериализации другое определение, если посмотреть даже в Wikipedia:
In computer science, in the context of data storage, serialization (or serialisation) is the process of translating data structures or object state into a format that can be stored (for example, in a file or memory buffer) or transmitted (for example, across a network connection link) and reconstructed later (possibly in a different computer environment).
Для Java, фактически, сериализация — это только преобразование Object-а в byte[]|String|..., которые можно передать по сети/сохранить в БД и т.д., но эти действия не относятся к самой сериализации.

Останемся при своих мнениях, не вижу смысла их друг другу навязывать.
Нет, не путаю. Речь здесь идёт именно про микросекунды (тысячные доли миллисекунды). Это результат усреднения сотен тысяч повторений сериализации/десериализации, о чём я написал выше в комментарии.
Конечно, измерять с такой точностью системные часы компьютеров не позволяют.
Сериализованы ли объекты передаваемые через сеть?
Передачи через сеть в наших измерениях нет, только сериализация/десериализация.

Рекомендую ознакомиться с Java Microbenchmark Harness (JMH).
«JMH-бенчмарк без деталей» я привёл в одном из комментариев выше. В ближайшее время добавлю этот кусок Java-кода в тело самой публикации.
Во-первых, коллега, я не «умудрился намерить», а выполнил качественные измерения с использованием JMH — специального софта для измерения производительности JVM. Опубликованные результаты измерений многократно повторялись на нашем софте и железе.

Во-вторых, если вы взглянете на первые графики из раздела «Гонки», то увидите, что для Java Standard цикл сериализации/десериализации данных размером порядка 1 КБ (примерно ваш размер) у нас занял 0,007 + 0,021 = 0,028 мс. У вас же получилось 4 мс за 2 цикла сериализации/десериализации + сетевые задержки. Это, без учёта сети, в 2000/28=~71 раз медленнее нашего результата. И где здесь «плачевный» результат?..

Кстати, исходя из того, что сама фаза измерения в нашем случае длилась 5 сек (я это указывал в начале «Гонок»), то для получения значения 0,007 мс по сериализации у нас ушло 714 285 повторений с усреднением результата. Для десериализации (0,021 мс) было использовано 238 095 повторений. Эти цифры кратно больше ваших 71 000 запросов, что говорит о том, что точность опубликованных измерений выше, чем в ваших «измерителях».

Java Standart — делает подобное, на мой взгляд, с наименьшими преобразованиями данных по сравнению со всем остальным перечисленным вами.
Субъективное суждение, это лично ваше мнение.
JBoss Serialization исключили из участников на основании вот этого теста: eishay/jvm-serializers
Там сериализация JBoss сильно уступает Jackson Smile-у, Kryo и FST, которые попали в наше исследование.
У One Nio те же плюсы, за одним непринципиальным исключением:
There is limited support for readObject/writeObject. These methods will be called, but they should not work with the stream directly. The only stream methods they may call are defaultReadObject and defaultWriteObject. Other calls will result in exception.

Externalizable is completely supported.
Да, мы смотрели в эту сторону, но предложенный способ использования аннотации @Version не подходит для нашей задачи, когда классы сериализуемых объектов готовятся потребителями нашего сервиса, а для самого сервиса это «чёрный ящик».
Кусок javadoc-а для аннотации @Version из FST
/**
 * support for adding fields without breaking compatibility to old streams.
 * For each release of your app increment the version value. No Version annotation means version=0.
 * Note that each added field needs to be annotated.
 *
 * e.g.
 *
 * class MyClass implements Serializable {
 *
 *     // fields on initial release 1.0
 *     int x;
 *     String y;
 *
 *     // fields added with release 1.5
 *     @Version(1) String added;
 *     @Version(1) String alsoAdded;
 *
 *     // fields added with release 2.0
 *     @Version(2) String addedv2;
 *     @Version(2) String alsoAddedv2;
 *
 * }

Как видим, нашим потребителям пришлось бы «заморочиться» со своими классами, сохраняемыми в сессию. А ведь из-за цепочек зависимостей объектов потребитель может даже не осознавать, что объекты какого-то из классов он сохраняет в сессию…
Таким образом, по умолчанию («не задавая лишних вопросов») у FST нет обратной совместимости со старыми сериализуемыми классами.
Судя по вашему уровню погруженности в тему, вы могли бы сами опубликовать отличный пост. Дерзайте!
Если честно, то мне сложно представить case-ы, когда реально, а не надуманно, было бы необходимо поддержать смену типа у поля при развитии класса. Если меняется тип поля, то, вероятнее всего, это уже другое поле.

Почему-то если имя не совпадает, то поле останется null, а если тип не совпадает, то это критическая ошибка.
Потому что имя — это всего лишь строка, а тип определяет структуру данных. Смена типа — гораздо более серьёзное изменение, нежели смена имени поля.
Потюнить Jackson, конечно, интересно, и я постараюсь это сделать, как будет время. Спасибо за наводки.
Однако добавлять геттеры и сеттеры в сериализуемые объекты — это не то, что нам нужно: объекты готовят потребители нашего сервиса, а мы должны быстро сериализовывать всё подряд.
Как я написал во введении, нам нужна библиотека, «не задающая лишних вопросов».
Исходники бенчмарков постараюсь к следующей публикации разместить на Github-е.
Пока могу показать лишь «скелет» без деталей реализации:
JMH-бенчмарк без деталей
public class SerializationPerformanceBenchmark {

    @State( Scope.Benchmark )
    public static class Parameters {

        @Param( {
            "Java standard",
            "Jackson default",
            "Jackson system",
            "JacksonSmile default",
            "JacksonSmile system",
            "Bson4Jackson default",
            "Bson4Jackson system",
            "Bson MongoDb",
            "Kryo default",
            "Kryo unsafe",
            "FST default",
            "FST unsafe",
            "One-Nio default",
            "One-Nio for persist"
        } )
        public String serializer;
        public Serializer serializerInstance;

        @Param( { "0", "100", "200", "300", /*... */ "1000000" } )  // Toward 1 MB
        public int sizeOfDto;
        public Object dtoInstance;
        public byte[] serializedDto;

        @Setup( Level.Trial )
        public void setup() throws IOException {
            serializerInstance = Serializers.getMap().get( serializer );
            dtoInstance = DtoFactory.createWorkflowDto( sizeOfDto );
            serializedDto = serializerInstance.serialize( dtoInstance );
        }

        @TearDown( Level.Trial )
        public void tearDown() {
            serializerInstance = null;
            dtoInstance = null;
            serializedDto = null;
        }
    }

    @Benchmark
    public byte[] serialization( Parameters parameters ) throws IOException {
        return parameters.serializerInstance.serialize(
                parameters.dtoInstance );
    }

    @Benchmark
    public Object unserialization( Parameters parameters ) throws IOException, ClassNotFoundException {
        return parameters.serializerInstance.deserialize(
                parameters.serializedDto,
                parameters.dtoInstance.getClass() );
    }
}

За абстракцицей Serializer скрыты все 14 исследуемых реализаций Java-сериализаторов.
1

Информация

В рейтинге
Не участвует
Откуда
Вологда, Вологодская обл., Россия
Работает в
Дата рождения
Зарегистрирован
Активность