Tornado of the Python framework (request Phase)

Source: Internet
Author: User
Tags epoll

Is the whole process of Tornado program start-up and receiving client requests, the whole process can be divided into two parts:

    • Start the program phase, also known as the pending request Phase (1, 2 All series and 3.0)
    • Receiving and processing the client request phase (3 Series)

Nutshell:

1, in the Start program phase, the first step, get the configuration file and then generate a URL map (that is: a URL corresponding to a xxrequesthandler, so that Xxrequesthandler to handle the request sent by the specified url); Create the server socket object and add it to epoll; third, create a wireless loop to listen to the Epoll. 2, in receiving and processing the request phase, the first step, Receive a request from the client socket (socket.accept); The second step is to obtain the request header information from the request and then match a xxrequesthandler based on the request URL in the request header; the third step is to match the successful Xxrequesthandler processing request; fourth step, place After the request is sent to the client, the fifth step is to close the client Socket.

This article mainly analyzes the "start program phase", the following we will be a step-by-step analysis of the entire process, at this stage is mainly marked by the following three methods to Achieve.

Import Tornado.ioloopimport Tornado.web class MainHandler (tornado.web.RequestHandler):    def get (self):        Self.write ("Hello, World") application = tornado.web.Application ([    (r "/index", mainhandler),]) if __name__ = = "__ main__ ":    application.listen (8888)    tornado.ioloop.IOLoop.instance (). start ()
one, application = tornado.web.Application ([(xxx,xxx)])

Executes the constructor of the application class and passes in a parameter of the list type, which holds the URL rule and the corresponding processing class, that is, when the Client's request URL can be configured with this rule, then the request is sent to the corresponding handler to Execute.

Note: handler refers to all classes that inherit from RequestHandler
Handlers refers to the collection of all classes that inherit from RequestHandler

Class Application (object): def __init__ (self, handlers=none, default_host= "", transforms=none,wsgi=false, **settings) : #设置响应的编码和返回方式, corresponding HTTP header: content-encoding and transfer-encoding #Content-encoding:gzip means compressing the data and then returning it to the user, thereby reducing        Transfer of Traffic.        #Transfer-encoding:chunck represents the way data is transmitted through a piece of Transmission. If transforms is None:self.transforms = [] if Settings.get ("gzip"): self.transforms. Append (gzipcontentencoding) self.transforms.append (chunkedtransferencoding) else:self.transf Orms = transforms #将参数赋值为类的变量 self.handlers = [] Self.named_handlers = {} Self.default_host = Default_host self.settings = Settings #ui_modules和ui_methods用于在模版语言中扩展自定义输出 #这里将tornado内置的ui_modules和                           Ui_methods added to the Class's member variables self.ui_modules and self.ui_methods self.ui_modules = {' linkify ': _linkify, ' xsrf_form_html ': _xsrf_form_html, ' Template ': Templatemodule,} Self.ui_methods = {} Self._wsgi = Wsgi #获取获取用户自定义的ui_modules和u        I_methods and add them to the previously created member variables self.ui_modules and self.ui_methods in Self._load_ui_modules (settings.get ("ui_modules", {})) The Self._load_ui_methods (settings.get ("ui_methods", {})) #设置静态文件路径, is set by matching the URL with a regular expression, letting the Staticfil            Ehandler to handle matching URLs if Self.settings.get ("static_path"): #从settings中读取key为static_path的值 for setting the static file path             Path = self.settings["static_path"] #获取参数中传入的handlers, If NULL is set to an empty list handlers = List (handlers or []) #静态文件前缀, the default Is/static/static_url_prefix = Settings.get ("static_url_prefix", "/static/") #在参 Add three mappings before the incoming handlers in the Number: # "/static/.*"--staticfilehandler # "/(FAVICON\.ICO)"--&G  T StaticFileHandler # "/(robots\.txt)"--staticfilehandler handlers = [(re . Escape (STATIC_URL_PREfix) + R "(. *)", staticfilehandler,dict (path=path)), (r "/(favicon\.ico)", staticfilehandler, dict (path=path )), (r "/(robots\.txt)", staticfilehandler, dict (path=path)),] + handlers #执行本类的Applicati On the Add_handlers method #此时, handlers is a list in which each element is a corresponding relationship, that is, the URL regular expression and the handler if Handlers:self.add_han that handles the URL that matches the regular. Dlers (". *$", Handlers) # automatically reload modified modules #如果settings中设置了 Debug mode, Then use auto-load restart I F Self.settings.get ("debug") and not wsgi:import autoreload Autoreload.start () application.__init__
application.__init__
Class Application (object): def add_handlers (self, host_pattern, host_handlers): #如果主机模型最后没有结尾符, Add a trailing character for Him. If not host_pattern.endswith ("$"): Host_pattern + = "$" handlers = [] #对主机名先做一层路由映射, for example: http:/        /www.wupeiqi.com and http://safe.wupeiqi.com #即: safe corresponds to a set of URL mappings, www corresponds to a set of URL mappings, then when the request arrives, first match it according to it, then continue to enter the internal Match. #对于第一层url映射来说, Because. * will match all urls, will be. * always at the end of the handlers list, Otherwise. * will be cut and ... #re. Complie is a compiled regular expression that is only required to execute the match method of the compiled result when the request is Made. To match the If self.handlers and Self.handlers[-1][0].pattern = = '. *$ ': self.handlers.insert ( -1, (re.compile (h Ost_pattern) (HANDLERS)) else:self.handlers.append ((re.compile (host_pattern), HANDLERS)) #遍历我们设置 And the "url->handler" map added in the constructor, encapsulates the URL and the corresponding Handler into the Urlspec class (the URL is compiled in the Constructor) #并将所有的URLSpec对象添加到handlers列表中, instead, The handlers list and hostname model form a meta-ancestor, which is added to Self.        The Handlers List.  For spec in Host_handlers:if type (SPEC) was type (()): assert Len (spec) in (2, 3)              Pattern = spec[0] Handler = spec[1] If len (spec) = = 3:kwar            GS = spec[2] Else:kwargs = {} spec = Urlspec (pattern, handler, Kwargs)                Handlers.append (SPEC) if spec.name: #未使用该功能, default spec.name = None If spec.name in self.named_handlers:logging.warning ("multiple handlers named%s; Replacing previous value ", Spec.name) self.named_handlers[spec.name] = specapplication.add_handlers
application.add_handlers
Class Urlspec (object):    def __init__ (self, pattern, handler_class, kwargs={}, name=none):        if not Pattern.endswith (' $ '):            pattern + = ' $ '        Self.regex = re.compile (pattern)        self.handler_class = Handler_ Class        Self.kwargs = Kwargs        self.name = name        self._path, self._group_count = self._find_groups () urlspec
Urlspec

The code above mainly accomplishes the following functions: loading configuration information and generating URL mappings, and encapsulating all the information in a application Object.

The configuration information that is loaded includes:

    • Encoding and return mode information
    • Static file path
    • Ui_modules (used in template language, temporarily ignored)
    • Ui_methods (used in template language, temporarily ignored)
    • Whether debug mode is running

All of the configuration information above can be configured in settings, and then pass in parameters when creating application Objects. Such as: application = tornado.web.Application ([(r "/index", Mainhandler),],**settings)

To generate a URL map:

    • Add the URL and the corresponding handler to the corresponding host prefix, such as: safe.index.com, www.auto.com

second, Application.listen (xxx)

The first step encapsulates information such as configuration and URL mapping into the application object, and this second step executes the listen method of the application Object. The method internally encapsulates the application object that previously contained various information into a httpserver object, and then continues to invoke the Liseten method of the Httpserver Object.

Class application (object):    #创建服务端socket, and bind the IP and port and add the appropriate settings, note: do not start through while listening to accept, waiting for the client to connect    def listen (self, port, address= "", **kwargs): from        tornado.httpserver import httpserver        server = Httpserver (self, **kwargs)        

Detailed code:

Class Httpserver (object): def __init__ (self, request_callback, no_keep_alive=false, io_loop=none,xheaders=false, ssl_ options=none): #Application对象 self.request_callback = request_callback #是否长连接 Self.no_keep_ali ve = no_keep_alive #IO循环 self.io_loop = io_loop self.xheaders = xheaders #Http和Http sel         F.ssl_options = ssl_options Self._socket = None self._started = False def listen (self, port, address= ""):        Self.bind (port, address) self.start (1) def bind (self, port, address=none, family=socket.af_unspec): Assert not Self._socket #创建服务端socket对象, IPV4 and TCP connections Self._socket = Socket.socket (socket.af_inet, socket. sock_stream, 0) flags = fcntl.fcntl (self._socket.fileno (), Fcntl. F_getfd) Flags |= Fcntl. Fd_cloexec fcntl.fcntl (self._socket.fileno (), Fcntl. f_setfd, Flags) #配置socket对象 self._socket.setsockopt (socket). sol_socket, SOCKET.   so_reuseaddr, 1)     Self._socket.setblocking (0) #绑定IP和端口 self._socket.bind (address, port) #最大阻塞数量 SELF._SOC  Ket.listen (+) def start (self, num_processes=1): assert not self._started self._started = True If  Num_processes is None or num_processes<= 0:num_processes= _cpu_count ()if Num_processes> 1 and Ioloop.                          ioloop.initialized (): logging.error ("cannot run in multiple Processes:ioloop instance" "has already been Initialized.        You cannot call "" ioloop.instance () before calling start () ") num_processes = 1            #如果进程数大于1 if num_processes > 1:logging.info ("pre-forking%d server processes", num_processes)                    For I in range (num_processes): if os.fork () = = 0:import Random                        From binascii import hexlify try: # If available, Use the same method as # random.py seed = long (hexlify (os.urandom), +) except not  Implementederror: # Include The PID to avoid initializing-processes to                The same value seed (int (time.time () * +) ^ os.getpid ())    Random.seed (seed) Self.io_loop = ioloop. Ioloop.instance () self.io_loop.add_handler (self._socket.fileno (), self._handle_ events, ioloop. Ioloop.read) return Os.waitpid ( -1, 0) #进程数等于1, default Else:if not self. Io_loop: #设置成员变量self. Io_loop As an example of ioloop, note: Ioloop uses Methodclass to complete a singleton mode Self.io_loop = Ioloop. Ioloop.instance () #执行IOLoop的add_handler方法, The socket handle, self._handle_events method, and Ioloop.read are passed in as arguments self.io_l                                     Oop.add_handler (self._socket.fileno (), self._handle_events, Ioloop. Ioloop.read) def _handle_events (self, fd, events): while True:try: #====important==== =# connection, address = self._socket.accept () except socket.error, e:if e.args[ 0] in (errno. ewouldblock, ERRno. eagain): return raise if self.ssl_options is not None:assert                    ssl, "Python 2.6+ and OpenSSL required for SSL" try: #====important=====#                Connection = Ssl.wrap_socket (connection,server_side=true,do_handshake_on_connect=false,**self.ssl_options) Except Ssl. sslerror, err:if err.args[0] = = Ssl.                Ssl_error_eof:return connection.close () else:raise Except socket.error, err:if err.args[0] = = Errno.            Econnaborted:return connection.close () else:raise Try:if self.ssl_options is not none:stream = Iostream. Ssliostream (connection, io_loop=self.io_loop) else:stream = Iostream. IOStream (connection, io_loop=self.IO_LOOP) #====important=====# httpconnection (stream, address, self.request_callback,self.no_  keep_alive, self.xheaders) except:logging.error ("error in connection callback", Exc_info=true)
Httpserver

Tornado of the Python framework (request Phase)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.