1. Посмотрите на TechEmpower - там масса тестов и фреймворков, в т.ч. и очень похожие на ваши - https://www.techempower.com/benchmarks/#section=data-r23. Исходники у них на Github лежат. И да, классический Spring там по производительности даже среди Java фреймворков... в серединке ближе к концу.
2. Не увидел в описании методики в части Слона (PgSQL)
а) подгонки параметров сервера к той машинке, на которой запускалось. Если правильно помню, то по умолчанию там "чтобы запускалось на зубной щётке", т.е. очень небольшие используемые ресурсы. Соотношение между разными фреймворками это не должно бы сильно поменять, но абсолютные цифры могут раза в два подняться. Посмотрите конфигуратор от CyberTech https://pgconfigurator.cybertec.at/, и не забудьте выставить стоимость похода на диск в соответствии с типом накопителя (по умолчанию там для HDD) б) после вставки такого количества записей просится vacuum analyze или вообще full analyze. Опять таки, абсолютные цифры подрастут.
3. В упор не увидел (или читал невнимательно?) сколько потоков NIO у Spring было доступно напротив 64 подключений в БД (что вообще ни о чём под такой RPS). Потому что как минимум подключений должно быть столько же, а лучше чуть больше, иначе NIO потоки будут тупо ждать подключений из пула и устраивать за них "давку" - у вас задача явно не того сорта, где 5% - сходить в БД за данными, 90% - их обсчитать. Дисбаланс частенько приводит к "пиле" на графиках RPS. Но если вы накрутите подключения в пуле не поправив ресурсы Слону - то скорее всего получите локи уже где-то в недрах сервера СУБД.
4.
Под большое количество коротких запросов уже надо бы ковырять HTTP KeepAlive и переиспользование пула сетевых подключений. Они имеют свойства кончаться.
5.
Где карта, Билли? В смысле, где сборка JFR и анализ того, чем на самом деле занималось приложение? Висело в локах, висело в ожидании доступного сокета, висело на read, испытывало большое GC Pressure ? Что нужно оптимизировать в первую очередь? Откройте полученный файл сначала в JMC, чтобы посмотреть на рекомендации, потом в IDEA, чтобы получить flame graph с точностью до строки исходного кода.
Не не будут, а уже делают. Потому что там тоже CEO и под ним мильён менеджеров, у которых KPI. Единственная надежда, что фаззинг большинство багов выявит до того, как оно начнёт управлять реальным железом.
Мы больше не бросаем исключения. Вместо этого явно возвращаем либо ошибку (Left), либо успешно созданный VO (Right). Больше примеров использования на все случаи жизни вы найдете в документации к библиотекам.
Вот такое я по возможности блокирую на review. Потому что: где-то должно быть написано, что Left - это ошибка, а Right - это значение. И соблюдаться неукоснительно. В данном случае накосячить с правой стороной сложно, а с левой - "а давайте для случаев, когда нужно возвращать VIP статус, будем там возвращать строчку "VIP", а если не "VIP" - то сообщение об ошибке. А если цифры - то это идентификатор сотрудника, который оформил заказ. И через пару - тройку развивателей продукта, каждому из которых нужно добавить функциональность и по возможности ничего не сломать - получаем псевдо-DSL в поле Left. В более лёгком случае - набор public static final String, которые сравниваются хитрыми if-else в объёме на полноценную state machine.
Исходя из принципов, приведённых в статье: делаем VO ErrorMessage, который инкапсулирует строку с сообщением. Или вообще имеет где-то там enum с этими строками. Either.left им и типизирован, при чтении понятна семантика, да и IDE автоматически сгенерирует переменную нужного типа где-нибудь там потом.
Вариант чуть посложнее, если упороться в рефакторинг: делаем VO для возвращаемого результата, с явными полями Error error и PickupNumber pickupNumber. Пару методов создания - ofError(, ofSuccess( можно ещё ofAlmost( - это когда и создать удалось, но не без сопутствующих ошибок. Кстати, когда попросят собрать все ошибки, warning-и и умолчания, которые случились внутри вызова, этот список можно будет упаковать внутрь Error и не переписывать весь окружающий код.
Таким образом появляется некоторый шанс, что API без присмотра просуществует некоторое время примерно так, как задумывал автор.
Всем value объекты прекрасны. Кроме как наличием отсутствия перегрузки операторов в Java, чем в общем и BigDecimal характерен. Более-менее сложное вычисление - и хоть в LLM скармливай, чтобы объяснило, что там написано. Особенно когда встречается пара таких объектов, каждый из которых - со своим неповторимым API.
Что-то не могу понять код: если кто-то выдернет питание из сервера (упадём по OOM и т.п.) между строчками 1 и 2 - то кажется в Kafka всё улетит, но в БД не будет отмечено как отправленное и при следующем подходе к снаряду улетит ещё раз. КМК Exact Onсe не будет
1: val updateIds = waitingMessages.mapNotNull { it.id }
2: outboxMessageRepository.updateSentStatusByIds(updateIds)
А если в ходе отправки в Kafka тоже вылетит исключение... тут я даже анализировать не хочу, что куда улетит и отметится, со Spring-овым transaction silentrly rolled back.
Пока не покажут пальцем на GC паузы :). Сейчас то хорошо, а раньше CMS (и что было до него) иногда давал прикурить, порождая такие артефакты в кодовой базе, как самописный пул объектов.
На мой взгляд в шпаргалках (и видимо вопросах на собесах) не хватает чего-то наподобие "Как вы будете разбираться с приложением, которое упало по OOM", "Как вы будете выяснять, почему приложение иногда перестаёт отвечать в рамках SLA (а потом опять начинает, само да...). Я про то, что JMC, VisualVM, Profiler в IDEA и это вот наше всё :)
Киньте в комментарии "+", если думаете что дублирование имеет смысл. "-" если думаете, что этому контенту место на Дзене, а не на Хабре. Ну а если, еще и мнением своим поделитесь - за это отдельное спасибо.
К статье наверно плюсик?
Да, да и ещё раз да. В конце концов, теперь у нас есть уровень материала - сложный или простой...
У меня от дома до метро - 1.7км. Автобусы ходят, но с половины дистанции и ещё в пробке постоять. От метро до офиса - ещё два ровно, и там (ну вот так вышло) вообще ничего не ходит. Если нужно ещё и съездить на встречу в рабочее время - то 10+ километров в день ножками - легко. Т.е. два с половиной часа минимум. А я ленивый...
Попробуйте как-нибудь провести "пару простых действий" без интернета. Вот совсем-совсем. И без доступных во внутренней сетке зеркал. Приходите к серверу или даже рабочей станции с воздушным зазором, вставляете flash, и накатываете...
Легко у него получается, и удобно :) У меня эта вундервафля уже лет восемь. Ничего удобнее для внутрирайонного перемещения и до / от метро не придумано. По магазинам тоже хорошо, два - три пакета в руках вообще никак на процесс езды не влияют
Seagway нифига не компактный. И не переносится одним человеком. И не кладётся в багажник. И не стоит дома рядом с кроссовками, занимая примерно столько же места.
А вот с моноколесом это всё получается (ну если только не совсем монстр на 2,5 киловатта с пробегом 130 км и максималкой под 70).
Именно. Потому что оно практически не занимает место, и "бегает как собачка", т.е. усилия по перекатыванию - отсутствуют. Получается идеальное антипробочное сочетание - от дома до метро на моноколесе, потом быстро и без пробок на метро, потом опять таки быстро - до офиса.
Borland "профукал" несколько не таким способом. Точнее, на некоторых аспектах в статье не заострено особого внимания. А зря.
Так вот... в одной далёкой галактике одна компания на букву M решила, что всё, что работало до этого на Win32 - это уже как-то несовременно. И сказала буквально следующее - в новых релизах все пользовательские программы будут работать только на .Net. И сама Windows тоже будет на .Net. А кто не успел - повторит судьбу Win16 приложений.
Компания Borland на примерно тот момент имела практически лучшую IDE для быстрой разработки. И звалась она Delphi 7. (Может быть и 6, я уж не упомню). В то же самое время (о чём в статье кстати сказано) Borland решила активно играть в ALM (Application Lifecyle Management) и прочие не-разработческие истории.
И началось шоу. Следующая вышедшая на .Net версия Delрhi была ужасной. Нет, она была настолько кошмарной, что работать на ней было невозможно. Сообщество разработчиков пожало плечами и осталось на Delphi 7. Следующая версия была вроде как получше, но тоже такое себе. Как пример - туда тоже не завезли Unicode. Это можно было решить сторонними компонентами, но по сути требовало полной переработки приложения. В BDE баги были тоннами. Сообщество в очередной раз пожало плечами, но многие уже задумались о том, что делать дальше.
Всё это наложилось на совершенно ушибленную ценовую политику и отсутствие бесплатных Starter версий. Да, серьёзно! Вы не могли вкатится в технологию, не заплатив приличной суммы денег. И получали за них мягко говоря сомнительного качества продукт. Если мне не изменяет склероз, то была даже какая-то программа - обменяй свои свежие лицензии на Delphi на лицензии на Delphi 7 (последняя версия на Win32).
Мир тем временем шёл вперёд, Web интерфейс для внутрикорпоративных приложений потихоньку начал становиться стандартом, появлялись разные интересные технологии и возможности. Что сделала Borland - ничего! Выпустила очередной релиз, который опять толком не работал. Сделай они хотя бы возможность транслировать dfm в Web-страницу (все метаданные и сценарии обработки собственно у них уже были) - и их бы носили на руках. Но нет.
Только в 2006 году появилась RAD Studio, на которой можно было разрабатывать, а не бороться со средой разработки. Но паровоз к этому моменту уже ушёл.
PS: Возможно кто-то вспомнит Sybase PowerBuilder, который в ряде аспектов не уступал, а то и превосходил по своим возможностям. Был куплен и убит SAP...
В данном случае - повезло, что всё это не сложилось. Треугольники на "родных" элементах не просто так для красоты делали. Хотя по фото стенку трубы и катет шва не сильно определишь.
Но лично я бы добавил диагоналей, причём как в самих надставках, так и от верха надставки к основанию (к месту крепления колеса). Последние можно вообще сделать из полосы типа 4x40, и крепить на два болтика М10 как железные верёвки
Спасибо огромное за материал! Жалко 10 плюсиков статье не могу поставить, только один.
И маленькая просьба - тот постер / cheatsheet, который был в соседней статье для привлечения внимания - можно его в векторе (pdf) выложить и тут ссылку дать? Я распечатаю и на стенку повешу, чтобы сверяться с.
1.
Посмотрите на TechEmpower - там масса тестов и фреймворков, в т.ч. и очень похожие на ваши - https://www.techempower.com/benchmarks/#section=data-r23. Исходники у них на Github лежат. И да, классический Spring там по производительности даже среди Java фреймворков... в серединке ближе к концу.
2.
Не увидел в описании методики в части Слона (PgSQL)
а) подгонки параметров сервера к той машинке, на которой запускалось. Если правильно помню, то по умолчанию там "чтобы запускалось на зубной щётке", т.е. очень небольшие используемые ресурсы. Соотношение между разными фреймворками это не должно бы сильно поменять, но абсолютные цифры могут раза в два подняться. Посмотрите конфигуратор от CyberTech https://pgconfigurator.cybertec.at/, и не забудьте выставить стоимость похода на диск в соответствии с типом накопителя (по умолчанию там для HDD)
б) после вставки такого количества записей просится vacuum analyze или вообще full analyze. Опять таки, абсолютные цифры подрастут.
3.
В упор не увидел (или читал невнимательно?) сколько потоков NIO у Spring было доступно напротив 64 подключений в БД (что вообще ни о чём под такой RPS). Потому что как минимум подключений должно быть столько же, а лучше чуть больше, иначе NIO потоки будут тупо ждать подключений из пула и устраивать за них "давку" - у вас задача явно не того сорта, где 5% - сходить в БД за данными, 90% - их обсчитать. Дисбаланс частенько приводит к "пиле" на графиках RPS. Но если вы накрутите подключения в пуле не поправив ресурсы Слону - то скорее всего получите локи уже где-то в недрах сервера СУБД.
4.
Под большое количество коротких запросов уже надо бы ковырять HTTP KeepAlive и переиспользование пула сетевых подключений. Они имеют свойства кончаться.
5.
Где карта, Билли? В смысле, где сборка JFR и анализ того, чем на самом деле занималось приложение? Висело в локах, висело в ожидании доступного сокета, висело на read, испытывало большое GC Pressure ? Что нужно оптимизировать в первую очередь?
Откройте полученный файл сначала в JMC, чтобы посмотреть на рекомендации, потом в IDEA, чтобы получить flame graph с точностью до строки исходного кода.
Не не будут, а уже делают. Потому что там тоже CEO и под ним мильён менеджеров, у которых KPI. Единственная надежда, что фаззинг большинство багов выявит до того, как оно начнёт управлять реальным железом.
Вот такое я по возможности блокирую на review. Потому что:
где-то должно быть написано, что Left - это ошибка, а Right - это значение. И соблюдаться неукоснительно. В данном случае накосячить с правой стороной сложно, а с левой - "а давайте для случаев, когда нужно возвращать VIP статус, будем там возвращать строчку "VIP", а если не "VIP" - то сообщение об ошибке. А если цифры - то это идентификатор сотрудника, который оформил заказ. И через пару - тройку развивателей продукта, каждому из которых нужно добавить функциональность и по возможности ничего не сломать - получаем псевдо-DSL в поле Left. В более лёгком случае - набор public static final String, которые сравниваются хитрыми if-else в объёме на полноценную state machine.
Исходя из принципов, приведённых в статье: делаем VO ErrorMessage, который инкапсулирует строку с сообщением. Или вообще имеет где-то там enum с этими строками.
Either.leftим и типизирован, при чтении понятна семантика, да и IDE автоматически сгенерирует переменную нужного типа где-нибудь там потом.Вариант чуть посложнее, если упороться в рефакторинг: делаем VO для возвращаемого результата, с явными полями Error error и PickupNumber pickupNumber. Пару методов создания - ofError(, ofSuccess( можно ещё ofAlmost( - это когда и создать удалось, но не без сопутствующих ошибок. Кстати, когда попросят собрать все ошибки, warning-и и умолчания, которые случились внутри вызова, этот список можно будет упаковать внутрь Error и не переписывать весь окружающий код.
Таким образом появляется некоторый шанс, что API без присмотра просуществует некоторое время примерно так, как задумывал автор.
Всем value объекты прекрасны. Кроме как наличием отсутствия перегрузки операторов в Java, чем в общем и BigDecimal характерен. Более-менее сложное вычисление - и хоть в LLM скармливай, чтобы объяснило, что там написано. Особенно когда встречается пара таких объектов, каждый из которых - со своим неповторимым API.
Что-то не могу понять код: если кто-то выдернет питание из сервера (упадём по OOM и т.п.) между строчками 1 и 2 - то кажется в Kafka всё улетит, но в БД не будет отмечено как отправленное и при следующем подходе к снаряду улетит ещё раз. КМК Exact Onсe не будет
А если в ходе отправки в Kafka тоже вылетит исключение... тут я даже анализировать не хочу, что куда улетит и отметится, со Spring-овым transaction silentrly rolled back.
HAWING - это WHERE для результатов агрегатов. Т.е. отобрать всех клиентов, которые делали больше, чем три покупки за последнюю неделю.
Пока не покажут пальцем на GC паузы :). Сейчас то хорошо, а раньше CMS (и что было до него) иногда давал прикурить, порождая такие артефакты в кодовой базе, как самописный пул объектов.
Спасибо за материал, кратко и со вкусом!
На мой взгляд в шпаргалках (и видимо вопросах на собесах) не хватает чего-то наподобие "Как вы будете разбираться с приложением, которое упало по OOM", "Как вы будете выяснять, почему приложение иногда перестаёт отвечать в рамках SLA (а потом опять начинает, само да...).
Я про то, что JMC, VisualVM, Profiler в IDEA и это вот наше всё :)
К статье наверно плюсик?
Да, да и ещё раз да. В конце концов, теперь у нас есть уровень материала - сложный или простой...
У меня от дома до метро - 1.7км. Автобусы ходят, но с половины дистанции и ещё в пробке постоять. От метро до офиса - ещё два ровно, и там (ну вот так вышло) вообще ничего не ходит. Если нужно ещё и съездить на встречу в рабочее время - то 10+ километров в день ножками - легко. Т.е. два с половиной часа минимум. А я ленивый...
Попробуйте как-нибудь провести "пару простых действий" без интернета. Вот совсем-совсем. И без доступных во внутренней сетке зеркал. Приходите к серверу или даже рабочей станции с воздушным зазором, вставляете flash, и накатываете...
Легко у него получается, и удобно :) У меня эта вундервафля уже лет восемь. Ничего удобнее для внутрирайонного перемещения и до / от метро не придумано. По магазинам тоже хорошо, два - три пакета в руках вообще никак на процесс езды не влияют
Seagway нифига не компактный. И не переносится одним человеком. И не кладётся в багажник. И не стоит дома рядом с кроссовками, занимая примерно столько же места.
А вот с моноколесом это всё получается (ну если только не совсем монстр на 2,5 киловатта с пробегом 130 км и максималкой под 70).
Именно. Потому что оно практически не занимает место, и "бегает как собачка", т.е. усилия по перекатыванию - отсутствуют. Получается идеальное антипробочное сочетание - от дома до метро на моноколесе, потом быстро и без пробок на метро, потом опять таки быстро - до офиса.
Borland "профукал" несколько не таким способом. Точнее, на некоторых аспектах в статье не заострено особого внимания. А зря.
Так вот... в одной далёкой галактике одна компания на букву M решила, что всё, что работало до этого на Win32 - это уже как-то несовременно. И сказала буквально следующее - в новых релизах все пользовательские программы будут работать только на .Net. И сама Windows тоже будет на .Net. А кто не успел - повторит судьбу Win16 приложений.
Компания Borland на примерно тот момент имела практически лучшую IDE для быстрой разработки. И звалась она Delphi 7. (Может быть и 6, я уж не упомню). В то же самое время (о чём в статье кстати сказано) Borland решила активно играть в ALM (Application Lifecyle Management) и прочие не-разработческие истории.
И началось шоу. Следующая вышедшая на .Net версия Delрhi была ужасной. Нет, она была настолько кошмарной, что работать на ней было невозможно. Сообщество разработчиков пожало плечами и осталось на Delphi 7. Следующая версия была вроде как получше, но тоже такое себе. Как пример - туда тоже не завезли Unicode. Это можно было решить сторонними компонентами, но по сути требовало полной переработки приложения. В BDE баги были тоннами. Сообщество в очередной раз пожало плечами, но многие уже задумались о том, что делать дальше.
Всё это наложилось на совершенно ушибленную ценовую политику и отсутствие бесплатных Starter версий. Да, серьёзно! Вы не могли вкатится в технологию, не заплатив приличной суммы денег. И получали за них мягко говоря сомнительного качества продукт. Если мне не изменяет склероз, то была даже какая-то программа - обменяй свои свежие лицензии на Delphi на лицензии на Delphi 7 (последняя версия на Win32).
Мир тем временем шёл вперёд, Web интерфейс для внутрикорпоративных приложений потихоньку начал становиться стандартом, появлялись разные интересные технологии и возможности. Что сделала Borland - ничего! Выпустила очередной релиз, который опять толком не работал. Сделай они хотя бы возможность транслировать dfm в Web-страницу (все метаданные и сценарии обработки собственно у них уже были) - и их бы носили на руках. Но нет.
Только в 2006 году появилась RAD Studio, на которой можно было разрабатывать, а не бороться со средой разработки. Но паровоз к этому моменту уже ушёл.
PS: Возможно кто-то вспомнит Sybase PowerBuilder, который в ряде аспектов не уступал, а то и превосходил по своим возможностям. Был куплен и убит SAP...
Гм. А почему на Вашем же скрине номер записи - 07 ?
В данном случае - повезло, что всё это не сложилось. Треугольники на "родных" элементах не просто так для красоты делали. Хотя по фото стенку трубы и катет шва не сильно определишь.
Но лично я бы добавил диагоналей, причём как в самих надставках, так и от верха надставки к основанию (к месту крепления колеса). Последние можно вообще сделать из полосы типа 4x40, и крепить на два болтика М10 как железные верёвки
Спасибо огромное за материал! Жалко 10 плюсиков статье не могу поставить, только один.
И маленькая просьба - тот постер / cheatsheet, который был в соседней статье для привлечения внимания - можно его в векторе (pdf) выложить и тут ссылку дать? Я распечатаю и на стенку повешу, чтобы сверяться с.
Вот! https://www.youtube.com/c/CuttingEdgeEngineeringAustralia Хотя с починкой ЧПУ он не сладил, продал железо.
Оставлю это здесь: https://pgconfigurator.cybertec.at/