Django 소스 읽기 (4): Django의 자동 로드 메커니즘

5861 단어 Django 소스 읽기
  • django는 파일의 변화를 감청하여 자동으로 재부팅한다. 절차는 대체로:django 서비스가 시작되는 동시에 두 개의 프로세스를 시작한다. 하나는 파일의 변화를 감시하고 하나는 메인 프로세스이다. 만약에 파일에 변화가 발생하면 현재 프로세스를 종료하고 하위 프로세스를 다시 시작한다.

  • 두 프로세스
  • 다시 시작하는 설정은runwith_reloader 함수에서 RUN이 설정되어 있는지 여부를 판단합니다.MAIN은 True이지만 처음에는 이 환경 변수가 없기 때문에 프로그램은 else 코드 블록을 걷고restartwith_reloader에서 이 환경 변수new_environ = {**os.environ, DJANGO_AUTORELOAD_ENV: 'true'}를 설정합니다.
  • 새로운 환경 변수에서subprocess를 사용합니다.call에서 새 하위 프로세스를 시작합니다. 이 하위 프로세스는 현재 명령 (python manage.py runserver) 을 실행하고 있습니다. 현재 RUNMAIN은 True입니다. 실행start_django(reloader, main_func, *args, **kwargs), 즉 서버를 시작합니다.하위 프로세스가 종료되지 않으면subprocess에서 계속 멈춥니다.call 이 단계;만약 종료 코드가 3이 아니라면 하위 프로세스가 종료되면while는 종료됩니다.3이면 순환을 계속하여 하위 프로세스를 다시 만듭니다.
  • 에서 알 수 있듯이django의autoreload 메커니즘에서 메인 프로세스는 사실 아무 일도 하지 않았다. 바로 하위 프로세스의 운행을 감시하는 것이다. 만약에 하위 프로세스의 종료 코드가 3이라면 하위 프로세스를 계속 생성한다.
  • #django/utils/autoreload.py
    DJANGO_AUTORELOAD_ENV = 'RUN_MAIN'
    ...
    def restart_with_reloader():
        new_environ = {**os.environ, DJANGO_AUTORELOAD_ENV: 'true'}
        args = get_child_arguments()
        while True:
            exit_code = subprocess.call(args, env=new_environ, close_fds=False)
            if exit_code != 3:
                return exit_code
                
    def run_with_reloader(main_func, *args, **kwargs):
        signal.signal(signal.SIGTERM, lambda *args: sys.exit(0))
        try:
            if os.environ.get(DJANGO_AUTORELOAD_ENV) == 'true':
                reloader = get_reloader()
                logger.info('Watching for file changes with %s', reloader.__class__.__name__)
                start_django(reloader, main_func, *args, **kwargs)
            else:
                exit_code = restart_with_reloader()
                sys.exit(exit_code)
        except KeyboardInterrupt:
            pass
    

    실제 문제
  • 프로젝트에서django의 프로세스를 지키기 위해 슈퍼visord를 사용했을 때 프로젝트를 다시 시작할 때 특히 느린 것을 발견했습니까?
  • 그러나 슈퍼visord가django를 시작할 때 두 프로세스 중 하나를 감시하기 때문에 실제적으로 슈퍼visord는 무효이며 메인 프로세스와 충돌하여 포트를 차지할 수도 있다.

  • 솔루션
  • django의reload를 취소하고django에 대한 웹 서비스에 -noreload 파라미터를 추가할 수 있다. 즉reload를 사용하면 된다
  • Supervisord를 사용하지 않거나 다른 솔루션을 찾는 경우
  • 좋은 웹페이지 즐겨찾기