web.py 학습(-) 로켓 웹 프레임워크

19704 단어 web.py
Rocket은 경량급, 다중 루틴, WSGI 규범에 부합되는 웹 프레임워크이다.
Rocket은 하나의 라인으로 연결을 감청하고 연결을 받은 후Queue에 넣고 워크맨 라인으로 처리합니다.
Rocket에는 다음과 같은 속성이 있습니다.
  • method  - A string value indicating the type of Worker to use to answer the requests received by Rocket. The default is wsgi and will invoke the WSGIWorker class for handling requests. Go to the Methods  section to see all available methods.
  • app_info  - A dictionary that holds information that the Worker class specified in method will use for configuration. See the documentation in the  Methods  section for the Worker class you are using for details on what to put in this dictionary.
  • min_threads  - An integer number of minimum Worker threads to run. This number must be greater than 0. Rocket will always have at least min_threads number of threads running at a time unless it is in the process of shutting down.
  • max_threads  - An integer number of maximum Worker threads. This number must be greater than  min_threads  or 0. A  max_threads  of 0 (zero) indicates there to be no maximum thread count. Rocket will continue generating threads so long as there are unanswered connections in the request queue. If the running environment is limited by how many threads a process can own, consider that in addition to  max_threads  there will also be a monitor thread and listening thread running.
  • queue_size  - An integer number of connections allowed to be queued before Rocket accepts them. This number is passed to the listen() function in the operating system’s socket library. It defaults toNone which either uses the operating system’s maximum or 5 if the OS max is not discoverable.
  • timeout  - An integer number of seconds to listen to a connection for a new request before closing it. Defaults to 600.
  • handle_signals  - A boolean indicating whether or not Rocket should respond to UNIX-style process signals (if the platform supports signals). Defaults to True.

  • min_threads는 0보다 큰 숫자여야 합니다. 로켓은 같은 시간에 반드시min 보다 큰 숫자가 있어야 합니다.threads가 실행 중입니다. 기본값은 10입니다.
    max_threads는 최대 몇 개의 라인이 동시에 실행되고 기본적으로 제한이 없으며 cPython에 있어 GIL이 존재하기 때문에 라인의 수량이 많고 문제가 없다.Jpython의 경우 진정한 다중 스레드이기 때문에 웹의 병목이 CPU에 있다면 maxthreads는 CPU 코어 수의 1.5배이므로 멀티스레드 전환을 방지하여 효율성이 떨어집니다.
    queue_size는 기본적으로 수신할 수 있는 연결 개수를 가리키며, 보통 이 값은 시스템에 의해 결정된다.
     
    Web.py에서 Rocket 프레임이 사용되고 초기 코드는 다음과 같습니다.
    class Rocket(object):
        """The Rocket class is responsible for handling threads and accepting and
        dispatching connections."""
    
        def __init__(self,
                     interfaces=('127.0.0.1', 8000),
                     method='wsgi',
                     app_info=None,
                     min_threads=None,
                     max_threads=None,
                     queue_size=None,
                     timeout=600,
                     handle_signals=True):
    
            self.handle_signals = handle_signals
            self.startstop_lock = Lock()
            self.timeout = timeout
    
            if not isinstance(interfaces, list):
                self.interfaces = [interfaces]
            else:
                self.interfaces = interfaces
    
            if min_threads is None:
                min_threads = DEFAULTS['MIN_THREADS']
    
            if max_threads is None:
                max_threads = DEFAULTS['MAX_THREADS']
    
            if not queue_size:
                if hasattr(socket, 'SOMAXCONN'):
                    queue_size = socket.SOMAXCONN
                else:
                    queue_size = DEFAULTS['LISTEN_QUEUE_SIZE']
    
            if max_threads and queue_size > max_threads:
                queue_size = max_threads
    
            if isinstance(app_info, dict):
                app_info['server_software'] = SERVER_SOFTWARE
    
            self.monitor_queue = Queue()
            self.active_queue = Queue()
    
            self._threadpool = ThreadPool(get_method(method),
                                          app_info=app_info,
                                          active_queue=self.active_queue,
                                          monitor_queue=self.monitor_queue,
                                          min_threads=min_threads,
                                          max_threads=max_threads)
    
            # Build our socket listeners
            self.listeners = [Listener(
                i, queue_size, self.active_queue) for i in self.interfaces]
            for ndx in range(len(self.listeners) - 1, 0, -1):
                if not self.listeners[ndx].ready:
                    del self.listeners[ndx]
    
            if not self.listeners:
                log.critical("No interfaces to listen on...closing.")
                sys.exit(1)
    
        def _sigterm(self, signum, frame):
            log.info('Received SIGTERM')
            self.stop()
    
        def _sighup(self, signum, frame):
            log.info('Received SIGHUP')
            self.restart()
    
        def start(self, background=False):
            log.info('Starting %s' % SERVER_SOFTWARE)
    
            self.startstop_lock.acquire()
    
            try:
                # Set up our shutdown signals
                if self.handle_signals:
                    try:
                        import signal
                        signal.signal(signal.SIGTERM, self._sigterm)
                        signal.signal(signal.SIGUSR1, self._sighup)
                    except:
                        log.debug('This platform does not support signals.')
    
                # Start our worker threads
                self._threadpool.start()
    
                # Start our monitor thread
                self._monitor = Monitor(self.monitor_queue,
                                        self.active_queue,
                                        self.timeout,
                                        self._threadpool)
                self._monitor.setDaemon(True)
                self._monitor.start()
    
                # I know that EXPR and A or B is bad but I'm keeping it for Py2.4
                # compatibility.
                str_extract = lambda l: (l.addr, l.port, l.secure and '*' or '')
    
                msg = 'Listening on sockets: '
                msg += ', '.join(
                    ['%s:%i%s' % str_extract(l) for l in self.listeners])
                log.info(msg)
    
                for l in self.listeners:
                    l.start()
    
            finally:
                self.startstop_lock.release()
    
            if background:
                return
    
            while self._monitor.isAlive():
                try:
                    time.sleep(THREAD_STOP_CHECK_INTERVAL)
                except KeyboardInterrupt:
                    # Capture a keyboard interrupt when running from a console
                    break
                except:
                    if self._monitor.isAlive():
                        log.error(traceback.format_exc())
                        continue
    
            return self.stop()
    
        def stop(self, stoplogging=False):
            log.info('Stopping %s' % SERVER_SOFTWARE)
    
            self.startstop_lock.acquire()
    
            try:
                # Stop listeners
                for l in self.listeners:
                    l.ready = False
    
                # Encourage a context switch
                time.sleep(0.01)
    
                for l in self.listeners:
                    if l.isAlive():
                        l.join()
    
                # Stop Monitor
                self._monitor.stop()
                if self._monitor.isAlive():
                    self._monitor.join()
    
                # Stop Worker threads
                self._threadpool.stop()
    
                if stoplogging:
                    logging.shutdown()
                    msg = "Calling logging.shutdown() is now the responsibility of \
                           the application developer.  Please update your \
                           applications to no longer call rocket.stop(True)"
                    try:
                        import warnings
                        raise warnings.DeprecationWarning(msg)
                    except ImportError:
                        raise RuntimeError(msg)
    
            finally:
                self.startstop_lock.release()
    
        def restart(self):
            self.stop()
            self.start()

    start 메서드에서 다음 단계를 수행합니다.
     
    1. 시동 닫기 잠금 및 잠금
    2, 등록 종료 및 재시작 신호
    3. Worker 스레드 풀을 시작합니다.
    4. 모니터링 스레드를 시작하고 모니터링 스레드를 스레드 풀에 추가
    5, 모든 감청 라인 시작
    6. 시동 잠금 해제
    7,while(감시 라인 생존) 순환에 들어가고 매번 휴면 1s
     
    stop 방법:
    1. 시동 닫기 잠금 및 잠금
    2. 모든 스레드 감청 설정ready는False로 표시
    3. 모든 감청 라인이 끝날 때까지 기다린다
    4. 모니터링 라인이 끝날 때까지 기다린다
    5、worker 스레드 풀 닫기
    6, 출력 닫기log
    7. 시동 잠금 해제

    좋은 웹페이지 즐겨찾기