Um chamador pode abortar uma execução de código invocado por solicitação HTTP?

8

Um terceiro que fará solicitações HTTP para a API que estou criando exige que a API responda em menos de um segundo. Minha pergunta é: eles têm uma maneira (literalmente, de qualquer maneira, dentro dos limites dos protocolos http e / ou tcp / ip) de interromper a execução do meu código se demorar mais de um segundo?

cortes
fonte
1
Eles podem definir o tempo limite do HttpClient diretamente, mas isso não anula o código em execução no servidor.
Jon Raynor
15
Sim. Geolocalização IP e um míssil de cruzeiro. Se não é isso que você tinha em mente, você terá que ser muito mais preciso com o seu "literalmente de qualquer maneira".
Jörg W Mittag
Pode haver dezenas de razões que podem "convencer" o usuário de que o processo está demorando mais de 1 segundo. Por exemplo, latência. Você sabe, alguém no escritório baixando conteúdo suspeito ... Quando o usuário enviar a solicitação de cancelamento, o processo poderá ter sido concluído com êxito. Um segundo é pouco tempo (eu acho) para um humano.
LAIV
@jmoreno seus "limites" incluem me adicionando um botão de cancelamento para o usuário clicar? Ou você está procurando algo mais baixo na pilha osi do que na camada de aplicação?
Candied_orange 22/09
2
Surpreendeu que isso fosse realmente VTC. A resposta é certa. Nada impede que você registre solicitações de alguma forma e inclua um terminal ou método de API que as cancele - por meio do gerenciamento de processos nativo ou por solicitações "canceláveis" que verificam periodicamente se foram instruídas a parar ...
svidgen

Respostas:

10

HTTP não funciona assim. O cliente envia uma solicitação e, em seguida, o servidor envia uma resposta de volta. Nenhuma outra comunicação ocorre. Bem, o servidor pode enviar respostas informativas 1xx antes da resposta principal. Mas não há como o cliente enviar atualizações sobre uma solicitação enviada.

(A situação é muito diferente para o HTTP / 2, que pode multiplexar várias solicitações pela mesma conexão. Um cliente pode CANCELAR um fluxo para indicar que não é mais necessário depois de receber um PUSH_PROMISE do servidor. Ignorarei o HTTP / 2 para o restante desta resposta.)

Além disso, as redes não funcionam assim. Em particular, veja o segundo falácia da computação distribuída : “latência é zero”. Não é. Nesse segundo tempo limite, 400ms podem ter sido gastos no estabelecimento da conexão e no envio da solicitação e 600ms na resposta, porque um dos pacotes foi descartado e você teve que reenviar tudo e seu cliente está na Austrália. Além do problema de o servidor não ter tempo suficiente, ele nem sabe quanto tempo tem porque a latência de resposta não pode ser conhecida antecipadamente.

Portanto, considerando que a implementação literal desses tempos limites é impossível, que tipo de solução pode ser boa o suficiente?

Se a resposta não tiver valor após o tempo limite, o cliente pode simplesmente fechar a conexão. Isso fará com que sua resposta seja ignorada, mas não impedirá a resposta.

Fechar a conexão TCP pela qual a solicitação HTTP é enviada notifica o servidor. Mas essa notificação chega apenas com latência, portanto pode ser tarde demais. Além disso, sua estrutura da web pode não estar fazendo nada quando o soquete do cliente está fechado. Nesse caso, você receberá o erro "redefinição de conexão por pares" quando tentar gravar no soquete fechado.

Se você não deseja gastar mais de um segundo no processamento da resposta, a implementação desse tempo limite é de sua inteira responsabilidade e não tem nada a ver com rede ou HTTP.

Você pode solicitar ao cliente que forneça um tempo limite ao servidor, para que o servidor possa abortar se não cumprir o prazo. Isso pode ser especificado como um cabeçalho personalizado ou como um parâmetro de consulta no URL. Esse prazo deve ser um ponto absoluto no tempo e não uma duração, para que os atrasos na transmissão também consumam o tempo disponível. Mas a precisão de um segundo é difícil: o servidor e o cliente precisam ser sincronizados com a hora correta e precisam usar um relógio adequado. Dependendo da configuração, cada fonte de tempo pode ser desativada em 100ms, mesmo quando configurada corretamente. Isso já consome uma parte significativa do seu orçamento de tempo.

amon
fonte
É claro que você pode enviar um tempo limite como tempo relativo - apenas significa que o servidor não pode parar de processar x segundos após o envio da solicitação, mas apenas x segundos após o servidor a receber. Pode ser melhor se você não puder garantir que o relógio e o servidor sejam iguais. Se eles estiverem com dois minutos de intervalo, todas as solicitações com um tempo limite de um minuto (em tempo absoluto) poderão ser rejeitadas.
gnasher729
1

Suponho que eles poderiam fechar a conexão, mas não sei se isso realmente causaria o cancelamento do seu código - isso dependeria de como o código foi escrito.

Eles também podem enviar outra mensagem que pode significar "você está demorando muito, então não se preocupe", mas nesse caso, você provavelmente já estará preparado para lidar com uma mensagem CANCEL_REQUEST explícita.

FrustratedWithFormsDesigner
fonte
Acho que gravar em uma porta fechada sinalizará, mas é claro que você pode ignorar ou manipular esse sinal (só sei disso do lado do cliente, onde esse problema causaria uma falha no cliente se você não o tratasse). Além disso, o cliente não pode forçar o servidor a fazer nada. É claro que o servidor pode interromper seu trabalho voluntariamente se a porta estiver fechada, ou cancelar o trabalho se não for realizado dentro do tempo limite, ou cancelar o trabalho se o cliente enviar uma mensagem para cancelar a solicitação.
gnasher729