Сегодня ночью за два часа случайно буквально проглотил небольшую книгу на 100 страниц на английском о тестировании Spring Boot приложений
и могу сказать следующее:
1) знание технического английского в IT невероятно важно (огромное количество ресурсов, документация, сами языки - это буквально английский)
2)фреймворки, все завязано на них(в данном случае junit, mockito,spring test,selenium, testcontainers)
Фреймворк (англ. framework — «каркас») - надстройка над языком, универсальный набор инструментов, обеспечивающий структуру кода и избавляющий от низкоуровневых операций. Это очень экономит время и усилия, позволяя сконцентрироваться на сути
Как бы хорошо вы не знали алгоритмы, синтаксис и прикладную область, без фреймворков все этобесполезно неприменимо в реальном мире
и могу сказать следующее:
1) знание технического английского в IT невероятно важно (огромное количество ресурсов, документация, сами языки - это буквально английский)
2)фреймворки, все завязано на них(в данном случае junit, mockito,spring test,selenium, testcontainers)
Фреймворк (англ. framework — «каркас») - надстройка над языком, универсальный набор инструментов, обеспечивающий структуру кода и избавляющий от низкоуровневых операций. Это очень экономит время и усилия, позволяя сконцентрироваться на сути
Как бы хорошо вы не знали алгоритмы, синтаксис и прикладную область, без фреймворков все это
🤝5🔥2⚡1
Недавно пришлось разбираться с полотном sql запроса с десятком вложенных подзапросов, джоинов и спагетти из ифов, добавляющих непонятные строчки. Запрос причём передавался просто String-ой..
Хотелось бы, чтобы все использовали такие абстракции как Entity Graph, но к сожалению обычно самым простым и производительным способом будет написать такой огромный запрос, рефакторинг которого превращается в ад
Entity модель и в целом Object Relation Mapping (оно же ORM, реализациями которого и являются Spring Data и Hibernate) - это модель отображающая объекты из ООП в строки таблиц SQL, что позволяет взаимодействовать с бд не написав ( написав ≥ 0) запросов
Entity граф же позволяет более точно описать сущности и сложные запросы к ним, для избежания проблем ленивой инициализации и n+1, но о них как нибудь в другой раз
Для тех кому интересно узнать больше о Spring Data
Хотелось бы, чтобы все использовали такие абстракции как Entity Graph, но к сожалению обычно самым простым и производительным способом будет написать такой огромный запрос, рефакторинг которого превращается в ад
Entity модель и в целом Object Relation Mapping (оно же ORM, реализациями которого и являются Spring Data и Hibernate) - это модель отображающая объекты из ООП в строки таблиц SQL, что позволяет взаимодействовать с бд не написав ( написав ≥ 0) запросов
Entity граф же позволяет более точно описать сущности и сложные запросы к ним, для избежания проблем ленивой инициализации и n+1, но о них как нибудь в другой раз
Для тех кому интересно узнать больше о Spring Data
Ключевым аспектом при приеме на работу помимо хардов/софтов, особенно на стажку/джуна являются алгоритмы. Из всех моих собесов их спрашивали процентах на 90% (особенно этим грешит пресловутый Яндекс).Большинство задач сводятся к одним и тем же паттернамскоторые надо уметь увидеть и применить
По уровню это обычно easy-medium задачи leetcode.com
Из его аналогов можно отметить coderun от Яндекса и codewars
Подобные сервисы предлагают решать задачи на определённые темы (list, map,динамическое программирование и тд) или воспользоваться подборками с наиболее частыми задачами определённых компаний
Всем, кто сомневается в своих знаниях таких базовых вещей, как O-нотация, префиксные суммы или метод двух указателей рекомендую зарегаться и подтянуть свои знания
P.S. И хотя на практике алгоритмы(особенно сложные) очень редко применимы, их можно считать базой, которая развивает мозг и нет-нет да и пригодится
По уровню это обычно easy-medium задачи leetcode.com
Из его аналогов можно отметить coderun от Яндекса и codewars
Подобные сервисы предлагают решать задачи на определённые темы (list, map,динамическое программирование и тд) или воспользоваться подборками с наиболее частыми задачами определённых компаний
Всем, кто сомневается в своих знаниях таких базовых вещей, как O-нотация, префиксные суммы или метод двух указателей рекомендую зарегаться и подтянуть свои знания
P.S. И хотя на практике алгоритмы(особенно сложные) очень редко применимы, их можно считать базой, которая развивает мозг и нет-нет да и пригодится
🔥3🤩2⚡1
не спать всю ночь,
5 часов подряд перед работой в максимальном туннеле разбивать монолит на микросервисы,
на работе третий день подряд искать баг и найти его вообще не там где искал,
съездить в офис,
а вечером помогать разрабатывать архитектуру python сервиса для мэтчинга в проект, не имея в этом никакого опыта
tipical autistic developer day
5 часов подряд перед работой в максимальном туннеле разбивать монолит на микросервисы,
на работе третий день подряд искать баг и найти его вообще не там где искал,
съездить в офис,
а вечером помогать разрабатывать архитектуру python сервиса для мэтчинга в проект, не имея в этом никакого опыта
tipical autistic developer day
🔥3💯2👨💻2
только что в квалификационном контексте Yandex Cup по бекенду пытался решить безумно интересную задачу
Суть задачи в реализации шардирования и реплицирования данных из единственной бд по нескольким кеширующим серверам с учётом гарантированного отказа одного из них в рандомный момент, используя несколько библиотек, но ней фреймворки
Респект Яндексу за интересный формат задачи для контекста
И большой дизреспект за то, что конфиг для этой задаче собирается через go, который я не могу физически поставить на рабочий ноут, с которого и решал контест(
Суть задачи в реализации шардирования и реплицирования данных из единственной бд по нескольким кеширующим серверам с учётом гарантированного отказа одного из них в рандомный момент, используя несколько библиотек, но ней фреймворки
Респект Яндексу за интересный формат задачи для контекста
И большой дизреспект за то, что конфиг для этой задаче собирается через go, который я не могу физически поставить на рабочий ноут, с которого и решал контест(
eax.me
Шардинг, перебалансировка и распределенные транзакции в реляционных базах данных | Записки программиста
При разработке нового проекта в качестве основной СУБД нередко выбираются реляционные базы данных, такие, как PostgreSQL или MySQL. В этом действительно есть см
🤝3⚡1👨💻1
последние дни на работе занимаюсь оконными и генерирующими функциями в SQL, использую их для сбора статистических параметров из промышленной бд
оконная функция (в отличие от агрегирующей) рассчитывает значения для всех значений внутри партиции (окна, по сути - набора строк, отвечающему условиям) и сохраняет количество строк, что позволяет применять их последовательно/поочерёдно для всего набора набора данных
оконная функция (в отличие от агрегирующей) рассчитывает значения для всех значений внутри партиции (окна, по сути - набора строк, отвечающему условиям) и сохраняет количество строк, что позволяет применять их последовательно/поочерёдно для всего набора набора данных
👾3💯1🏆1
Наш проект отобрали для акселератора ИТМО🎉
И вот мы уже занимаемся первым заданием - проводим исследование рынка согласно Customer Development - разработке ориентированной на пользователей
Для этого мы проводим несколько десятков интервью по
специальному скрипту с целью выяснить потребности ЦА, выявить боли клиентов и подтвердить(или опровергнуть) наши гипотезы о полезности приложения
Дальше - больше!
И вот мы уже занимаемся первым заданием - проводим исследование рынка согласно Customer Development - разработке ориентированной на пользователей
Для этого мы проводим несколько десятков интервью по
специальному скрипту с целью выяснить потребности ЦА, выявить боли клиентов и подтвердить(или опровергнуть) наши гипотезы о полезности приложения
Дальше - больше!
🔥4⚡1💯1
Сейчас открыто сразу несколько интересных стажировок от крупных компаний, у всех есть направление Backend разработки на java
Стажировка - отличный способ получить коммерческий опыт для тех, у кого его еще нет. Также зачастую стажеров берут в штат после окончания стажки
Основные необходимые знания - java core и алгоритмы
- Авито
- Яндекс
- Тинек
Стажировка - отличный способ получить коммерческий опыт для тех, у кого его еще нет. Также зачастую стажеров берут в штат после окончания стажки
Основные необходимые знания - java core и алгоритмы
- Авито
- Яндекс
- Тинек
🤝2⚡1👨💻1
Java Backend Diary
Сейчас открыто сразу несколько интересных стажировок от крупных компаний, у всех есть направление Backend разработки на java Стажировка - отличный способ получить коммерческий опыт для тех, у кого его еще нет. Также зачастую стажеров берут в штат после окончания…
очень рекомендую всем, кто хочет найти работу сейчас или в будущем в IT - попробовать, проверить свой уровень и вполне вероятно попасть на стажировку
🤩2🔥1💯1
Забавная история из сегодняшнего задания - пофиксить баг в SQL запросе
Показалось, что при текущем построении запроса пофиксить не получится -
и я весь день пеерабатывал его с нуля, попутно пытаясь оптимизировать
Выяснилось, что новый запрос отрабатывает в10^-1 раз быстрее, зато правильно
К концу же дня, после тотального реворка оказалось, что можно было пофиксить баг добавив ОДНУ СТРОЧКУ
Казалось бы, день в помойку но это не так -
1)Я самовоспитывался, что принесло свои плоды,пусть и не сразу
2)Если в SQL ,который был моей слабой стороной я освоился - то с оптимизацией есть над чем работать(буду смотреть в сторону EXPLAIN ANALYZE/QUERY PLAN)
Показалось, что при текущем построении запроса пофиксить не получится -
и я весь день пеерабатывал его с нуля, попутно пытаясь оптимизировать
Выяснилось, что новый запрос отрабатывает в
К концу же дня, после тотального реворка оказалось, что можно было пофиксить баг добавив ОДНУ СТРОЧКУ
Казалось бы, день в помойку но это не так -
1)Я самовоспитывался, что принесло свои плоды,пусть и не сразу
2)Если в SQL ,который был моей слабой стороной я освоился - то с оптимизацией есть над чем работать(буду смотреть в сторону EXPLAIN ANALYZE/QUERY PLAN)
💯3⚡1🤩1
Сегодня, спустя месяц страданий я практически в одиночку запустил тестконтейнеры на рабочем проекте
Testcontainers - библиотека, позволяющая тестировать приложение целиком или отдельные модули в контейнере Docker, где также можно развернуть базу/очередь сообщений, кэш и тд
Это был мой первый опыт на такой большой системе и от осознания того, что все это сделал я, конечно, появляется чувство гордости и ответственности за проделанную работу
Testcontainers - библиотека, позволяющая тестировать приложение целиком или отдельные модули в контейнере Docker, где также можно развернуть базу/очередь сообщений, кэш и тд
Это был мой первый опыт на такой большой системе и от осознания того, что все это сделал я, конечно, появляется чувство гордости и ответственности за проделанную работу
🔥6
Мы ждали почти полгода и я вернулся!➡️
📈 Что у меня нового?
Продолжаю управлять в несколько раз выросшей командой разработки продукта @dada_tuda(Ждите статью о достигнутых результатах )
Сменил проект чтобы больше времени уделять своему (и больше получать)
Работаю над своим spring-boot стартером и другими полезными инструментами для enterprise разработки
📅 Какие планы?
Уже через несколько недель будет крупнейшая конференция по Java, еду туда от компании и привезу много полезного контента
Меньше месяца остается до первой стадии релиза, буду писать об интересных инцидентах и best-practice
Продолжу освещать всегда актуальные темы Роадмэпа Java-разработчика и подготовки к собеседованиям
Помимо этого я хочу делать действительно нужный и полезный контент, поэтому как всегда жду вашей обратной связи ⬇️
📈 Что у меня нового?
Продолжаю управлять в несколько раз выросшей командой разработки продукта @dada_tuda
Работаю над своим spring-boot стартером и другими полезными инструментами для enterprise разработки
📅 Какие планы?
Уже через несколько недель будет крупнейшая конференция по Java, еду туда от компании и привезу много полезного контента
Меньше месяца остается до первой стадии релиза, буду писать об интересных инцидентах и best-practice
Продолжу освещать всегда актуальные темы Роадмэпа Java-разработчика и подготовки к собеседованиям
Помимо этого я хочу делать действительно нужный и полезный контент, поэтому как всегда жду вашей обратной связи ⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7
Об инфобезопасности не начинаешь задумываться пока не украдут первую базу 💀
📌Свежий инцидент:
Мы сделали общий сбор логов - обычное продакшн решение
Использовали ELK - три инструмента, работающих вместе для сбора, хранения и анализа логов
UI оставили на дефолтном порту и с дефолтным паролем ...
Одним прекрасным утром обнаруживаем вот такое вместо своих логов😪
Выяснили что это проделки автоматических переборщиков открытых IP на дефолтных кредах
Вывод: ставьте пароли..
А если серьезно - это заставило нас задуматься об ИБ и боле жестких решениях - ждите отчеты о внедрении
📌Свежий инцидент:
Мы сделали общий сбор логов - обычное продакшн решение
Использовали ELK - три инструмента, работающих вместе для сбора, хранения и анализа логов
Одним прекрасным утром обнаруживаем вот такое вместо своих логов
Выяснили что это проделки автоматических переборщиков открытых IP на дефолтных кредах
Вывод: ставьте пароли..
А если серьезно - это заставило нас задуматься об ИБ и боле жестких решениях - ждите отчеты о внедрении
Please open Telegram to view this post
VIEW IN TELEGRAM
👾5
🔐 OAuth 2.0 и JWT-аутентификация: как это работает?
Каждый день мы используем OAuth 2.0, даже не задумываясь. Например, когда заходим наGit Hub через Google-аккаунт.
📌 Как это работает изнутри?
1️⃣ Предварительная настройка:
Задолго до того, как ты нажмёшь "Войти через Google", GitHub (клиент) и Google (сервер авторизации) договариваются об использовании OAuth. Google выдаёт GitHub client_id и client_secret.
2️⃣ Запрос авторизации:
Когда ты выбираешь вход через Google, GitHub перенаправляет тебя на страницу авторизации, передавая свой client_id и список запрашиваемых прав (например, доступ к email).
3️⃣ Выдача токена:
После успешного входа Google спрашивает у тебя разрешение и, если ты согласен, отправляет GitHub access-токен — временный ключ доступа.
4️⃣ Доступ к ресурсам:
Теперь GitHub использует этот токен для выполнения запросов от твоего имени (например, получения email или списка репозиториев).
5️⃣ Обновление токена:
Когда access-токен истекает, GitHub может запросить новый с помощью refresh-токена, который также выдал Google. Это позволяет не заставлять пользователя логиниться заново.
⚡️ Для продвинутых
Благодаря передаче access и refresh в Cookie, токены могут поочередно обновяться автоматически пока сессия не закончится
Каждый день мы используем OAuth 2.0, даже не задумываясь. Например, когда заходим на
📌 Как это работает изнутри?
1️⃣ Предварительная настройка:
Задолго до того, как ты нажмёшь "Войти через Google", GitHub (клиент) и Google (сервер авторизации) договариваются об использовании OAuth. Google выдаёт GitHub client_id и client_secret.
2️⃣ Запрос авторизации:
Когда ты выбираешь вход через Google, GitHub перенаправляет тебя на страницу авторизации, передавая свой client_id и список запрашиваемых прав (например, доступ к email).
3️⃣ Выдача токена:
После успешного входа Google спрашивает у тебя разрешение и, если ты согласен, отправляет GitHub access-токен — временный ключ доступа.
4️⃣ Доступ к ресурсам:
Теперь GitHub использует этот токен для выполнения запросов от твоего имени (например, получения email или списка репозиториев).
5️⃣ Обновление токена:
Когда access-токен истекает, GitHub может запросить новый с помощью refresh-токена, который также выдал Google. Это позволяет не заставлять пользователя логиниться заново.
⚡️ Для продвинутых
🤩3👨💻2✍1
Только что фиксил очень интересный баг на стенде // Post-mortem
Вводные: есть буффер рекомендаций для пользователя в пг-таблице, при его запросе если размер мал, происходит асинхронный дозапрос рекомендаций через RabbitMQ в другой сервис,перед отдачей рекомендаций пользователю они удаляются из буффера
Внезапно начала падать ошибка
Ресерч проблемы показал,что вторая транзакция вызывается непосредственно из-за
последовательность вызовов примерно такая:
1)запрос рекомендаций по пользователю
2)выборка из буффера
3)проверка на нормальный размер оставшегося буфера
4)дозапрос
5) поиск валидных заглушек вместо рекомендаций
6)удаление из буффера ответа
7)коммит
8)возврат ответа - рекомендаций
Однако нкито не учел,что при обработке ответа от сервиса рекомендаций будет открыта новая и (с некой вероятностью паралельная) транзакция, дозаписывающая в буффер по тому же user ID
Если ответ вклинится между 4 и 7 шагами и будет содержать отдаваемое сейчас мероприятие - получится что удаление из контекста сталкивается с тем, что в БД уже есть запись с тем же ID, а L1 кэш хранит «старое состояние».
Тут нужно сделать небольшую ремарку - мы используем постгрес и у него дефолтный уровень изоляции транзакций - READ COMMITED где могут встречаться аномалии (non-repeatable read и phantom read)
Соответственно если коммит дозаписи в буффер произорйдет раньше коммита основной транзакции, основная транзакций столкнется с аномалией,допустимой на нашем уровне изоляции,что и произошло
Однако интересный момент в том,что транзакция по сути сама инициировала (косвенно) эту самую вставку и стабильно кусала себя за хвост
В данном случае Hibernate спас нас от аномалии ценой убитой транзакции, но в случае голых запросов,суть ошибки бы не изменилсь
Лучшим решением оказалось вынести дозапрос(обращение в RMQ) в afterTransaction,что не так логично как поставить пессимистичную блокировку (самое простое решение), но имеет дополнительный бенефит в отказа от интеграционного взаимодействия с левой системой внутри транзакции(антипаттерн)
Вводные: есть буффер рекомендаций для пользователя в пг-таблице, при его запросе если размер мал, происходит асинхронный дозапрос рекомендаций через RabbitMQ в другой сервис,перед отдачей рекомендаций пользователю они удаляются из буффера
Внезапно начала падать ошибка
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [...RecommendationEntryEntity#....EventUserId@bae8cdbc]
Ресерч проблемы показал,что вторая транзакция вызывается непосредственно из-за
асинхронного дозапроса рекомендаций через RabbitMQ в другой сервис
последовательность вызовов примерно такая:
1)запрос рекомендаций по пользователю
2)выборка из буффера
3)проверка на нормальный размер оставшегося буфера
4)дозапрос
5) поиск валидных заглушек вместо рекомендаций
6)удаление из буффера ответа
7)коммит
8)возврат ответа - рекомендаций
Однако нкито не учел,что при обработке ответа от сервиса рекомендаций будет открыта новая и (с некой вероятностью паралельная) транзакция, дозаписывающая в буффер по тому же user ID
Если ответ вклинится между 4 и 7 шагами и будет содержать отдаваемое сейчас мероприятие - получится что удаление из контекста сталкивается с тем, что в БД уже есть запись с тем же ID, а L1 кэш хранит «старое состояние».
Тут нужно сделать небольшую ремарку - мы используем постгрес и у него дефолтный уровень изоляции транзакций - READ COMMITED где могут встречаться аномалии (non-repeatable read и phantom read)
Соответственно если коммит дозаписи в буффер произорйдет раньше коммита основной транзакции, основная транзакций столкнется с аномалией,допустимой на нашем уровне изоляции,что и произошло
Однако интересный момент в том,что транзакция по сути сама инициировала (косвенно) эту самую вставку и стабильно кусала себя за хвост
В данном случае Hibernate спас нас от аномалии ценой убитой транзакции, но в случае голых запросов,суть ошибки бы не изменилсь
Лучшим решением оказалось вынести дозапрос(обращение в RMQ) в afterTransaction,что не так логично как поставить пессимистичную блокировку (самое простое решение), но имеет дополнительный бенефит в отказа от интеграционного взаимодействия с левой системой внутри транзакции(антипаттерн)
👨💻3✍2💯1
О каскадных сбоях // Post-mortem #2
Решил я добавить в кластер еще один сервис для работы с данными (Apache Zeppelin, очень интересная игрушка для дата-инженеров)
Описал хельм, выставил requests / limits по памяти и cpu, коммичу
...
Через пару минут весь кластер лежит, фронты уже стучатся в личку с 503 статусом, графана алертит в чат, что все плохо
в UI кластера видно, что лежат почти все поды, статус Evicted -> не хватило диска
Окей - увеличил диск на ноде - проверяем - половина стоит, вторая стабильно падает
В целом для кубера вне облака это почти нормально - запросы на ресурсы превышают возможности, кубер начинает выгонять некоторые сервисы с ноды, становится полегче. Тут приходит менеджер над кубом (Argo CD) и возвращает изгнанников, и так по кругу пока ресурсов не дадут / запросы не порежут
Почему диск не помог: по совпадению именно в это время поставщик образов bitnami решил, что пора переводить всехи на новые образы и ...
у нас не встают Брокер Сообщений и База Данных (из старых образов), а вслед за тем и остальне сервисы, которые от них зависят - это и называется Каскадный сбой
Все это еще сильнее заставляет кубер крутиться и мы получаем такие картинки -
Вывод #1 проектируйте сервисы так, чтобы при недоступности базы/брокера уходить в retry а не падать
Вывод #2 imagePullPolicy: IfNotPresent нужна именно для предотвращения ошибок при проблемах на стороне поставщика образов, используй мы эту политику сразу - избежали бы часовго даунтайма
Решил я добавить в кластер еще один сервис для работы с данными (Apache Zeppelin, очень интересная игрушка для дата-инженеров)
Описал хельм, выставил requests / limits по памяти и cpu, коммичу
...
Через пару минут весь кластер лежит, фронты уже стучатся в личку с 503 статусом, графана алертит в чат, что все плохо
в UI кластера видно, что лежат почти все поды, статус Evicted -> не хватило диска
Окей - увеличил диск на ноде - проверяем - половина стоит, вторая стабильно падает
В целом для кубера вне облака это почти нормально - запросы на ресурсы превышают возможности, кубер начинает выгонять некоторые сервисы с ноды, становится полегче. Тут приходит менеджер над кубом (Argo CD) и возвращает изгнанников, и так по кругу пока ресурсов не дадут / запросы не порежут
Почему диск не помог: по совпадению именно в это время поставщик образов bitnami решил, что пора переводить всехи на новые образы и ...
у нас не встают Брокер Сообщений и База Данных (из старых образов), а вслед за тем и остальне сервисы, которые от них зависят - это и называется Каскадный сбой
Все это еще сильнее заставляет кубер крутиться и мы получаем такие картинки -
Вывод #2 imagePullPolicy: IfNotPresent нужна именно для предотвращения ошибок при проблемах на стороне поставщика образов, используй мы эту политику сразу - избежали бы часовго даунтайма
⚡2👨💻1