Для .NET-бэкендеров, которым мало просто выучить ответ про асинхронность
Синьорская многопоточка
В хайлоад берут с опытом хайлоада. Где его взять, если на работе нагрузки нет?
За четыре недели реализуешь восемь фич для высоконагруженного приложения и на собеседованиях будешь говорить про практический опыт
Старт 29 ноябряпродажи с 15 ноября
Бонусы только по анкете предзаписи до 14 ноября
Узнаёшь хотя бы один пункт?
- Монолит, CRUD и пара фоновых задач по расписанию. Гонкам там негде случиться, а
SemaphoreSlimиChannelты встречал только в статьях. - Собеседуешься туда, где нагрузка есть, и тебя спрашивают про какие-то рпсы и трафик. Рассказать нечего, а придуманную историю видно сразу.
- На собесе дают кусок кода: тут
.Wait(), там.Result, где-тоConfigureAwait(false). Спрашивают, что выведется, где сломается, а ты пытаешься угадать. - Про асинхронность прочитал, вроде понял. Через неделю на первом же уточнении отвечать нечего.
- Код уже пишет нейронка. Объяснять на ревью, почему он встанет под нагрузкой, всё равно тебе.
Откуда сеньор знает, как lock работает под капотом
Представь ночь. Сервис встал, процессор свободен, в логах тихо, а к утру надо разобраться, что здесь вообще происходит и какой поток кого ждёт. После такой ночи тебе придётся понять, как оно работает, и поймёшь ты это лучше, чем из любой статьи.
В простом CRUD-проекте такой ночи можно ждать годами. В программе их восемь за четыре недели. Каждую неделю на живом проекте ты сам разберёшься, почему оно здесь сломалось и как этого можно было избежать.
Как проходит неделя
- ТеорияУроки по 5–10 минут: как устроены поток, пул,
awaitи что делает рантайм. - ПрактикаВидео по проекту: что за фича, где она в коде, с чего начать, как имитировать нагрузку и куда смотреть на графиках.
- КодПишешь код в своём репозитории на GitHub.
- ПроверкаТесты и нагрузочный прогон. В «С проверкой» ещё моё код-ревью.
- ОбсуждениеСозвон группы: разбираем решения, ошибки и вопросы.
Программа
Неделя 1. Потоки, гонки, блокировки Что ломается, когда два запроса меняют одни данные
Блок 1. Карта: три слова, которые путают
- Сколько стоит поток и почему тысяча потоков не спасёт
- Многопоточность, параллельность, асинхронность: в чём разница
- Когда
asyncускоряет сервис, а когда нет
Блок 2. Гонки: счётчик, который врёт
- Два потока инкрементят один счётчик, и часть инкрементов теряется
- Как починить без блокировки
Блок 3. Что происходит внутри lock
- Как устроен
lockи откуда он знает, какой поток его держит - Почему одни блокировки почти бесплатны, а другие намного дороже
- Дедлок: как найти и не допустить
Блок 4. Что есть кроме lock
- Как пускать к базе не больше N запросов и не повесить сервис
- Какую блокировку брать, когда читателей много, а писатель один
- Почему потокобезопасный словарь теряет обновления
- Почему read-only коллекция не спасает от гонки
- Шпаргалка: какой инструмент когда
Практика
Задача 1. Распродажа, на которой падала половина заказов, проходит без ошибок
- Стартует чёрная пятница, тысячи покупателей жмут «Купить» на один товар, и падают заказы даже на обычные товары
- Напишем код так, чтобы один популярный товар не утягивал за собой всё остальное
Задача 2. Вдвое меньше запросов к базе на каждую цену
- Миллион показов карточек даёт миллион одинаковых запросов за правилами цен, хотя правила меняются реже
- Напишем код так, чтобы правила жили в памяти и покупатель никогда не видел цену наполовину по старым скидкам, наполовину по новым
исходный код
после фичи
Итог недели
За неделю ты подготовил магазин к распродаже и снял лишнюю нагрузку с базы. На собесе рассказываешь, как это сделал и что при этом происходит внутри lock.
Неделя 2. Пул потоков, Task, async/await Где запрос, пока ждёт ответа базы
Блок 5. ThreadPool: откуда берутся потоки
- Из чего состоит пул
- Почему пул добавляет потоки медленно и как из-за этого сервис встаёт при пустом процессоре
- Как пул сам подбирает число потоков и почему таски выполняются не в том порядке, в каком ты их поставил
- Как рантайм узнаёт, что БД уже ответила
Блок 6. Task: обещание результата
- Чем таска отличается от потока
- Куда девается исключение из таски и почему оно может потеряться
- Запустил десять запросов, упали три, а в логе одна ошибка
- Как завернуть в
Taskкод, который сообщает о результате колбэком
Блок 7. Что происходит на await
- Почему
asyncне создаёт потоков - Что делает метод, когда доходит до
await - Почему пауза через
Thread.Sleepдержит поток, а черезawaitнет - Стейт-машина: как метод продолжает с того места, где остановился
Практика
Задача 3. Пуш маркетинга не кладёт витрину: втрое меньше запросов к сервисам за ней
- Маркетинг разослал пуш с одним товаром. За секунду пришли тысячи покупателей, каждый запрос ушёл в шесть сервисов. Первыми легли отзывы, за ними витрина
- После фичи витрина переживает такой пуш, а сбой рекомендаций больше не показывает ошибку вместо страницы товара
Задача 4. Наличие по складам в полтора раза быстрее
- Перед распродажей открывают временные склады, и с каждым новым складом блок «Где купить» отвечает дольше
- Сделаем так, чтобы новый склад не добавлял времени, а заказам хватало соединений с базой. Прошлую распродажу положил именно пул соединений
Итог недели
За неделю ты ускорил карточку товара и проверку наличия. На собесе объясняешь, где находится запрос, пока ждёт базу, и почему поток в это время свободен.
Неделя 3. Контекст, поломки, отмена Ошибки в асинхронном коде, которые проходят ревью
Блок 8. Где ломается асинхронный код
- Когда действительно нужен
ConfigureAwait(false) - Почему
.Resultи.Wait()вешают сервис под нагрузкой - Почему
awaitнельзя внутриlockи что ставить вместо него - Как контекст запроса переживает
await - Что искать на ревью в чужом коде
Блок 9. Отмена
- Почему токен отмены сам ничего не останавливает
- Как правильно отменить работу, если клиент отвалился
Блок 10. ValueTask и аллокации
- Когда
ValueTaskэкономит аллокации, а когда всё ломает - Как рантайм пулит объекты
Практика
Задача 5. Карточка отвечает за секунду вместо ста, даже когда сервис завис
- Зависли рекомендации внизу страницы, и вся карточка висит до ста секунд. Покупатель давно ушёл, а сервисы всё работают
- После фичи карточка отвечает в срок: без цены не открывается, а опоздавшие рекомендации просто не показываем
Задача 6. Сроки доставки почти не пропадают с карточки, даже когда логистика лежит
- Легаси-клиент сервиса доставки то теряет сроки, то добивает перегруженную логистику повторами
- Найдёшь, почему так, и напишешь свой клиент на замену
Итог недели
Можешь рассказать, как сделал карточку, которая отвечает, даже когда сервис завис, и клиент, который не добивает упавшего партнёра.
Неделя 4. Диагностика, очереди, параллелизм Сервис встал ночью, процессор пустой
Блок 11. Почему сервис встал
- Ломаешь сервис сам: он стоит, а процессор свободен
- Какие метрики смотреть первыми
- Дамп: где стоит каждый поток и кто кого ждёт
- Трейс: как поймать аварию, которую не застал дамп
- Как идти от симптома к причине
- Три поломки разом: как подойти к проблеме
Блок 12. Очереди и стриминг
- Ограниченная очередь: быстрый продюсер ждёт медленного консьюмера, и память не растёт
- Как стримить данные из базы, не загружая всё в память
Блок 13. Модель памяти и lock-free
- Почему один поток не видит, что записал другой
- Барьеры памяти: как заставить потоки видеть записи друг друга
- Lock-free: как устроен и где ломается
Блок 14. Параллелизм
- Как раскидать вычисления по ядрам и почему на сервере не надо занимать все
Блок 15. Async в тестах
- Как написать тест на гонку, который ловит её в каждом прогоне
Практика
Задача 7. Прайс на миллион строк за минуту вместо получаса
- Крупный продавец присылает прайс на миллион строк. Загрузка идёт дольше получаса, падает по таймауту, продавец шлёт заново, и всё начинается сначала
- После фичи прайс успевает загрузиться, память не растёт, и при остановке сервиса ни одна принятая строка не теряется
Задача 8. Сервис больше не встаёт под ночной нагрузкой
- В 03:10 сервис перестал отвечать: процессор почти пустой, в логах ни одной ошибки, база в порядке. Перезапуск не помог
- Найдёшь причину по метрикам и дампу, починишь и напишешь разбор инцидента для команды. А заодно выгрузку каталога перестанешь держать в памяти целиком для каждого партнёра
Итог недели
Можешь рассказать, как по дампу нашёл, почему сервис встал ночью, и написал разбор инцидента. Когда сервис встаёт, знаешь, с какой команды начать.
Что изменится к 27 декабря
На собесе спрашивают про нагрузку, а рассказать нечего
В репозитории восемь фич с графиками до и после. Про каждую рассказываешь, что сломалось, как исправил и какие выводы сделал.
Ошибки в асинхронном коде всплывают уже в проде
На ревью замечаешь проблемы в асинхронном коде до того, как он уедет в прод.
Сервис встал, и непонятно, с чего начать
Снимаешь дамп и показываешь, где встряли потоки.
На уточнении пытаешься угадать
Мыслишь логически: механизм ты писал руками.
Тарифы
группа
Группа
или 5 834 ₽ в месяц на полгода
- 50+ уроков: от устройства
lockдо разбора дампа упавшего сервиса - Проект на четыре недели: восемь фич, ревью чужой библиотеки с настоящими багами и разбор инцидента
- Эталон после выполнения: как решено, почему так и что могло пойти не так
- Каждое решение проверяют тесты и нагрузка в k6
- Живой созвон группы каждую неделю, полтора часа
- Чат участников
- Доступ к урокам и проекту ещё год после конца группы
советую его, всего 15 мест
С проверкой
или 8 334 ₽ в месяц на полгода
- Всё из «Группы»
- Код-ревью каждого решения, пока код не станет таким, какой я принял бы на работе
- Отвечаю на вопросы в тот же рабочий день
Бонус предзаписи
Финальный созвон, час
Час вдвоём после четвёртой недели. Проходим голосом все темы, с уточнениями, и в конце у тебя список, что подтянуть.
3 места
Лично
или 16 667 ₽ в месяц на полгода
- Всё из «С проверкой»
- Созвон один на один каждую неделю, час
- Пишешь мне в личку в любой день, отвечаю в тот же день
- На личных созвонах смотрим твой код и слабые темы
Бонус предзаписи
Два месяца разборов после группы
Задали вопрос по многопоточке на собесе? Приноси, разберёмся. До трёх созвонов.
Вопросы
За предзапись надо платить?
Нет, это анкета: имя, почта и Telegram. После этого я напишу тебе лично и сориентирую по дальнейшим шагам.
Сколько времени в неделю? Совмещу с работой?
Уроки недели: 11–13 штук по 5–10 минут, это час-два, плюс видео по проекту. Созвон: полтора часа. Остальное время уходит на код: две фичи с тестами, нагрузочным прогоном и пулл-реквестом. Закладывай около десяти часов в неделю. Сдаёшь решение до конца недели.
Не успеваю по графику. Что будет?
Созвоны записываются, открытые уроки и проект остаются у тебя ещё год после конца группы. Решение можно сдать после срока: тесты проверят его так же, но моё ревью только в установленные сроки.
Я мидл. Мне рано?
Нет, если пишешь бэкенд на C# и видел async в коде. Программа рассчитана на вход с уровня джуна или мидла.
Можно писать код с нейронкой?
Можно, но зачем? Цель в том, чтобы один раз разобраться в механике и понять причину. Каждый раз писать такой код руками незачем, но первый раз напиши сам: без этого непонятно, почему он работает.
Можно в рассрочку?
Да, на полгода, сумма та же, что при оплате сразу.
Можно оплатить из-за границы?
Да. На странице оплаты есть кнопка «Зарубежной картой»: доллары, евро или белорусские рубли. Если карта не пройдёт, напиши мне в Telegram, найдём другой способ.
Платит работодатель.
Напиши мне в Telegram, пришлю счёт и договор на юрлицо. Цена та же.
Дальше три варианта
- Ничего не менять. Перед следующим собесом снова откроешь те же статьи и посыпешься на таком же уточнении, но в другую сторону.
- Разобраться самому. Рихтер, исходники рантайма, блог Стивена Тауба, свои эксперименты: всё это есть в открытом доступе. Стенда с нагрузкой и человека, который скажет, где ты ошибся, там нет.
- Пойти в группу. Четыре недели по графику, восемь фич под нагрузкой и созвон каждую неделю.
Займи место в очереди
Выбери тариф и оставь имя, почту и Telegram. Платить сейчас ничего не нужно. После заявки напишу тебе лично и сориентирую по дальнейшим шагам.