Heroku скорочує відповіді HTTP?


78

Я запускаю додаток Flask / Gunicorn Python на динозавірі Heroku Cedar. Додаток повертається JSON responsesдо своїх клієнтів (це API server, насправді).

Час від часу клієнти отримують 0-байтові відповіді. Однак я повертаю їх не я. Ось фрагмент журналу мого додатка:

14 березня 13:13:31 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 додаток [web.1] [2013-03-14 13:13:31 UTC] 10.104.41.136 apisrv - api_get_credits_balance (): session_token = [MASKED ]

Перший рядок вище - це я починаю обробляти запит.

14 березня 13:13:31 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 app [web.1] [2013-03-14 13:13:31 UTC] 10.104.41.136 apisrv 1252148511 api_get_credits_balance (): повернення [{' credits_balance ': 0}]

Другий рядок - це я повертаю значення (у Flask - це об’єкт Flask "Response").

14 березня 13:13:31 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 app [web.1] "10.104.41.136 - - [14 / Mar / 2013: 13: 13: 31]" POST / get_credits_balance? Session_token = MASKED HTTP / 1.1 "200 22" - "" Appcelerator Titanium / 3.0.0.GA (iPhone / 6.1.2; iPhone OS; en_US;) "

Третій рядок - Gnicorn, де ви можете бачити, як Gunicorn отримав статус 200 і 22 байта HTTP-тіла (" 200 22").

Однак клієнт отримав 0 байт. Ось журнал маршрутизатора Heroku:

14 березня 13:13:30 d.0b1adf0a-0597-4f5c-8901-dfe7cda9bce0 heroku [маршрутизатор] at = info method = POST path = / get_credits_balance? Session_token = MASKED host = matchspot-apisrv.herokuapp.com fwd = "66.87. 116.128 "dyno = web.1 черга = 0 очікування = 0ms підключення = 1ms послуга = 19ms стан = 200 байт = 0

Чому Gunicorn повертає 22 байти, а Heroku бачить 0 і справді передає клієнту 0 байт? Це помилка Heroku?


1
Ви помітили, що мітка часу героку стоїть перед міткою часу вашого процесу? Ви використовуєте гевент? Щось не так із синхронізацією, я думаю.
Тігра

2
І все-таки мітка часу зазначає 1 секунду різниці, а не 1 1 мс ... Я не працював з героку, тому це лише пропозиції. 1 мс і 1999 мс можуть дати вам 1 секунду різниці в позначці часу. Сервіс 19ms також занадто низький, щоб бути правдою щодо хмарного сервісу. Отже, моя думка полягає в тому, що, ймовірно, є якийсь тайм-аут, а час очікування замість помилки героку подає порожню сторінку. Ця пропозиція давно розстріляна, але, можливо, вам слід наслідувати довгий запит і подивитися, що станеться
Тігра

9
Наскільки корисним був Героку, коли ви з цим зв’язалися (з цікавості)?
orokusaki,

6
Поки що не дуже багато. Я підійшов до них 10 днів тому, і мені сказали, що хлопці з Python спочатку подивляться на це, і якщо вони не зможуть мені допомогти, тоді хлопці з маршруту поглянуть. Через 5 днів мені повідомили, що хлопці з Python передали це хлопцям-маршрутизаторам, і сьогодні я отримав електронне повідомлення від "маршрутизатора", який сказав, що він не може відтворити, і попросив отримати додаткову інформацію. Так так, вони йдуть через правильний процес, але це триває вічно.
Nitzan Shaked

1
Невелике оновлення: це ще не вирішено. Я переписувався туди-сюди з підтримкою Heroku, і найкраще, що я можу зібрати зараз, - це те, що вони не відхилили мене "це на твоєму кінці", і намагаються написати інструмент, який tcpdump фіксує трафік додатків , для "таких випадків налагодження".
Nitzan Shaked

Відповіді:


1

Я знаю, що тут мене можуть вважати трохи від стіни, але є інший варіант.

Ми знаємо, що час від часу під час транзиту трапляється помилка. Ми знаємо, що зараз ми не можемо зробити багато, щоб зупинити проблему. Якщо ви надаєте лише API, припиніть читати, однак, якщо ви також пишете клієнт, продовжуйте.

Помилка - відомий випадок та відома причина. Результат порожнього значення повернення означає, що щось пішло не так. Однак значення доступне і було отримано, розраховано, що завгодно ... Моїм інстинктом розробника було б сприймати порожній результат як помилку HTTP та вимагати повторної передачі даних. Потім ви можете відстежувати повторно надіслані запити та бачити, як часто це відбувається.

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

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

Це також призведе до обробки будь-якої кількості інших помилкових мережевих помилок і зробить додаток набагато надійнішим навіть в умовах проблем із підключенням.

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


Насправді це не поганий коментар (хоча, мабуть, він повинен бути в коментарі, а не у відповіді), і не думайте, що я про це не думав ... Проблема в тому, що клієнт не може подати запит знову, оскільки запит може мати побічні ефекти на стороні сервера (наприклад, переказ грошей вдруге, скажімо). Рішення для цього полягає в тому, щоб клієнт видав request_id's, а сервер містив список "які request_id були подані за останні 60 секунд". Коли клієнт отримує відповідь 200 із 0-байтовим тілом, він повторно видає запит з тим самим ідентифікатором, а сервер не виконує повторно (не продовжує)
Nitzan Shaked

(продовжувати) все це знову. Однак це настільки негарно, що я вирішив не реалізовувати.
Nitzan Shaked

Я ледве новачок у кешуванні, але мені здається: надішліть випадковий рядок як частину запиту та кешуйте результат. Коли ви повторно надсилаєте запит з тим самим випадковим рядком, ви, природно, отримуєте кешований результат (той же вміст, те саме джерело ...), але коли ви надсилаєте законний новий запит, у вас є новий випадковий рядок і, отже, немає кешованого результат.
Нарфанатор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.