>  기사  >  백엔드 개발  >  PHP에는 왜 타이밍 기능이 없나요?

PHP에는 왜 타이밍 기능이 없나요?

青灯夜游
青灯夜游원래의
2023-02-24 09:59:122899검색

PHP가 웹 개발에서 타이머를 사용할 수 없는 근본적인 이유는 제어 가능한 상주 메모리 운영 환경이 부족하기 때문입니다. 첫 번째는 상주 메모리이고 두 번째는 제어 가능합니다. CGI 모드에서는 프로세스가 스크립트 실행 후 바로 종료되며 지정된 시간에 작업이 실행될 것으로 예상할 수 없습니다. PHP-FPM 모드에서는 프로세스가 메모리에 상주하지만 제어할 수 없습니다.

PHP에는 왜 타이밍 기능이 없나요?

이 튜토리얼의 운영 환경: Windows 7 시스템, PHP 8 버전, DELL G3 컴퓨터

PHP에는 왜 타이밍 기능이 없나요?

두 가지 일반적인 타이머가 있습니다: 하나는 주기적 타이밍 실행입니다. , 예를 들어 매일 이른 아침 3시에 보고서가 발행되고, 다른 보고서는 지정된 시간(1회) 후에 실행됩니다. 예를 들어 일일 로그인 보상은 회원이 시스템에 로그인한 후 5분 후에 발행됩니다. JavaScript의 setInterval, setTimeout 함수에 해당합니다(엄밀히 말하면 setInterval은 주기적으로 실행되며 지정된 시점의 실행은 자체적으로 처리해야 함).

웹 개발을 하는 PHP 프로그래머는 JavaScript의 두 가지 타이머 기능에 익숙해야 합니다. PHP 수준으로 돌아가면 약간 어리둥절합니다.

PHP에는 절전 기능이 있지만 (내장) 타이머는 없습니다. 기능을 사용할 수 있습니다. 슬립 기능은 거의 할 수 없지만 이 기간 동안 프로세스가 차단되고 다른 작업을 수행할 수 없습니다(또는 응답하지 않게 됨). PHP는 왜 타이머 기능을 제공하지 않습니까?

이유

PHP가 웹 개발에서 타이머를 사용할 수 없는 근본적인 이유는 제어 가능한 상주 메모리 운영 환경이 부족하기 때문입니다. 두 가지 핵심 사항: 첫째, 상주 메모리, 둘째, 제어 가능. CGI 모드에서는 프로세스가 스크립트 실행 후 바로 종료되며 지정된 시간에 작업이 실행될 것으로 예상할 수 없습니다. PHP-FPM 모드에서는 프로세스가 (대부분) 메모리에 상주하지만 제어할 수 없습니다.

Uncontrollable은 PHP를 실행하는 프로세스가 PHP 코드의 영향을 받지 않으며 프로세스의 진입점과 종료 시점이 추가 프로그램에 의해 제어된다는 의미입니다. 예를 들어 FPM 모드에서 PHP 스크립트의 종료 및 다이 기능은 스크립트 실행을 중단할 뿐이며 스크립트 실행 프로세스에 특별한 영향을 미치지 않습니다(메모리 누수 제외). PHP 개발자가 작성한 스크립트는 프로세스의 실행 본문이며 실행 후 프로세스의 실행 컨텍스트에서 언로드됩니다. 이 경우 PHP 스크립트를 실행하는 타이밍은 여전히 ​​외부에 의해 좌우됩니다. 외부 요청이 없으면 PHP 코드는 아무 작업도 하지 않고 조용히 하드 디스크에 놓여 예약된 작업이 됩니다.

PHP는 주로 웹 개발을 지향하기 때문에 PHP의 실행 모드는 안정적이고 신뢰할 수 있으며 개발 효율성이 빠릅니다. 예를 들어 리소스 릴리스 단계를 생략하면 개발 시 많은 작업량과 함정을 피할 수 있습니다. 시간대, 문자 인코딩 등을 변경하고 이를 복원하지 않는 일부 타사 라이브러리 코드를 생각해 보십시오. 상주 메모리 실행 환경에서는 후속 요청에 문제가 발생할 것이 거의 확실합니다. 그러나 FPM 모드에서는 이 함정이 의도치 않게 완화되어 디버깅 시간을 많이 절약하고 프로그래머의 헤어라인 유지 능력에 상당한 기여를 합니다.

이제 문제를 이해했으므로 PHP에서 예약된 작업을 수행하기 위해 타이머를 어떻게 사용합니까?

위험한 습관

웹 환경에서 PHP 스크립트에는 기본적으로 시간 초과가 있습니다. 시간 초과 설정을 제거하면 프로그램이 백그라운드에서 계속 실행될 수 있습니다(프로세스가 종료되지 않는 경우). 예를 들어, 다음 코드는 요청에 응답한 후에도 백그라운드에서 계속 실행되어 5초마다 파일에 시간을 출력합니다.

# test.php
set_time_limit(0); # 取消超时设置,让脚本可一直运行

echo 'This is a background run forever script. Now you can leave me alone.';

fastcgi_finish_request();   # 结束当前请求

do{
   file_put_contents("/tmp/out.dat", "test script, now:" . date("Y-m-d H:i:s") . "\n", FILE_APPEND);
   sleep(5);
}while(true);

http://localhost:8080/test.php 파일에서 <code>/tmp/out.dat 파일을 모니터링하면 클라이언트 연결 끊기, 브라우저 닫기 또는 컴퓨터 재시작 여부에 관계없이 콘텐츠가 지속적으로 출력되는 것을 확인할 수 있습니다(서버는 다시 시작했습니다). 이는 프로그램이 실행되었으며 우리가 원하는 타이머 기능이 달성되었음을 나타냅니다. sleepusleep 또는 time_nanosleep으로 변경하면 마이크로초 및 나노초 타이머도 구현할 수 있으면 좋지 않을까요? http://localhost:8080/test.php文件后,监测/tmp/out.dat文件,会发现不断有内容输出,无论客户端是否断开连接、关闭浏览器或者重启电脑(不能重启服务器)。这说明程序一直在执行,并且也实现了我们想要的定时器功能。如果把sleep改成usleeptime_nanosleep,还能实现微秒、纳秒级定时器,岂不美哉?

实践中应当尽量避免用这种方式实现定时器,不仅因为低效,还略有危险。原因之一是每次请求会占用一个进程,请求十万次需要十万个进程,基本上会导致系统崩溃或后续请求无响应;另外如果打开了session,但是忘记调用session_write_close

실제로는 이러한 방식으로 타이머를 구현하는 것을 피해야 합니다. 비효율적일 뿐만 아니라 약간 위험하기 때문입니다. 그 이유 중 하나는 각 요청이 하나의 프로세스를 점유하고 10만 개의 요청에는 10만 개의 프로세스가 필요하기 때문입니다. 이로 인해 기본적으로 세션이 열려 있지만 사용자가 응답하지 않는 경우 시스템이 중단되거나 후속 요청이 응답하지 않게 됩니다. session_write_close를 호출하는 것을 잊어버리면 동일한 사용자의 후속 요청이 중단됩니다. 세션은 활성 상태일 때 잠긴 상태이며 세션을 닫지 못하면 후속 프로세스를 수행할 수 없습니다. 세션을 열려면).

웹 개발에서는 사용자 요청에 가능한 한 빨리 응답해야 합니다. 웹 개발에서 이러한 방식으로 타이머를 강제로 구현하면 전체 웹 애플리케이션이 불안정하고 신뢰할 수 없거나 예측할 수 없게 됩니다. 맹자가 말했다: 군자는 위험한 벽 아래 서지 않는다. 신뢰할 수 없는 관행은 최대한 피해야 하며, 책임을 떠맡거나 전가하는 행위도 피해야 합니다.

다음으로 PHP에서 타이머를 사용하는 올바른 자세를 살펴보겠습니다.

올바른 자세

PHP에서 타이머를 구현하는 방법은 다음과 같이 간단히 요약할 수 있습니다.
  • cron, Jenkins 및 기타 예약 도구를 사용하여 정기적으로 예약된 작업을 수행합니다(스크립트 실행 또는 특정 URL 요청).
  • 일회성 실행 작업은 메시지 대기열, 데이터베이스 등을 통해 실행하기 위해 타사 프로그램에 전달됩니다.
  • WordPress와 같은 예약된 작업을 시뮬레이션하지만 이 방법은 클라이언트 요청에 의존한다는 점을 기억하세요. 프로세스 동시성 문제를 직접 처리하려면
  • 상주 메모리 모드를 사용하여 PHP 프로그램, 즉 CLI 모드를 실행하세요. 🎜

세 번째 방법을 제외한 다른 모든 방법은 실제 필요에 따라 구체적인 계획을 고려하는 것이 좋습니다. 물론 PHP 프로그래머로서 첫 번째 선택은 CLI 모드인 PHP를 사용하는 것입니다.

CLI 모드

양심적으로 말하면 CLI 모드를 사용하면 PHP가 공간을 많이 확장할 수 있습니다. CLI 모드에서 프로그램의 진입점은 스크립트이고 코드는 메모리에 상주할 수 있으며 프로세스는 PHP 코드에 의해 완전히 제어됩니다. 이 형식에는 타이머를 구현하는 방법이 많이 있습니다. 이 문서에는 다른 사람들에게 영감을 줄 수 있는 몇 가지 방법이 나와 있습니다.

  • 내장된(고정밀) 타이머가 있는 swooleworkerman과 같은 프레임워크를 사용하세요. 멀티 프로세스(풀)/멀티 스레딩(풀) 기술을 사용합니다(pcntl, pthreads 확장은 CLI 모드에서만 사용 가능) swooleworkerman等框架,内置(高精度)定时器;

  • 使用多进程(池)/多线程(池)技术(pcntlpthreads拓展在CLI模式下才可用);

  • 处理tick或者alarm等信号;

  • 使用libeventlibev等事件驱动库;

  • sleep加循环或自己实现事件循环。

想折腾的话自己用2-5方案,不想折腾swooleworkerman

다음과 같은 프로세스 신호 틱 또는 알람

libeventlibev와 같은 이벤트 기반 라이브러리를 사용하여 루프를 추가하거나 구현합니다. 이벤트가 스스로 루프됩니다.

만들고 싶다면 swooleworkerman과 같은 프레임워크를 망치고 싶지 않다면 2-5 계획을 직접 사용하세요. 그들은 안정적이고 신뢰할 수 있는 첫 번째 선택입니다.

🎜Summary🎜🎜🎜 HTTP 요청과 작업의 관계를 구별하면 예약된 작업을 구현하는 것이 간단해집니다. 이를 구현하기 위해 PHP를 사용할 것인지 여부는 또 다른 문제입니다. 물론 웹 개발에 선호되는 언어인 PHP는 예약된 작업을 쉽게 구현할 수 있습니다. 🎜🎜추천 학습: "🎜PHP 비디오 튜토리얼🎜"🎜🎜

위 내용은 PHP에는 왜 타이밍 기능이 없나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.