Solution Architect в EPAM
  • Чому SOLID — важлива складова мислення програміста. Розбираємося на прикладах з кодом

    Connect передбачає підключення до чогось. Підключення до локального файлу як мінімум звучить дивно.
    Так у вас же работа не с файлами, а с «источниками данных». То что источником является локальный файл — это деталь реализации.

    Так все ж так і є. IDataSource та IRemoteDataSource — це абстракції. IRemoteDataSource додаткового вимагає ще метода сonnect. До файлів, локального кеша, та навід вводу з command line вам підключатись не потрібно. Тому їх реалізацій ви будете наслідувати IDataSource. До віддалених джерел даних, таких як бази даних, розподілені кеші, розподілені черги ви маєте якось спочатку підключитись. Тому до їх реалізацій ви будете використовувати IRemoteDataSource, який вимагає методу connect.

    разделив ремоут и не ремоут датасорсы вы рискуете получить код который работает с датасорсом и не имеет возможности использовать ремоут датасорсы

    Ну, що краще, робити додаткову перевірку на IRemoteDataSource і викликати connect тільки для тих об’єктів, які дійсно його потребують, чи викликати зайвий метод connect, щоб прочитати файл, локальний кеш чи командну стрічку?

  • Чому SOLID — важлива складова мислення програміста. Розбираємося на прикладах з кодом

    Стаття написана виходячи зі свого досвіду Code Review та співбесід. Про Liskov Substitution переважно відповідають всі і про підводні камені також знають переважно всі. Open/Close крім поліморфізму ніхто нічого не каже. От ніхто. Коли починаєш наводити якісь приклади, чи самому підштовхувати до відповіді, то так, люди починають замислюватись і генерують якісь відповіді. Така ж ситуація і на код рев’ю: коли запитуєш, як ти плануєш розширяти код через тиждень, коли буде ось ця і ось ця фіча, то всі відразу бачать проблему. Але задетектати її наперед не всім вдається і ще крім того, розширяти без наступних змін класу — часто це буває челендж.
    Як бачу Liskov Substitution викликав багато інтересу. На вихідних тоді попрацюю над розширеною версією.

  • Чому SOLID — важлива складова мислення програміста. Розбираємося на прикладах з кодом

    Цікаве твердження про нові мови програмування. Я з Котліном не мав справи, але знайшов, що там є companion object та @JvmStatic. У всіх посиланнях я знаходжу це як аналог до Java static. Але ніхто не каже, в чому принципова різниця. Ну так, ви зайжди викликаєте метод з companion об’єкта, а не класу. Але це суті не змінює, виклик залишається MyClass.f(). Хотілось би розібратись в цьому питання та почути вашу думку.
    Також, чи ви вважаєте Rust та Swift новими мовами програмування? На скільки я знайшов, у них є статичні методи.
    А в чому проблема таких методів як Console.Read() та JSON.parse? Невже new Console().Read() дає якісь переваги?
    Також не експерт в Gо, але на скільки я прочитав, то кажуть що в Go є структури, а не класи і цим пояснюють відсутність static.
    У мене є певний досвід проблем з статичними методами, особливо покриття їх тестами. Але я не можу сказати, що це катастофічні проблеми. Тому дуже хотілось би почути аргументовану розгорнуту відповідь.

  • Чому SOLID — важлива складова мислення програміста. Розбираємося на прикладах з кодом

    Чому subscriptionType є приватним? Якщо я хочу дізнатись ім’я користувача, чи його імейл, то чим це відрізняється від того, що я хочу дізнатися тип підписки користувача?
    Дані readonly, тобто модифікувати їх ззовні (та й всередині) не получиться. Звісно можна додати get set, але чи варто?
    Повністю підтримую 2 інтерфейси і реалізацію цих інтерфейсів в одному класі чи декількох в залежності від конкретних бізнес задач.

    Підтримав: Dmitry Bugay
  • Чому SOLID — важлива складова мислення програміста. Розбираємося на прикладах з кодом

    Нехай у користувача є email — user.email. Що ми будемо робити, якщо додасться ще alternative email та isValidatedEmail? Ну нехай ми створимо об’єкт UserEmails і будемо в ньому зберігати посилання на користувача і всі його імейли, включаючи основний, і чи ці імейли провалідовані. А що, якщо така ж сама ситуація буде і з адресою проживання? А з прізвищем? А з імнем? Якщо слідувати за логікою все «окремий об’єкт», то у нас буде об’єкт User, в якого є тільки ID. Чи буде у нас користь з такого об’єкта? А якщо такі об’єкти ще й будуть зберігатись в реляційній базі даних, скільки це join треба зробити, щоб зібрати всю інформацію про об’ект.
    Якщо підписка користуча визначає кожен його крок (які фільми можна дивитися, який інтерфейс показувати, які фічі активувати) і в осяжному майбутньому вона не буде змінюватися, то навіщо нам робити окремий об’єкт UserSubscription, якого весь час його доведеться шукати по user.id? Якщо тип підписки є такою ж невід’ємною частиною сутності користувача, як і email, name і address, то навіщо її відділяти?
    Відповідаючи на ваше запитання про кількість дивайсів і користувачів у підписці. Давайте розглянемо UI/UX. Ми десь цю інформацію збираємось показувати? Як це вплине на функціонал користувача? Скоріш за все ця інформація буде використовуватися під час авторизації запиту на перегляд. Якщо кількість дивайсів перевищила максимально можливу, або з вашого акаунту дивляться більше, ніж дозволено користувачів, то вам верне 403 і ви покажете коирстувачу помилку. І тут у вас не буде великий об’єкт User, в якому буде все. У ньому буде лише тип підписки. За типом підписки ви отримаєте деталі підписки (іншим запитом у базу або кеш), а саме кількість дивайсів та користувачів.
    Треба в першу чергу розуміти свій домен. Користувач, який дивиться фільми, не такий самий користуч, який грає в одлайн ігри. Якщо невід’ємна частина першого є його підписка на контент, то невід’ємною частиною другого є те, чи він онлайн.

    Підтримав: Dmitry Bugay
  • Чому SOLID — важлива складова мислення програміста. Розбираємося на прикладах з кодом

    Connect передбачає підключення до чогось. Підключення до локального файлу як мінімум звучить дивно. Можна додати метод Open, який підготує файл для читання, але ця операція буде синхронною, так як може відразу перевірити чи файл доступний на диску і чи є права на читання. Connect вимагає часу для встановлення TCP з’єднання, тому таку операцію краще робити асинхронною.

  • Чому SOLID — важлива складова мислення програміста. Розбираємося на прикладах з кодом

    Дуже слушне зауваження. Вже виправили. Дякую!

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Додав декілька версій. Є Docker container з MySQL та Redis. Під час запуску Docker генеруються рандомні дані для 1000 міст і записуються в MySQL і Redis. Load test для кожного із 1000 користувачів робить запит на різне місто.
    /v9 — обрахунки в SQL запиті, без індексів
    /v10 — обрахунки в SQL запиті, з індексами
    /v11 — обрахунки у веб-сервісі, але дані беруться з Redis
    /v12 — обрахунки у веб-сервісі, дані перший раз беруться з Redis, а тоді кешуються в пам’яті процесу. Кешуються саме початкові дані, а не ті, для яких вже пораховані середні температури.

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    process.hrtime() - не знав про цей метод. Виглядає класно! Змерджив. Після мерджу другий PR вже був з конфіктами.

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Спочатку був DB First підхід. Всю логіку писали в сторед процедурах. Простий API, який тільки вмів викликати базу і віддавати результат на фроненд.
    Потім прийшов Code First. Пишемо бекенд, а тоді вибираємо базу або навіть набір баз данних, які нам підходять. Фокус не на данних, а на тому, що з ними можна робити.
    Зараз UI First. Проектуємо складні процеси на UI, потім робимо декілька бекендів (microservises, serverless), а тоді під бекенди вибираємо бази данних.
    Я це пишу до того, що бекенд має диктувати базі, які там мають бути індекси. Добре оптимізуєте бекенд, а тоді вже оптимізуєте базу під його потреби. При чому під різні потреби можна зробити різні бази даних: одна на читання, а друга на запис — CQRS

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Вы не внимательно прочитали мой ответ и повторяете мои слова как утверждение мне же:

    Я і не намагався вам нічого заперечувати. Просто сказав, що я відтворив теж саме, про що ви говорили, 1 в 1.

    оталкиваться в написании кода на Nodejs от неких парадигм, например:

    1.

    основною структурою буде завжди хеш таблиця (не має значення чи то об’єкт чи його похідна — массив).

    .
    — ні. у випадку об’єкта — це буде хеш таблиця. у випадку Array — буде List. ryanpeden.com/...​rays-work-under-the-hood.
    2. +
    2.5 про антипатерн. ну +/-. якщо вже є підключений лодаш, і хтось напише _.sumBy замість нативної reduce, ну мені важко сказати, що це погано. з одного боку користуватися нативними функціями — це добре, з іншого sumBy явно каже, що ти робиш. не готовий відповісти, +/-
    3. + до вкладених циклів. +/- «Плоское лучше, чем вложенное» — ну а якщо є дерево, чи хеш табилця має вкладені масиви, чи навіть матриця — це все певного роду вкладення.

    Нужно ли столько «оптимизировать» если изначально оталкиваться в написании кода на Nodejs от неких парадигм, например:

    Хтось казав, не пригадаю хто, що немає поганих алгоритмів — є неоптимізовані. Слідувати певним парадигмам — це необхідка ознака оптимального алгоритму, але не достатня. «Нужно ли столько „оптимизировать“» «столько» залежить від початкових requirements, від середовища, де буде виконуватися програма, від навантаження і так далі. «столько» — це можуть бути супер оптимізовані алгоритми для людини, яка їх пише сходу, бо добре володіє ними. Не завжди оптимальні алгоритми вимагають надзусиль. Якщо ви володієте базовими речами, то ви будете писати оптимальні алгоритми не докладаючи до цього особиливих чусиль, але це не буде тому, що ви слідуєте парадигмам, а тому, що ви розумієте, що робите, а не робити здогадки про це.

    Bottom line — парадигми потрібні, але їх не завжди достатньо

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    О, коли вже якісь цифри і формули, то вже можна предментно поговорити.
    Але давайте я спрочатку покажу деякі результати, того, що було відбулося на практиці.
    Я створив Azure сторе і залив туди JSON 3.3 мб.
    Тоді додав CDN, він цей файлик зжимає через gzip і маємо 200кб. Відповідь приходить за 300 мілісекунд, тому я в коді ще додатково, що чекаю, щоб було 800 як у формулі.

      async v7(): Promise<Result> {
        const start = new Date();
        const response = await axios.get('https://weather-dou.azureedge.net/weather/hourly.json', {
          headers: {
            'Accept-Encoding': 'gzip'
          }
        });
    
        const responseTime = new Date().getTime() - start.getTime();
        await this.timeout(responseTime < 800 ? 800 - responseTime : 0);
    
        const groupedByDate: { [day: string]: IWeatherItem[] } =
          _.groupBy(response.data.data, item => item.time.substring(0, 10));
    
        const dates = Object.keys(groupedByDate);
    
        const meanTemperaturesByDate: { date: string, meanTemperature: number }[] =
          dates.map(date => {
            const temperaturesInOneDay = groupedByDate[date];
            return {
              date,
              meanTemperature: _.meanBy(temperaturesInOneDay, item => item.temperature)
            }
          })
    
        return new Result(response.data.data.length, meanTemperaturesByDate, start);
      }
    
      private timeout(milliseconds: number) {
        return new Promise(resolve => {
          setTimeout(resolve, milliseconds);
        });
      }
    

    Коли запускаю один запит, у мене ось таке результати:

    {
    "count": 8784,
    "memoryUsed": "25.26Mb",
    "processingTime": "806ms",
    "pid": 79264,
    "meanTemperaturesByDate": [
    {
    "date": "2019-01-01",
    "meanTemperature": 8.441666666666663
    },
    {
    "date": "2019-01-02",
    "meanTemperature": 5.054166666666666
    },
    

    Тепер я запускаю навантажувальний тест, в якому кожної секунди приходять 100 користувачів і розблять один запит. Користувачі приходять на протязі 10 секунд, тобто у нас буде 1000 запитів. Нагадаю, що в коментарі вище ми будемо очікувати, що запити будуть виконуватися близько 15 хвилин.

    Запускаємо тест, дивимось, що практиці.

    Started phase 0, duration: 10s @ 11:11:42(+0300) 2020-07-28
    ...
    Report @ 11:12:24(+0300) 2020-07-28
    Elapsed time: 43 seconds
      Scenarios launched:  0
      Scenarios completed: 2
      Requests completed:  2
      Mean response/sec: NaN
      Response time (msec):
        min: 39672.2
        max: 40115.8
        median: 39894
        p95: 40115.8
        p99: 40115.8
      Codes:
        200: 2
    
    All virtual users finished
    Summary report @ 11:12:24(+0300) 2020-07-28
      Scenarios launched:  1000
      Scenarios completed: 1000
      Requests completed:  1000
      Mean response/sec: 23.47
      Response time (msec):
        min: 803.4
        max: 40115.8
        median: 9270.9
        p95: 19747.3
        p99: 26210.4
      Scenario counts:
        0: 1000 (100%)
      Codes:
        200: 999
        500: 1
    

    44 секунди. Не 15 хв, а 44 секунди.
    Я можу погодитись, що якби у версії 7, я б використовував першу весію алгоритму, то це б зайняло на 3 хвилини довше, тобто майже 4.

    Висновок, навіть коли ми підлючаємо мережу, програма під навантаженням для оптимального алгоритму виконується майже в 4 рази скоріше.

    Чому так, а не 15 хвилин, як було припущено у попередньому коментарі. Нода виконує операції Event Loop в одному потоці. Але це не означає, що I/O операції також повинні виконуватися в одному потоці. Нода використовує багатопоточність, але вона схована від розробника.

    На 43 секудні у нас 2 закінчених запити, а вже на 44 всі запити закінченні. Це тому, що решта 988 запитів були в процесі виконання. Вони разом качали майже 200мб JSON.

    (800 + 100 + 2) * 1000 / (1000 * 60) ≈ 15 хвилин.
    Це все в разрахунку для синхронного коду.
    З цифр випливае наступна оптимізація по порядку:
    1) Тримати відкрите підключення, чи пул підключень до сервера
    2) Змінити формат данних, щоб уникнути парсинга великого за об’ємом JSON (наприклад стрімити чанки JSON/CSV)
    3) Оптимизувати алгоритм, якщо це стало bottleneck
    4) Замінити Nodejs на більш «продуктивний» сервер чи змінити подхід до агрегації данних (наприклад використовувати спеціалізовані БД)

    Цікавий висновок. Спочатку показати, що в нас 800 — це найбільший таймаут (сторонній API + мережа), а потім сказати, «4) Замінити Nodejs на більш „продуктивний“ сервер».

    далі йде парсинг JSON.parse > 100 мс (прогнав пару раз на локальной машині с данними)

    Ну я теж поміряв

        const start = new Date();
        const obj = JSON.parse(jsonStr);
        console.log(`${new Date().getTime() - start.getTime()}ms`, jsonStr.length);
    

    11ms 3756752
    10ms 3756752
    13ms 3756752
    10ms 3756752
    11ms 3756752
    12ms 3756752
    13ms 3756752
    10ms 3756752

    Може ви з диску читали файл, або десь з мережі качали?

    Но зі статті випливає, що єдиною оптимізацією є алгорітм.

    Стаття про алгоритми. У статті я розповідаю, як підняти продуктивність алгоритмічно. Стаття не про бази даних, кеші, мережу і так далі. Я не розповідаю про бази, кеші і мережу, а розповідаю про алгоритми, бо про це стаття, то з цього аж ніяк не випливає

    Но зі статті випливає, що єдиною оптимізацією є алгорітм.

    Версія 7 на гітхабі. Хто бажає, можете спробувати у себе самі.

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Спасибі, дуже приємно :)

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Так, в BigData і стрімами було б інакше. Я б робив якось так: 2 singletone масиви (один для суми, інший для кількості) довжиною 366 елементів. Ідемо по стріму, вираховуємо номер дня у році (ну і позицію в масиві), сумуємо там значення. В іншому масиві робимо інкемент. Коли потрібно повертати результати — ділимо один масив на інший. Тут O(n) по часу і O(1) для пам’яті.
    В тому алгоритмі, що у статті остання версія v6
    Групування O(n) + Отримати дат по ключах HashMap O(n) + Обрахунок середньої температури O(n) — по часу і пам’яті

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    На рахунок 1М запитів: MS SQL Server стягне паралельно 30,000 запитів. Redis може стягнути 65 тисяч запитів, що рівне максимальній кількості відкритих TCP з’єднань. І вам треба дуже нехиле залізо, щоб буди близьким до таких цифр. Ну і не будемо забувати про fault tolerance, тобто вам потрібна надлишковість ресурсів, щоб коли щось завалиться, ваші користувачі цього не відчули. Тобто ви праві про кеші, але вони будуть не тільки в вигляді Redis Cluster, але і локальні в пам’яті. Словом — 1М ні разу не просто.
    Остання версія алгоритму опрацьовує запит 2 мс, це дійсно варто додаткового процесу, щоб він підрахував додатково дані десь окремо?
    Давайте уявимо, що у нас є додатковий процес, який підраховує дані для нас. Перша версія алгоритму опрацьовувала 16 запитів в секунди. Нахай ми отримуємо дані про 1000 міст. Тобто, щоб опрацювати всі дані, у нас піде більше 16 * 1000 / 60 / 60 = 4 годин. Якщо дані приходять раз в годину, то нам треба 4 такі процеси, щоб хоча б встигав в проміжок 1 година, але користувачі будуть чекати годину, щоб отримати актуальні дані.

    Підтримав: Dmitry Kapustin
  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Ну, ну, вже підміни понять не достатньо, будете підміняти лінки? :) Оригінально ви скинили ось цю лінку www.google.com/...​&sourceid=chrome&ie=UTF-8.
    У видачі:
    Продуктивність та продуктивність праці: сутність та ... Реферат
    Продуктивність — Вікіпедія
    Продуктивність праці — Вікіпедія
    Продуктивність і ефективність: в чому різниця? — Baker Tilly

    Ви хотіли, щоб я не скіпнув реферат і вікіпедію і ми почали говорити про продуктиність праці?

    Стаття, яку показуєте ви зараз:
    Якість програмного забезпечення — Вікіпедія. Її у видачі не було, оскільки тоді ви гуглили «продуктивність визначення»

    Продуктивність (efficiency) або ефективність

    І знову ж ваші слова

    Є productivity and performance and efficiency.

    Або зараз вікіпедія не права, або ви тоді були не правий.

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Тобто ви вважаєте, що такий спосіб ітерації по масиву це нормально?

    while (source.length > 0) { source.splice(0, 1); }

    Я вважаю, це трохи дивно робити таке у списку. Тим не менше, це може бути валідний код для черги або стеку, або якщо ви читаєте дані зі стріма: поки стрім не закритий, читаємо з нього дані. Це получився досить хороший і наочний приклад того, що часто видаляти або додавати дані в список може мати негативний імпакт на продуктивність.

    Можно замінити на:

    Та можна, але переважна більшість людей, які не працюють з JS, не зловить сходу, що через reduce шукаємо суму. Я б все ж хотів, щоб стаття принесла користь якомога більшому колу читачів.

    Ви намалювали «сферичного коня в вакуумі» для сладной сістемі спростивши її у зручний вам спосіб, тому всі ці запитання й з’явилися.

    Так в цьому ж і суть: коли ви робите тестову площадку, ви ізолюєте її від всіх сторонніх впливів і досліджуєте тільки ті характеристити, які вам цікаві. Якщо я хочу показати, що видалення ементів зі спистку забирає час, то навіщо мені робити запити у базу даних, або включати час парсання JSON? Мій фокус — список.

    Чому на останьому етапі підіймаєте ще один сервіс, коли даже с першим варіантом кода та кешем можно було б збільшити показники відповіді в рази по відношенню з останнім кодом?

    Кеш не допоможе, якщо всі запити будуть різні. Я думав спочатку додати від 100 до 1000 різних JSON для різних міст, але вирішив, що буде очевидно, що раз нова версія працює скоріше з одним однаковим файлом, то вона буде працювати так само і для 1000 різних файлів.

    Підтримав: Yuri Predborski
  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Node.js коли десереалізує JSON, автоматично не приводить стрічку з датою до Date об’єкту. Цьому є логічне пояснення — десереалізація дати займає додатковий час. Конкретно для 8000 елементів у цій статті — це в середньому 4 мілісекунди. В той час, як остання версія алгоритму у цій статті, займає 2.

        data.forEach(item => {
            new Date(item.time)
        });
       // 4 ms
    

    Вам далеко не завжди потрібно працювати з датою. Десеріалізувати її в Date, а потім серіалізувати її у стрічку назад, щоб відправити відповідь в браузер — ну трохи зайве.

    Серіазувати можна не тільки в текст, але і в binary. Тут вже пробем з довгою серіалізацією/десеріалізацією не повинно виникати, але виникають інші.

    Ну і взагалі серіалізація/десеріалізація — часом складна тема. На деяких проектах навіть пишуть кастумні серіалізатори/десеріалізатори, які точно знають розмір даних, та їх позиції, і можуть оптималініше здійснювати операції. А ще часто оптимізують сам JSON, скорочуючи назви полів та констант до одного символа.

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    Ви такого лінка не знайдете. Масив в JS — це об’єкт. Думаю в С масив не можна назвати об’єктом.

  • Опановуємо основи алгоритмів, або Як прискорити код з 15 до 1000 запитів за секунду

    не прошли бы code review,
    будучи низкоквалифицированным специалистом и/или большой спешке и потом не читать

    Дуже суб’єктивні твердження. Дайте об’єктивні метрики, щоб можна було почати діалог.

    Ипользовании сторонней библиотеки, где нативная конструкция занимает столько же места это антипатерн.

    Конкретніше

    В последнем примере у вас лишняя операция (создание массива с ключами

    Затегайте код, напишіть, як має виглядати за вашою версією, покажіть різницю продуктивності. Бо зараз поки суб’єктивна оцінка.

    Зачем нужна оптимизация если основная задача веб-сервера — IO, в реальных системах, первый шаг при создании/оптимизации будет выделение CPU bound операций в отдельный сервис

    Не завжди. Вам потрібні важкі обчислення, щоб мотивувати створення окремого сервісу. Окремий сервіс — це дорожче. Віртуалки не безплатні. Ганяти дані по мережі — це додаткова latency. Сереалізація/десереалізація також не безкоштовні і забирають процесорний час. Якщо у вас обчислення на API займають мілісекунди, то вам буде важко добитися хоч якогось позитивного ефекту, делегувавши обчислення іншому сервісу. Простіше понизити рівень складності обчислення оптимальнішими алгоритмами, або використовувати кеші різного рівня

    Выбор данных очень неудачный, мало того что небольшой по объему, так еще и обновляется раз в час. Это уже ETL процесс, можно написать скрипт на любом языке и в статике хранить результат.

    Невдалий для чого? Для контексту моєї задачі і прикладів, які я описую — в самий раз, адже можна легко помітити різницю в часі виконання між різними версіями алгоритму. «небольшой по объему» — почитайте коментар Roman Pavlyuk про 1000 елементів та кубічну складність.

    Как связаны деревья поиска с данной задачей?

    В однїй з версій алгоритму я роблю пошук по масиву і далі в статті розказую, як можна робити швидкий пошук. BST є частиною цієї розповіді.

    Горизонтальное масштабирование сервера == оптимизация CPU bound алгоритма?

    — ні. Це дуже різні речі. Крім горизонтального, існує ще й верикальне маштабування. А ще, якщо говорити про мікросервіси, існує Z-маштабування. Про маштабування ви можете прочитати на вікіпедії en.wikipedia.org/wiki/Scalability. Ну і ще б я вам дуже порекомендував прочитати Patterns of Enterprise Application Architecture. У цій книзі Фаулер пояснює про властивості розподілених систем, і як іх варто проектувати, щоб не погіршити загальну продуктивність системи.

← Сtrl 123 Ctrl →