Чому важливо керувати часом життя сервісів?
Управління часом життя сервісів (lifetime management) у Dependency Injection - це ключ до стабільної, передбачуваної і масштабованої архітектури. Без нього система починає "текти" - у прямому сенсі: по пам'яті, по продуктивності і по логіці.
Розберемо по суті.
1. Щоб уникнути витоків пам'яті
Якщо об'єкт живе довше, ніж повинен, він залишається в пам'яті навіть після того, як перестав бути потрібним.
Наприклад, Singleton зберігає посилання на залежність, створену як Scoped (яка живе один запит).
У підсумку:
- кожен новий запит створює нові екземпляри,
- старі не очищаються,
- пам'ять росте, продуктивність падає.
Висновок: неправильний lifetime може утримувати зайві об'єкти і заважати збірці сміття.
2. Щоб уникнути конфліктів стану
Коли різні клієнти (користувачі, запити) отримують один і той самий екземпляр сервісу, у ньому може зберігатися стан попереднього запиту.
Приклад:
public class UserSession {
public string CurrentUser { get; set; }
}Якщо цей сервіс випадково зареєстрований як Singleton, то CurrentUser буде спільним для всіх.
Висновок: кожен контекст (запит, сесія) повинен мати свій стан, і lifetime повинен це відображати.
3. Щоб уникнути надлишкового створення об'єктів
Якщо сервіс оголошено як Transient, контейнер створює новий екземпляр при кожному зверненні.
Це може бути виправдано для легких утиліт, але катастрофічно для важких сервісів, наприклад підключення до БД чи зовнішнього API.
Результат:
- зайве навантаження на процесор,
- зростання часу відгуку,
- збільшення кількості відкритих з'єднань.
Висновок: ресурсомісткі сервіси повинні жити довше (singleton / scoped), щоб не перестворюватися постійно.
4. Щоб забезпечити коректне управління ресурсами
Lifetime напряму впливає на життєвий цикл підключень, транзакцій і потоків.
Наприклад:
Scoped-сервіс (один на запит) може безпечно тримати транзакцію з базою даних.- Якщо зробити його
Singleton, транзакції різних користувачів почнуть конфліктувати. - А якщо
Transient, транзакція розірветься між викликами.
Висновок: правильний lifetime гарантує, що ресурси живуть стільки, скільки потрібно, і не довше.
5. Щоб спростити масштабування і тестування
- У тестах
Transientдозволяє створювати незалежні екземпляри. - У продакшені
Singletonзнижує навантаження. - У вебзастосунках
Scopedгарантує чистоту даних між запитами.
Правильне управління часом життя робить систему передбачуваною при навантаженні, у багатопотоковості і при паралельних запитах.
Підсумок
| Lifetime | Де використовувати | Мета |
|---|---|---|
| Singleton | для спільних сервісів (логери, конфіг, кеш) | стабільність і продуктивність |
| Scoped | для сервісів, що працюють з даними запиту/сесії | ізоляція стану |
| Transient | для легких, stateless-компонентів | гнучкість і чистота даних |
Головна думка:
Управління часом життя сервісів - це управління ресурсами і межами відповідальності. Якщо lifetime обрано неправильно, система втрачає пам'ять, логіку і надійність. Якщо правильно - стає легкою, масштабованою і безпечною.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.