В проде под нагрузкой API начинает подвисать, медиана ответа растёт с 40 мс до 400 мс, а иногда и выше.
Логи показывают, что в горячем месте встречается такой
public async Task<User> GetUserAsync(int id)
{
using var conn = new SqlConnection(_conn);
conn.Open(); // 👈 синхронный блокирующий вызов
var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT * FROM Users WHERE Id = @id";
cmd.Parameters.AddWithValue("@id", id);
using var reader = cmd.ExecuteReader(); // 👈 тоже блокировка
if (await reader.ReadAsync())
return Map(reader);
return null;
}
Под нагрузкой резко растёт:
- очередь ThreadPool
- количество заблокированных потоков
- p99 latency
Какой вариант исправления правильный?
1. Заменить ExecuteReader на ExecuteReaderAsync, но оставить conn.Open() как есть.
2. Вынести всё выполнение в Task.Run и пусть код работает на отдельных потоках.
3. Переписать весь путь на асинхронный: использовать OpenAsync, ExecuteReaderAsync и полностью убрать sync-over-async.
Как думаешь, какой вариант правильный?
Please open Telegram to view this post
VIEW IN TELEGRAM
Олег Шелест - профессионал по информационной безопасности, раскрывает скрытые механики Linux, с помощью наглядных картинок и коротких, максимально понятных разборов у себя в тг канале.
- Без воды.
- Без лишней теории.
Только практические приёмы, которые реально используют профи.
Если хочешь уверенно владеть Bash - здесь ты получишь всё, что нужно: t.iss.one/bashmastter
Please open Telegram to view this post
VIEW IN TELEGRAM
✔️ Задача C# и ASP.NET Core
В проде под нагрузкой периодически "умирает" интеграция с внешним сервисом оплаты:
в логах всплывают TimeoutException и SocketException: "Only one usage of each socket address...".
Фрагмент кода из сервисного слоя:
Под нагрузкой:
- растёт количество TIME_WAIT соединений
- часть запросов получает timeout
- p95 и p99 по этому методу улетают в космос
Какой вариант исправления правильный?
1. Увеличить Timeout у HttpClient и ServicePointManager.DefaultConnectionLimit.
2. Сделать HttpClient статическим полем и переиспользовать его во всех запросах.
3. Зарегистрировать HttpClient через IHttpClientFactory и использовать пул подключений, конфигурируя таймауты и политику повторов.
Как думаешь, какой вариант правильный?
В проде под нагрузкой периодически "умирает" интеграция с внешним сервисом оплаты:
в логах всплывают TimeoutException и SocketException: "Only one usage of each socket address...".
Фрагмент кода из сервисного слоя:
public class PaymentClient
{
private readonly string _baseUrl;
public PaymentClient(string baseUrl)
{
_baseUrl = baseUrl;
}
public async Task<bool> ChargeAsync(ChargeRequest request)
{
using var http = new HttpClient();
http.BaseAddress = new Uri(_baseUrl);
var response = await http.PostAsJsonAsync("/charge", request);
return response.IsSuccessStatusCode;
}
}
Под нагрузкой:
- растёт количество TIME_WAIT соединений
- часть запросов получает timeout
- p95 и p99 по этому методу улетают в космос
Какой вариант исправления правильный?
1. Увеличить Timeout у HttpClient и ServicePointManager.DefaultConnectionLimit.
2. Сделать HttpClient статическим полем и переиспользовать его во всех запросах.
3. Зарегистрировать HttpClient через IHttpClientFactory и использовать пул подключений, конфигурируя таймауты и политику повторов.
Как думаешь, какой вариант правильный?
Что выведет на экран это код?
Anonymous Quiz
39%
1,2,3,4
19%
2,3,4
4%
1,2,3
18%
бесконечно будет выводить 1
6%
бесконечно будет выводить 0
5%
Код не скомпилируется
10%
Как сделать .NET-приложения устойчивыми с помощью Polly
Polly — это мощная библиотека для обработки сбоев и нестабильных сетевых вызовов в .NET.
С её помощью можно легко добавить retry, timeout, circuit breaker и другие стратегии отказоустойчивости.
На картинке показан пример, где применяется два ключевых механизма:
1) Retry (повтор запроса при ошибках)
— Обрабатываем конфликты через
— Делаем паузу между попытками (`Delay = 1 сек`)
— Используем экспоненциальный backoff
— Добавляем jitter, чтобы избежать «шторма» повторов
— Ограничиваем количество попыток (`MaxRetryAttempts = 2`)
2) Timeout (ограничение времени выполнения)
— Ставим таймаут в 10 секунд на сетевой запрос
Далее создаётся pipeline и выполняется HTTP-запрос:
Эти две стратегии уже дают серьёзную устойчивость:
запросы не зависают, ошибки перехватываются, приложение остаётся стабильным даже при нестабильных сервисах.
https://github.com/App-vNext/Polly
Polly — это мощная библиотека для обработки сбоев и нестабильных сетевых вызовов в .NET.
С её помощью можно легко добавить retry, timeout, circuit breaker и другие стратегии отказоустойчивости.
На картинке показан пример, где применяется два ключевых механизма:
1) Retry (повтор запроса при ошибках)
— Обрабатываем конфликты через
Handle<ConflictException>() — Делаем паузу между попытками (`Delay = 1 сек`)
— Используем экспоненциальный backoff
— Добавляем jitter, чтобы избежать «шторма» повторов
— Ограничиваем количество попыток (`MaxRetryAttempts = 2`)
2) Timeout (ограничение времени выполнения)
— Ставим таймаут в 10 секунд на сетевой запрос
Далее создаётся pipeline и выполняется HTTP-запрос:
await pipeline.ExecuteAsync(async ct ⇒ await httpClient.GetAsync("https://modularmonolith.com", ct));Эти две стратегии уже дают серьёзную устойчивость:
запросы не зависают, ошибки перехватываются, приложение остаётся стабильным даже при нестабильных сервисах.
https://github.com/App-vNext/Polly
Media is too big
VIEW IN TELEGRAM
⚡️ Hunyuan 3D Engine
Новый высокоточный ИИ-движок сокращает производство коммерческих 3D-ассетов с недель до нескольких минут.
Платформа поддерживает создание объектов из текста, изображений с мультивидовой реконструкцией и даже из простых скетчей. Это делает процесс максимально гибким и доступным как художникам, так и командам в индустрии.
Качество отвечает профессиональному уровню. Новый 3D-DiT модельный стек обеспечивает трёхкратный прирост точности и выдаёт ультра-HD разрешение. Форматы OBJ и GLB легко подключаются к Unreal Engine, Unity и Blender.
Модель также доступна через Tencent Cloud International.
Платформа даёт новым авторам 20 бесплатных генераций в день. Корпоративные клиенты получают 200 бесплатных кредитов при регистрации.
Попробовать движок можно на 3d.hunyuanglobal.com
API: tencentcloud.com/products/ai3d
#AI #3D #Hunyuan3D #Tencent #AItools #3Dgeneration
Новый высокоточный ИИ-движок сокращает производство коммерческих 3D-ассетов с недель до нескольких минут.
Платформа поддерживает создание объектов из текста, изображений с мультивидовой реконструкцией и даже из простых скетчей. Это делает процесс максимально гибким и доступным как художникам, так и командам в индустрии.
Качество отвечает профессиональному уровню. Новый 3D-DiT модельный стек обеспечивает трёхкратный прирост точности и выдаёт ультра-HD разрешение. Форматы OBJ и GLB легко подключаются к Unreal Engine, Unity и Blender.
Модель также доступна через Tencent Cloud International.
Платформа даёт новым авторам 20 бесплатных генераций в день. Корпоративные клиенты получают 200 бесплатных кредитов при регистрации.
Попробовать движок можно на 3d.hunyuanglobal.com
API: tencentcloud.com/products/ai3d
#AI #3D #Hunyuan3D #Tencent #AItools #3Dgeneration
🎮 Создайте игры с s&box!
s&box — это современный игровой движок на основе Source 2 от Valve и новейших технологий .NET. Он предлагает интуитивно понятный редактор для разработки игр и предоставляет возможность компилировать движок из исходников для тех, кто хочет внести свой вклад в его развитие.
🚀 Основные моменты:
- Современный игровой движок с мощным редактором.
- Основан на Source 2 и .NET технологиях.
- Поддержка разработки и компиляции из исходников.
- Полная документация и обучающие материалы доступны онлайн.
📌 GitHub: https://github.com/Facepunch/sbox-public
#csharp
s&box — это современный игровой движок на основе Source 2 от Valve и новейших технологий .NET. Он предлагает интуитивно понятный редактор для разработки игр и предоставляет возможность компилировать движок из исходников для тех, кто хочет внести свой вклад в его развитие.
🚀 Основные моменты:
- Современный игровой движок с мощным редактором.
- Основан на Source 2 и .NET технологиях.
- Поддержка разработки и компиляции из исходников.
- Полная документация и обучающие материалы доступны онлайн.
📌 GitHub: https://github.com/Facepunch/sbox-public
#csharp
Что выведет на экран этот код?
Anonymous Quiz
28%
1, 2, finally!, exception!
25%
1, finally!, 2, finally!, exception!
10%
1, 2, exception!
15%
1, 2, finally!, 2, 2
7%
1, 2, finally!, 1, 2
16%
Синхронный
lock не работает с async/await, и многие пытаются заменить его чем угодно, лишь бы компилилось. Правильный путь — использовать SemaphoreSlim с WaitAsync, как на примере: он позволяет ограничивать конкуренцию и работает корректно в асинхронном коде.Главное — всегда освобождать семафор в
finally и не забывать про таймауты, чтобы не создавать висячие блокировки.Асинхронная синхронизация — это не магия, а аккуратность и понимание того, как работает планировщик задач в .NET.
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡️ Annotation Toolkit помогает дизайнерам прямо в макете объяснить, как должны работать элементы интерфейса.
Проще говоря, он позволяет:
подписывать элементы: что кликается, что меняется, как ведёт себя при разной ширине экрана;
сразу указать требования по доступности: например, какой alt-текст нужен или что должно быть доступно с клавиатуры;
убрать путаницу при передаче макета разработчикам, чтобы они точно понимали задумку.
Почему это важно:
Почти половина ошибок по доступности появляется только потому, что дизайнеры и разработчики по-разному понимают поведение элемента. Если зафиксировать эти детали заранее - проблемы просто не возникнут.
https://github.blog/enterprise-software/collaboration/level-up-design-to-code-collaboration-with-githubs-open-source-annotation-toolkit/
Проще говоря, он позволяет:
подписывать элементы: что кликается, что меняется, как ведёт себя при разной ширине экрана;
сразу указать требования по доступности: например, какой alt-текст нужен или что должно быть доступно с клавиатуры;
убрать путаницу при передаче макета разработчикам, чтобы они точно понимали задумку.
Почему это важно:
Почти половина ошибок по доступности появляется только потому, что дизайнеры и разработчики по-разному понимают поведение элемента. Если зафиксировать эти детали заранее - проблемы просто не возникнут.
https://github.blog/enterprise-software/collaboration/level-up-design-to-code-collaboration-with-githubs-open-source-annotation-toolkit/
44 000 000+ операций c товарами осуществляется на складских объектах Ozon. Лучший способ влиять на то, как эти товары находят дорогу к покупателям, — откликнуться на одну из этих вакансий.
✔️В команду расписания и отгрузки магистрали:
Руководитель группы разработки C#
Старший C#-разработчик
✔️В команду коммерциализации логистики:
Старший C#-разработчик
✔️В команду учётной интеграции и претензионной работы:
Руководитель группы разработки C#
Старший C#-разработчик
C#-разработчик
Удачи на интервью! 🍀
✔️В команду расписания и отгрузки магистрали:
Руководитель группы разработки C#
Старший C#-разработчик
✔️В команду коммерциализации логистики:
Старший C#-разработчик
✔️В команду учётной интеграции и претензионной работы:
Руководитель группы разработки C#
Старший C#-разработчик
C#-разработчик
Удачи на интервью! 🍀
Почти 50 процентов разработчиков сталкиваются с утечками памяти в EF Core.
И причина у большинства одна и та же.
❌ Ошибочное управление временем жизни DbContext
Многие регистрируют
На деле всё сложнее.
- DbContext не потокобезопасен.
Делить один экземпляр между потоками приводит к исключениям.
- DbContext лёгкий и должен жить недолго.
Создавай его часто, освобождай сразу.
- Неверная работа с контекстом ведёт к росту памяти и утечкам.
✅ Решения которые уже есть в EF Core
IDbContextFactory
Позволяет безопасно создавать контексты по запросу.
Подходит для фоновых задач, многопоточности и десктоп приложений.
DbContext Pooling
Переиспользует заранее подготовленные экземпляры.
Сбрасывает состояние после использования, снижает нагрузку на память и процессор.
Pooled DbContextFactory
Комбинирует фабрику и пул.
Даёт контексты по запросу и эффективно их переиспользует.
⚠️ Правила которые нельзя нарушать
- Никогда не дели DbContext между потоками.
- Всегда освобождай контекст с помощью using или возврата в пул.
Грамотное управление жизненным циклом DbContext повышает стабильность и масштабируемость и убирает скрытые утечки памяти которые годами портят EF Core проекты.
https://antondevtips.com/blog/top-10-mistakes-developers-make-in-ef-core/
И причина у большинства одна и та же.
❌ Ошибочное управление временем жизни DbContext
Многие регистрируют
DbContext как scoped и считают что этого достаточно. На деле всё сложнее.
- DbContext не потокобезопасен.
Делить один экземпляр между потоками приводит к исключениям.
- DbContext лёгкий и должен жить недолго.
Создавай его часто, освобождай сразу.
- Неверная работа с контекстом ведёт к росту памяти и утечкам.
✅ Решения которые уже есть в EF Core
IDbContextFactory
Позволяет безопасно создавать контексты по запросу.
Подходит для фоновых задач, многопоточности и десктоп приложений.
DbContext Pooling
Переиспользует заранее подготовленные экземпляры.
Сбрасывает состояние после использования, снижает нагрузку на память и процессор.
Pooled DbContextFactory
Комбинирует фабрику и пул.
Даёт контексты по запросу и эффективно их переиспользует.
⚠️ Правила которые нельзя нарушать
- Никогда не дели DbContext между потоками.
- Всегда освобождай контекст с помощью using или возврата в пул.
Грамотное управление жизненным циклом DbContext повышает стабильность и масштабируемость и убирает скрытые утечки памяти которые годами портят EF Core проекты.
https://antondevtips.com/blog/top-10-mistakes-developers-make-in-ef-core/
🔥 C# Pattern Matching — делает ваш код чище
Вместо громоздких проверок вида:
✨ Что изменилось?
✔️ Нет ручных проверок на null - компилятор сам учитывает это в выражении
✔️ Условие читается как описание объекта, а не как набор проверок
✔️ Логика становится компактнее и легче сопровождается
Используйте pattern matching, чтобы избавляться от лишнего шума и писать более понятный код.
Вместо громоздких проверок вида:
if (user != null &&
user.Name.Length > 0 &&
user.Subscription != null)
{
// ...
}
C# позволяет писать проще и выразительнее:
if (user is { Name.Length > 0, Subscription: not null })
{
// ...
}
✨ Что изменилось?
✔️ Нет ручных проверок на null - компилятор сам учитывает это в выражении
✔️ Условие читается как описание объекта, а не как набор проверок
✔️ Логика становится компактнее и легче сопровождается
Используйте pattern matching, чтобы избавляться от лишнего шума и писать более понятный код.