찾다
운영 및 유지보수안전Gunicorn Arbiter 소스 코드를 분석하는 방법

Gunicorn Arbiter 소스 코드를 분석하는 방법

May 12, 2023 pm 04:28 PM
gunicornarbiter

앞서 언급했듯이 Arbiter는 Gunicorn 마스터 프로세스의 핵심입니다. Arbiter는 작업자 프로세스 시작, 모니터링 및 종료를 포함하여 작업자 프로세스를 관리하는 일을 주로 담당합니다. 동시에 Arbiter는 특정 신호가 발생할 때 앱 애플리케이션을 핫 업데이트(다시 로드)하거나 온라인으로 gunicorn을 업그레이드할 수도 있습니다. Arbiter의 핵심 코드는 하나의 파일에 들어 있으며, 코드 양은 많지 않습니다. 소스 코드는 https://github.com/benoitc/gunicorn입니다.

Arbiter에는 주로 다음과 같은 방법이 있습니다.

setup:

구성 항목을 처리하는데, 가장 중요한 것은 작업자 수와 작업자 작업 모델입니다.

init_signal:

신호 처리 기능 등록

handle_xxx :

각 신호의 특정 처리 기능

kill_worker, kill_workers:

작업자 프로세스에 신호 보내기

spawn_worker,spawn_workers:

새 작업자 프로세스를 포크합니다

murder_workers:

일정 시간 내에 응답하지 않는 작업자 프로세스 종료

manage_workers:

구성 파일의 작업자 수와 현재 활성 작업자 수를 기반으로 작업자 프로세스를 분기할지 종료할지 결정합니다.

reexec :

신호 SIGUSR2 호출 수신, 온라인 업그레이드 gunicorn

reload:

신호 SIGHUP 호출을 받은 후 작업자 프로세스는 새로운 구성에 따라 시작되고 이전 작업자 프로세스는 종료됩니다

sleep :

신호 처리가 없는 경우 선택 타임아웃을 사용하여 잠자기하고 깨울 수 있습니다.

wakeup:

파이프에 메시지를 작성하여 프로세스를 깨우고

run:

메인 루프

실제로 다른 코드(애플리케이션)에 의해 Arbiter가 호출되는 유일한 함수는 __init_ _이며 코드 한 문장에서 실행 메서드는 다음과 같습니다.

Arbiter(self).run()

  위 코드의 self는 애플리케이션 인스턴스입니다. , 여기서 __init__는 setup을 호출하여 구성 항목을 설정합니다. 다음은 실행 메소드의 의사 코드입니다


def run()
    self.init_signal()
    self.LISTENERS = create_sockets(self.cfg, self.log)
    self.manage_workers()    while True:        if no signal in SIG_QUEUE
            self.sleep()        else:
            handle_signal()


포크 하위 프로세스에 대해

포크 하위 프로세스에 대한 코드는spawn_worker에 있으며, 소스 코드는 다음과 같습니다.

如何进行gunicorn Arbiter 源码解析 Arbiter.spawn_worker

기본 프로세스:

(1) Worker_class 로드 및 인스턴스화(기본값은 동기 모델 SyncWorker)

(2) 상위 프로세스(마스터 프로세스)는 포크 후 반환되고 모든 후속 로직은 하위에서 실행됩니다. process

(3) Worker.init_process를 호출하여 루프, 새 채널에 들어갑니다. IELTS 훈련의 모든 작업은 이 루프에 있습니다.

(4) 루프가 끝난 후 sys.exit(0)

을 호출합니다. (5) 마지막으로 , 마지막으로 작업자 프로세스의 종료를 기록합니다.

다음은 메인 포크 프로세스를 단순화하기 위해 작은 코드를 작성한 것입니다.


 1 # prefork.py 2 import sys 3 import socket 4 import select 5 import os 6 import time 7   8 def do_sub_process(): 9     pid = os.fork()10     if pid  0:14         print 'fork sub process %d'  % pid15         return16  17     # must be child process18     time.sleep(1)19     print 'sub process will exit', os.getpid(), os.getppid()20     sys.exit(0)21  22 def main():23     sub_num = 224     for i in range(sub_num):25         do_sub_process()26     time.sleep(10)27     print 'main process will exit', os.getpid()28  29 if __name__ == '__main__':30     main()


테스트 환경에서의 출력:

 fork sub 프로세스 9601

 fork 하위 프로세스 9602

 하위 프로세스는 9601 9 600

하위 프로세스는 9602 9600

기본 프로세스는 9600

을 종료합니다. 라인 20은 sys.exit을 호출합니다. 보장하다 하위 프로세스가 종료됩니다. 그렇지 않으면 기본 함수의 for 루프와 후속 논리가 계속됩니다. 19행을 주석 처리하고 다시 실행하면 출력을 보면 이해할 수 있습니다.

자식 프로세스 종료에 대하여

 마스터 프로세스가 작업자 프로세스를 종료하는 것은 매우 간단하며 직접 신호를 보내기만 하면 됩니다. 소스 코드는 다음과 같습니다.


 1     def kill_worker(self, pid, sig): 2         """\ 3         Kill a worker 4  5         :attr pid: int, worker pid 6         :attr sig: `signal.SIG*` value 7          """ 8         try: 9             os.kill(pid, sig)10         except OSError as e:11             if e.errno == errno.ESRCH:12                 try:13                     worker = self.WORKERS.pop(pid)14                     worker.tmp.close()15                     self.cfg.worker_exit(self, worker)16                     return17                 except (KeyError, OSError):18                     return19             raise


잠자기 및 wakeup

Arbiter sleep과 wakeup을 살펴보겠습니다. Arbiter는 처리할 신호가 없을 때 "sleep"합니다. 물론 실제로 time.sleep을 호출하지 않습니다. 그렇지 않으면 신호가 오면 즉시 처리되지 않습니다. 여기서 구현은 파이프와 선택 시간 초과를 사용하여 더 영리합니다. 코드를 보면 알 수 있습니다


        def sleep(self):        """\
        Sleep until PIPE is readable or we timeout.
        A readable PIPE means a signal occurred.        """
            ready = select.select([self.PIPE[0]], [], [], 1.0) # self.PIPE = os.pipe()
            if not ready[0]: 
                return
            while os.read(self.PIPE[0], 1):                pass

코드의 주석은 매우 명확합니다. PIPE는 읽을 수 있고 즉시 반환되거나 대기 시간이 초과됩니다. 신호가 발생하기 때문에 파이프를 읽을 수 있습니다. 파이프 함수를 살펴보세요

  •  os.pipe()  os.pipe()

  • Create a pipe. Return a pair of file descriptors (r,w)

파일 설명자 쌍을 반환합니다. (r, w) 는 각각 읽기 및 쓰기에 사용할 수 있습니다.

그런 다음 파이프를 읽을 수 있는 경우를 살펴보겠습니다. 파이프에 기록된 내용이어야 합니다. 이것은 wakeup 함수

        def wakeup(self):            """
            Wake up the arbiter by writing to the PIPE            """
            os.write(self.PIPE[1], b'.')
입니다.

마지막으로 Arbiter 신호 처리를 연결합니다.

:

Exit, INT: 빠른 종료 🎜🎜TERM: 우아한 종료. 시간이 초과될 때까지 작업자가 현재 요청을 완료할 때까지 기다립니다. 🎜

HUP: 구성을 다시 로드하고, 새로운 구성으로 새 작업자 프로세스를 시작하고, 이전 작업자 프로세스를 정상적으로 종료합니다. Gunicorn은 애플리케이션이 사전 로드되지 않은 경우에도 새 버전을 로드합니다(--preload 옵션 사용).

TTIN: 프로세스 수를 하나씩 늘립니다.

TTOU: 프로세스 수를 하나씩 줄입니다.

USR1: 로그 파일을 다시 엽니다.

USR2: 즉시 Gunicorn을 업그레이드합니다. 이전 프로세스를 종료하려면 별도의 용어 신호를 사용해야 합니다. 이 신호는 사전 로드된 새 버전의 애플리케이션을 사용하는 데에도 사용될 수 있습니다.

Winch: Gunicorn이 데몬화되면 작업자 프로세스를 정상적으로 종료합니다.

위 내용은 Gunicorn Arbiter 소스 코드를 분석하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
이 기사는 亿速云에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경