Поза межами лімітів: розширення доступу до Codex та Sora
Автор: Джона Коен, технічний персонал
За останній рік як Codex, так і Sora набули швидкого поширення, і їх використання швидко перевищило наші початкові очікування. Ми спостерігаємо стійку закономірність: користувачі з головою поринають у роботу з сервісом, знаходять у ньому собі реальну цінність, і потім зіштовхуються з обмеженнями кількості запитів.
Ліміти швидкості можуть допомогти вирівняти попит та забезпечити для всіх рівні умови доступу, але ми чудово розуміємо, як відчувається різка поява обмежень, щойно ти почав отримувати корисність від сервісу. Ми хотіли знайти спосіб, щоб користувачі могли продовжувати роботу, захищаючи продуктивність системи та довіру користувачів до нашого підходу.
Для вирішення цього завдання ми створили механізм доступу в режимі реального часу, який враховує використання. Один із рівнів цього механізму — можливість купівлі кредитів. Коли користувачі перевищують свої ліміти запитів, кредити дозволяють продовжувати використовувати наші продукти, витрачаючи свій кредитний баланс.
В основі лежить складна система, яка поєднує ліміти, відстеження використання у реальному часі та кредитні баланси в єдину модель доступу. У цьому пості пояснюється, чому для масштабування Codex і Sora знадобилося переосмислення контролю доступу, як коректна система в реальному часі поєднує обмеження швидкості і кредити на запит, і як ця основа тепер відкриває додатковий доступ до обох продуктів.
Якщо поглянути ширше, традиційні моделі доступу зазвичай змушують робити вибір:
- Обмеження швидкості можуть бути корисними спочатку, але в результаті залишають у користувачів негативне враження від чергового «повертайтеся пізніше»
- Тарифікація на основі використання — досить гнучка система, проте тут користувачі змушені вносити плату з першого токена, що на ранньому етапі знайомства з продуктом аж ніяк не ідеально.
У випадку з Codex та Sora жоден із цих варіантів не був достатнім сам по собі. Якби ми просто підвищили ліміти швидкості, ми втратили б важливі механізми вирівнювання попиту та забезпечення рівних умов, і вичерпали б можливості, необхідні для обслуговування всіх користувачів. А якби ми повністю покладалися на асинхронне виставлення рахунків за використання, ми зіткнулися б із затримками, перевитратами та проблемами з звіркою, що виникають для користувачів у найбільш невідповідний момент.
Отже, нам потрібна була єдина гібридна система, що поєднує обмеження в реальному часі з доступом за принципом «оплата в міру використання»:
Ця система мала:
- Застосовувати обмеження швидкості до досягнення лімітів
- Дозволяти плавно переходити до використання кредитів у рамках одного запиту
- Приймати рішення про перехід у режимі реального часу
- Забезпечувати граничну точність та можливість аудиту при відстеженні витрати кредитів
Одним із ключових концептуальних зрушень з нашого боку було моделювання доступу у вигляді каскаду рішень. Замість питання «чи дозволено?» ми запитуємо «скільки дозволено, і звідки?» При підрахунку використання система виконує таку послідовність дій:
Ця модель відображає, як користувачі дійсно сприймають продукт. Ліміти, безкоштовні рівні, кредити, промоакції та корпоративні права — лише шари в тому самому стеку прийняття рішень. Із погляду користувачів, вони не «перемикаються між системами» — вони просто продовжують користуватися Codex і Sora. Ось чому кредити здаються невидимими: вони — просто ще один елемент каскаду.
На певному етапі ми аналізували ефективність сторонніх платформ для білінгу, обліку використання та управління витрачанням кредитів. Хоча вони добре підходили для виставлення рахунків та звітності, виявилося, що вони не відповідають двом важливим вимогам:
Коли користувач досягає ліміту і має доступні кредити, система повинна знати про це негайно. Підрахунок за принципом можливості або із затримкою може мати негативні результати у вигляді несподіваних блокувань, неузгоджених балансів та неправильних списань. Для таких інтерактивних продуктів, як Codex та Sora, це дуже помітно, і дуже дратує.
Нам також потрібно було забезпечити прозорість щодо кожного результату:
- Чому той чи інший запит було дозволено або заблоковано
- Скільки даних було використано
- Які обмеження чи баланс були застосовані
Цю можливість слід було тісно інтегрувати в наш каскад прийняття рішень, а не вирішувати ізольовано на окремій платформі білінгу, яка бачила лише частину того, що відбувається. Щоб користувачі могли отримувати доступ до наших продуктів без шкоди довірі, нам потрібен був повний контроль над коректністю, своєчасністю та спостережуваністю. Це спонукало нас до пошуку рішення в рамках компанії.
Ми створили розподілену систему обліку використання та балансу, спеціально розроблену для синхронного ухвалення рішень про доступ.
На високому рівні система:
- Відстежує використання кожного користувача та кожної функції
- Підтримує вікна обмеження частоти запитів
- Підтримує баланси кредитів у реальному часі
- Ідемпотентно дебетує баланси через потоковий асинхронний процесор
Кожен запит проходить через єдиний шлях оцінки, який у реальному часі генерує рішення про допустимий обсяг використання, синхронно споживаючи ліміти швидкості та, за необхідності, перевіряючи наявність достатньої кількості кредитів; потім він повертає один остаточний результат, одночасно асинхронно виконуючи будь-які списання кредитів. Це гарантує однакову поведінку в усіх продуктах та усуває дублювання логіки між командами.
Один із ключових принципів проєктування цієї системи полягає в тому, що ми маємо змогу довести, що наше виставлення рахунків коректне. Це відображає витоки нашої кредитної підтримки, яка почалася з корпоративних клієнтів. На наведеній вище системній діаграмі представлено три окремі, але пов'язані набори даних:
- Події використання продукту: Що саме зробив користувач
- Події монетизації: За що ми стягуємо плату з користувача
- Оновлення балансу: Наскільки ми змінили кредитний баланс користувача і чому
Ці набори даних — не випадковий побічний продукт; вони справді керують системою, і кожен набір даних запускає наступний. Розподіл подій використання, пов'язаних нарахувань та списань дозволяє нам незалежно проводити аудит, відтворювати та звіряти кожен рівень. Це свідомий компроміс, при якому ми віддаємо пріоритет доведеній коректності ціною невеликої затримки в оновленні балансу кредитів. Як ми цього досягли:
- Події використання продукту публікуються для всієї активності користувача, незалежно від того, чи призводить вона до витрачання кредитів чи ні. Це підтримує ведення журналу аудиту дій користувачів і дозволяє нам пояснити, чому ми стягували чи не стягували кредити у тому чи іншому випадку.
- Кожна подія має стабільний ключ ідемпотентності, тому повторні спроби, відтворення або перезапуск ніколи не призводять до подвійного списання коштів. Це також дозволяє нам виконувати періодичну звірку для перевірки нашої роботи в автономному режимі.
- Замість синхронних оновлень балансу ми виконуємо асинхронні (але майже в реальному часі) звірки для ведення журналу аудиту. Ми допускаємо невелику затримку під час оновлення балансу користувача, щоб довести, що система працює, і запевнити наших користувачів, що ми не виставляємо їм неправильні рахунки. Коли ця коротка затримка призводить до перевищення кредитного балансу користувача, ми автоматично повертаємо кошти; ми ставимо в пріоритет доведену коректність і довіру користувачів, а не суворе дотримання.
- Ми зменшуємо кредитний баланс та додаємо запис про оновлення балансу в рамках однієї атомарної транзакції бази даних. Оновлення балансу серіалізуються для кожного облікового запису, тому паралельні запити ніколи не зможуть конкурувати за використання тих самих кредитів. Запис про оновлення балансу містить як суму дебету, так і прив'язку до події монетизації, що ініціювало оновлення; обернувши це на одну транзакцію бази даних, ми гарантуємо наявність аудиторського сліду кожної коригування кредитного балансу.
Вся ця ретельність спрямована на одну мету: зробити доступ простим та безпечним. Коли люди займаються розробкою чи пишуть код, вони не повинні гадати, чи пройде запит, чи не буде з них списано зайвого, і чи точний їхній баланс. Забезпечуючи доведену коректність використання, виставлення рахунків і балансів, ми надаємо користувачам систему, яка не відволікає їх від роботи. Це те, що дозволяє нам замінити жорсткі зупинки безперервним доступом, і це робить кредити придатними для використання в процесі реальної роботи, а не тільки в рахунку.
Основний принцип нашого підходу — захист користувацького імпульсу. Кожне архітектурне рішення пов'язане з результатом, помітним для користувача: оновлення балансу в реальному часі запобігає непотрібним перериванням, атомарне споживання запобігає подвійному списанню, а єдина логіка доступу забезпечує передбачувану поведінку. У результаті люди можуть працювати довше і масштабніше, і просувати свої проєкти далі, не стикаючись із жорсткими обмеженнями чи передчасними змінами планів.
Система повинна допомагати користувачам у роботі, а не заважати. Дії з лімітами та кредитами мають відбуватися на задньому плані, не відволікаючи.
Створення цього досвіду вимагало переосмислення принципів доступу, використання та виставлення рахунків як єдиної системи та створення інфраструктури, що розглядає коректність як першокласну функцію продукту. Та ж основа з часом може поширитися на більшу кількість продуктів; Codex і Sora — лише початок.


