http 응답을 보낸 후 php 처리를 계속합니다.
내 스크립트는 서버에서 호출됩니다.서버로부터의 수신ID_OF_MESSAGE
그리고.TEXT_OF_MESSAGE
.
스크립트에서 수신 텍스트를 처리하고 매개 변수를 사용하여 응답을 생성합니다.ANSWER_TO_ID
그리고.RESPONSE_MESSAGE
.
문제는 인코밍에 대한 응답을 보내고 있다는 것입니다."ID_OF_MESSAGE"
http 응답 200 을 수신한 후, 메시지를 송신하는 서버는, 그 메세지가 나에게 전달된 것으로 설정됩니다(즉, 그 ID 에 대한 응답을 송신할 수 있습니다).
해결책 중 하나는 메시지를 데이터베이스에 저장하고 1분마다 실행되는 cron을 만드는 것입니다만, 즉시 응답 메시지를 생성해야 합니다.
서버 http response 200으로 전송하고 php 스크립트를 계속 실행하는 방법이 있습니까?
정말 감사합니다
네, 할 수 있습니다.
ignore_user_abort(true);//not required
set_time_limit(0);
ob_start();
// do initial processing here
echo $response; // send the response
header('Connection: close');
header('Content-Length: '.ob_get_length());
ob_end_flush();
@ob_flush();
flush();
fastcgi_finish_request();//required for PHP-FPM (PHP > 5.3.3)
// now the request is sent to the browser, but the script is still running
// so, you can continue...
die(); //a must especially if set_time_limit=0 is used and the task ends
여기 있는 많은 답변들을 봤는데ignore_user_abort(true);
이 코드는 필요 없습니다.이 조작은, 유저가 중단했을 경우(브라우저를 닫거나 에스케이프를 눌러 요구를 정지하는 것에 의해서) 응답이 송신되기 전에, 스크립트의 실행을 계속하는 것입니다.하지만 그건 네가 원하는 게 아니야.응답을 보낸 후 실행을 계속하도록 요청하는 중입니다.필요한 것은 다음과 같습니다.
// Buffer all upcoming output...
ob_start();
// Send your response.
echo "Here be response";
// Get the size of the output.
$size = ob_get_length();
// Disable compression (in case content length is compressed).
header("Content-Encoding: none");
// Set the content length of the response.
header("Content-Length: {$size}");
// Close the connection.
header("Connection: close");
// Flush all output.
ob_end_flush();
@ob_flush();
flush();
// Close current session (if it exists).
if(session_id()) session_write_close();
// Start your background work here.
...
백그라운드 작업이 PHP의 기본 스크립트 실행 시간 제한보다 더 오래 걸릴 것으로 우려되는 경우, 고정하십시오.set_time_limit(0);
맨 위에.
Fast CGI 처리 또는 PHP-FPM을 사용하는 경우 다음을 수행할 수 있습니다.
session_write_close(); //close the session
ignore_user_abort(true); //Prevent echo, print, and flush from killing the script
fastcgi_finish_request(); //this returns 200 to the user, and processing continues
// do desired processing ...
$expensiveCalulation = 1+1;
error_log($expensiveCalculation);
출처 : https://www.php.net/manual/en/function.fastcgi-finish-request.php
PHP 문제 #68722: https://bugs.php.net/bug.php?id=68772
저는 이 문제에 대해 몇 시간을 할애했고 Apache와 Nginx에서 작동하는 다음 기능을 가지고 있습니다.
/**
* respondOK.
*/
protected function respondOK()
{
// check if fastcgi_finish_request is callable
if (is_callable('fastcgi_finish_request')) {
/*
* This works in Nginx but the next approach not
*/
session_write_close();
fastcgi_finish_request();
return;
}
ignore_user_abort(true);
ob_start();
$serverProtocole = filter_input(INPUT_SERVER, 'SERVER_PROTOCOL', FILTER_SANITIZE_STRING);
header($serverProtocole.' 200 OK');
header('Content-Encoding: none');
header('Content-Length: '.ob_get_length());
header('Connection: close');
ob_end_flush();
ob_flush();
flush();
}
긴 처리를 하기 전에 이 함수를 호출할 수 있습니다.
답변을 @vcampitelli로 약간 수정.필요없을 것 같아close
header를 클릭합니다.Chrome에서 중복된 닫기 헤더를 보고 있었습니다.
<?php
ignore_user_abort(true);
ob_start();
echo '{}';
header($_SERVER["SERVER_PROTOCOL"] . " 202 Accepted");
header("Status: 202 Accepted");
header("Content-Type: application/json");
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();
sleep(10);
2012년 4월에 Rasmus Lerdorf에게 다음과 같은 질문을 했습니다.
- https://www.zulius.com/how-to/close-browser-connection-continue-execution/
- 접속을 조기에 종료하다
- http://php.net/manual/en/features.connection-handling.php
(stdout?에서) 더 이상의 출력이 생성되지 않음을 플랫폼에 알리기 위해 새로운 PHP 내장 함수의 개발을 제안했습니다(이 함수는 접속을 닫을 수 있습니다).라스무스 레르도프는 다음과 같이 대답했다.
기어맨을 봐프런트 엔드 웹 서버가 이런 백엔드 처리를 하는 것은 정말 원하지 않습니다.
나는 그의 요점을 알 수 있고, 몇몇 어플리케이션/로드 시나리오에 대한 그의 의견을 지지할 수 있다.그러나 일부 다른 시나리오에서는 vcampitelli 등의 솔루션이 좋다.
여기에는 php 함수 register_shutdown_function을 사용합니다.
void register_shutdown_function ( callable $callback [, mixed $parameter [, mixed $... ]] )
http://php.net/manual/en/function.register-shutdown-function.php
편집: 위는 동작하지 않습니다.뭔가 오래된 서류에 현혹된 것 같아요.register_shutdown_function의 동작은 PHP 4.1 링크 이후 변경되었습니다.
pthread 를 인스톨 할 수 없고, 이전의 솔루션도 마찬가지입니다.기능하는 솔루션은 다음과 같습니다(참조 자료:https://stackoverflow.com/a/14469376/1315873):
<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(); // optional
ob_start();
echo ('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
session_write_close(); // Added a line suggested in the comment
// Do processing here
sleep(30);
echo('Text user will never see');
?>
저는 압축하여 응답을 보내고 다른 php 코드를 실행할 수 있는 것을 가지고 있습니다.
function sendResponse($response){
$contentencoding = 'none';
if(ob_get_contents()){
ob_end_clean();
if(ob_get_contents()){
ob_clean();
}
}
header('Connection: close');
header("cache-control: must-revalidate");
header('Vary: Accept-Encoding');
header('content-type: application/json; charset=utf-8');
ob_start();
if(phpversion()>='4.0.4pl1' && extension_loaded('zlib') && GZIP_ENABLED==1 && !empty($_SERVER["HTTP_ACCEPT_ENCODING"]) && (strpos($_SERVER["HTTP_ACCEPT_ENCODING"], 'gzip') !== false) && (strstr($GLOBALS['useragent'],'compatible') || strstr($GLOBALS['useragent'],'Gecko'))){
$contentencoding = 'gzip';
ob_start('ob_gzhandler');
}
header('Content-Encoding: '.$contentencoding);
if (!empty($_GET['callback'])){
echo $_GET['callback'].'('.$response.')';
} else {
echo $response;
}
if($contentencoding == 'gzip') {
if(ob_get_contents()){
ob_end_flush(); // Flush the output from ob_gzhandler
}
}
header('Content-Length: '.ob_get_length());
// flush all output
if (ob_get_contents()){
ob_end_flush(); // Flush the outer ob_start()
if(ob_get_contents()){
ob_flush();
}
flush();
}
if (session_id()) session_write_close();
}
php file_get_module을 사용하는 경우 연결 닫기는 충분하지 않습니다.php는 여전히 서버에 의한 마녀의 전송을 기다립니다.
솔루션은 'Content-Length:'를 읽는 것입니다.
다음은 샘플입니다.
대답.php:
<?php
ignore_user_abort(true);
set_time_limit(500);
ob_start();
echo 'ok'."\n";
header('Connection: close');
header('Content-Length: '.ob_get_length());
ob_end_flush();
ob_flush();
flush();
sleep(30);
대기 중 fget을 읽지 않은 경우 클로즈라인에 대한 응답으로 "\n"을 적어둡니다.
read.devel:
<?php
$vars = array(
'hello' => 'world'
);
$content = http_build_query($vars);
fwrite($fp, "POST /response.php HTTP/1.1\r\n");
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fwrite($fp, "Content-Length: " . strlen($content) . "\r\n");
fwrite($fp, "Connection: close\r\n");
fwrite($fp, "\r\n");
fwrite($fp, $content);
$iSize = null;
$bHeaderEnd = false;
$sResponse = '';
do {
$sTmp = fgets($fp, 1024);
$iPos = strpos($sTmp, 'Content-Length: ');
if ($iPos !== false) {
$iSize = (int) substr($sTmp, strlen('Content-Length: '));
}
if ($bHeaderEnd) {
$sResponse.= $sTmp;
}
if (strlen(trim($sTmp)) == 0) {
$bHeaderEnd = true;
}
} while (!feof($fp) && (is_null($iSize) || !is_null($iSize) && strlen($sResponse) < $iSize));
$result = trim($sResponse);
보시다시피 이 스크립트는 콘텐츠 길이에 도달할 때까지 기다립니다.
도움이 되기를 바라다
응답 헤더를 조작하지 않는 경우는, 다른 어프로치가 있어 검토해 주세요.다른 프로세스에서 스레드를 시작하면 호출된 함수는 응답을 기다리지 않고 최종 http 코드와 함께 브라우저로 돌아갑니다.pthread를 설정해야 합니다.
class continue_processing_thread extends Thread
{
public function __construct($param1)
{
$this->param1 = $param1
}
public function run()
{
//Do your long running process here
}
}
//This is your function called via an HTTP GET/POST etc
function rest_endpoint()
{
//do whatever stuff needed by the response.
//Create and start your thread.
//rest_endpoint wont wait for this to complete.
$continue_processing = new continue_processing_thread($some_value);
$continue_processing->start();
echo json_encode($response)
}
$continue_processing->start()를 실행하면 PHP는 이 스레드의 반환 결과를 기다리지 않으므로 rest_endpoint가 고려됩니다.끝났다.
pthreads에 도움이 되는 링크
행운을 빌어요.
른른른 른!!! !!! !!!!!!!!!!!!!!
TL;DR:
echo str_repeat(' ', 1024);
제 사용 예에서는 API Call을 "Accepted"로 표시하고 클라이언트가 처리를 완료할 때까지 기다리지 않도록 하고 싶습니다.
사실 맞는 느낌입니다.클라이언트는 "Connection: close" 헤더를 수신하면 응답을 기다리는 것을 중지해야 하지만, 적어도 MY php는 아직 이러한 헤더를 전송하지 않습니다.(Browser+를 통해 2개의 다른 PHP-서버로 테스트 완료)불면증 클라이언트 각각)
적어도 특별한 바이트 수가 아직 에코되지 않은 경우 flush()가 첫 번째 콘텐츠를 전송하지 않는 특별한 동작이 있습니다(내 경우 1024바이트).(ph 파일에 선두 또는 후행 공백이 있는 경우, 실제로는 echo 스테이트먼트와 같이 처리되어 나중에 header() 스테이트먼트가 활성화되지 않도록 하기 위한 핫픽스를 사용합니다).
이 문제를 해결하려면 선행 공백 문자를 1024개 보낼 수 있으며, 이는 JSON/XML/HTML 인터프리터에 의해 무시되어야 합니다.
전체 코드는 다음과 같습니다.
ob_start();
echo str_repeat(' ', 1024);
echo $response; // send the response
header('Connection: close');
header('Content-Length: '.ob_get_length());
ob_end_flush();
@ob_flush();
flush();
(여기 내 인수에 대한 백업이 있습니다.올바른 소스 rn을 찾을 수 없습니다.각 '에코' 호출 후에 출력을 플러시하려면 어떻게 해야 합니다.
답변과 더불어 답변으로 JSON 문자열을 반환했습니다.알 수 없는 이유로 응답이 잘리고 있는 것을 발견했습니다.이 문제를 해결하려면 공간을 추가해야 합니다.
echo $json_response;
//the fix
echo str_repeat(' ', 10);
언급URL : https://stackoverflow.com/questions/15273570/continue-processing-php-after-sending-http-response
'programing' 카테고리의 다른 글
PHP에서 컨스트럭터를 오버로드할 수 없는 이유는 무엇입니까? (0) | 2022.09.25 |
---|---|
Cake용으로 작성된 기존 MySQL 데이터베이스에서 ER 다이어그램 생성PHP (0) | 2022.09.25 |
vuex 및 Vue-native-websocket 플러그인에서 WebSockets 데이터 수신 (0) | 2022.09.24 |
JUnit 테스트를 통해 SLF4J(로그백 포함) 로깅을 대행 수신하려면 어떻게 해야 합니까? (0) | 2022.09.24 |
'shell='의 실제 의미하위 프로세스에서 참' (0) | 2022.09.24 |