Welcome! Log In Create A New Profile

Advanced

Re: повторная отправка POST запросов ?

Maxim Dounin
December 26, 2019 06:58AM
Hello!

On Thu, Dec 26, 2019 at 02:05:51AM +0500, Илья Шипицин wrote:

> чт, 26 дек. 2019 г. в 01:13, Maxim Dounin <mdounin@mdounin.ru>:
>
> > Hello!
> >
> > On Thu, Dec 26, 2019 at 12:32:04AM +0500, Илья Шипицин wrote:
> >
> > > ср, 25 дек. 2019 г. в 23:20, Maxim Dounin <mdounin@mdounin.ru>:
> > >
> > > > Hello!
> > > >
> > > > On Wed, Dec 25, 2019 at 02:58:15PM +0500, Илья Шипицин wrote:
> > > >
> > > > > ср, 25 дек. 2019 г. в 14:38, Sergey Kandaurov <pluknet@nginx.com>:
> > > > >
> > > > > >
> > > > > > > On 24 Dec 2019, at 23:35, Илья Шипицин <chipitsine@gmail.com>
> > wrote:
> > > > > > >
> > > > > > > привет!
> > > > > > >
> > > > > > > допустим, такая ситуация. есть POST запрос, у него есть хедеры и,
> > > > > > собственно, тело запроса. мы отправили хедеры на бекенд, тело не
> > успели
> > > > > > отправить, и бекенд нам сделал TCP RST.
> > > > > > >
> > > > > > > должен ли такой POST повторно отправляться, если не указан
> > > > > > non_idempotent ? (судя по моим экспериментам - не отправляется. но
> > ведь
> > > > > > тело не было отправлено ? значит мы должны попасть под условие, что
> > > > такой
> > > > > > запрос можно отправить повторно ?)
> > > > > >
> > > > > > Как только мы успешно установили соединение и перешли к отправке
> > > > запроса
> > > > > > (не важно, успели начать отправку тела или нет), запрос считается
> > > > > > отправленным,
> > > > > > т.к. в общем случае мы не знаем, был ли он обработан или нет.
> > > > > >
> > > > >
> > > > > я предлагаю такую логику.
> > > > > бекенд умеет отличать полностью полученный запрос от неполного
> > запроса
> > > > > (например, по Content-Length)
> > > > > навряд ли бекенд будет обрабатывать неполностью полученный запрос
> > > > >
> > > > > и считать отправленными только полностью отправленные запросы
> > > >
> > > > Считать-то можно, но у бекенда может быть своё мнение по этому
> > > > вопросу. Каких-либо явных утверждений в RFC 2616 / RFC 7231,
> > > > которые бы говорили о том, что так можно - я в своё время не
> > > > нашёл. И по факту так скорее всего нельзя, так как на тело
> > > > бекенду во многих случаях может быть наплевать.
> > > >
> > >
> > > есть достаточно странный кейс, когда отправляется POST без тела. не
> > > конкретно в наших приложениях, а в принципе.
> > > я по некоторым разбирался, зачем так делают (ну то есть, можно же GET, но
> > > специально сделали POST). ответ меня поразил -
> > > по RFC нельзя кешировать POST. ну и чтобы наверняка без кеша, мы выбрали
> > > POST )) ну а тело ... надо не надо было
> > >
> > > в описанном выше случае, действительно, тело (запроса) не предполагалось.
> > >
> > > если тело предполагается, но не было отправлено, допустим бекенд
> > вменяемый,
> > > что вполне может быть. он запрос не обработал.
> > > можно ретраить.
> > >
> > > каких-то явных противоречий в этом не вижу
> >
> > Явных противоречий тут и нет: скорее всего бекенд смотрит на тело,
> > и в тех немногих случаях, когда мы точно знаем, что оно отправлено
> > не полностью - скорее всего можно ретраить.
> >
>
> > Однако проблем тут две:
> >
> > - "Скорее всего можно" - не значит "точно можно", наступить на
> > ситуацию, когда бекенд на тело не смотрит - на практике вполне
> > можно. И каких-либо явных причин требовать от бекенда, чтобы
> > смотрел - я, как я уже писал выше, не вижу, и если у такого
> > бекенда вдруг что-то пойдёт не так - виноват будет nginx. (Если эти
> > причины вдруг есть - с удовольствием ознакомлюсь с соответствующей
> > цитатой из RFC.)
> >
> > - Условие "когда мы точно знаем" не выполняется приблизительно
> > никогда: в подавляющем большинстве случаев тело вместе с
> > запросом уже сложено в буфер сокета, и что там с ним стало
> > дальше - узнать невозможно. То есть мы про микрооптимизацию
> > оцень небольшого процента запросов.
> >
> >
> ну вот у меня ситуация, когда я знаю, что можно.
> рассказываю.
>
> берем IIS. на нем хостим ASP.NET
> ASP.NET хостится в т.н. AppPool, у этого пула есть режим "пул остановлен"
>
> можно настроить пул на HttpLevel, либо на TcpLevel, в первом случае
> остановленный пул отдает 503, во втором tcp rst.
>
> вы хотели RFC ? оно есть у меня. смотрите, есть такой хидер Expect. смотрим
> RFC, там сказано, что он End-to-End.
> итак, рассмотрим цепочку
>
> Браузер --> nginx --> IIS
>
> браузер посылает Expect: 100-Continue, по RFC nginx должен его доставить до

Какой именно браузер? Из известных мне клиентов - 100-continue
шлёт только curl.

> IIS ? но этого не происходит.
> IIS (и http.sys под капотом) ответил бы Expect, и у nginx была бы инфа, что
> запрос не успел отправиться

Не было бы: запрос _успел_ отправиться. Тело запроса бекенд не
принял - но это вопросы к бекенду, и что он там успел сделать по
этому запросу, перед тем как сломаться - вопрос к бекенду.

> но nginx не отправляет Expect.

И, скорее всего, в ближайшее время не будет. В частности потому,
что никто, кроме curl'а этого не поддерживает. Но это отдельный
разговор, и он имеет очень мало отношения к обсуждаемому вопросу.

> и POST улелает в остановленный пул. если пул настроен на HttpLEvel, то пул
> отдает 503 уже после отправки (были бы Expect-ы, отдал бы до).
>
> ок, меняем режим пула на TcpLevel, пул должен сделать tcp rst. и он его
> сделает. но! нюанс. после отправки хидеров.
> объяснение простое, на порту, на котором слушает IIS, могут быть несколько
> приложений (пулов), чтобы понять, в какой именно пул мы попали, нужно поле
> Host.
>
> но я точно знаю, что tcp rst идет до отправки тела. и nginx это точно знает.

Как я уже говорил, в большинстве случаев nginx ничего не знает -
тело и заголовки он отправляет вместе. И если connect() к бекенду
успешно прошёл - то он просто запишет в буфер сокета запрос
целиком.

То есть так или иначе ни 503, ни закрытие соединения после его
принятия - работать не будут. В большинстве случаев у nginx'а
вообще нет информации о том, отправилось ли тело на бекенд, или
нет, и даже если она есть - нет оснований считать, что запрос, у
которого не отправилось тело, можно отправить куда-то ещё
повторно.

> а разработчики, которые пишут идеальные приложения ... ну я тоже люблю
> фантазировать.

В данном конкретном случае есть совсем простое решение: убирать
бекенды из балансировки перед тем, как их ломать.

--
Maxim Dounin
http://mdounin.ru/
_______________________________________________
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru
Subject Author Posted

повторная отправка POST запросов ?

Илья Шипицин December 24, 2019 03:36PM

Re: повторная отправка POST запросов ?

Sergey Kandaurov December 25, 2019 04:40AM

Re: повторная отправка POST запросов ?

Илья Шипицин December 25, 2019 05:00AM

Re: повторная отправка POST запросов ?

Maxim Dounin December 25, 2019 01:22PM

Re: повторная отправка POST запросов ?

Илья Шипицин December 25, 2019 02:34PM

Re: повторная отправка POST запросов ?

Maxim Dounin December 25, 2019 03:14PM

Re: повторная отправка POST запросов ?

Илья Шипицин December 25, 2019 04:08PM

Re: повторная отправка POST запросов ?

Maxim Dounin December 26, 2019 06:58AM



Sorry, only registered users may post in this forum.

Click here to login

Online Users

Guests: 300
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready