• Tornado 高并发源码分析之五--- IOLoop 对象


    IOLoop主要工作
    1、将TCPServer 注册到 IOLoop 的事件记到 _handlers 字段,同时注册 READ 和 ERROR 事件到 epoll
    2、IOLoop 启动一个大循环,负责轮询epoll中是否已经有就绪的事件,如果有就执行对应的回调
     
    以下为源码分析,省略部分源码,只取主要部分
     1 class Configurable(object):
     2     """根据子类的配置,来创建一个对象,也就是说,继承自Configurable的子类,可以自己配置产生不同的类,并且每个类都会执行initialize方法
     3     __impl_class = None
     4     __impl_kwargs = None
     5 
     6     def __new__(cls, **kwargs):   
     7         base = cls.configurable_base()
     8         args = {}
     9         if cls is base:
    10             impl = cls.configured_class()
    11             if base.__impl_kwargs:
    12                 args.update(base.__impl_kwargs)
    13         else:
    14             impl = cls
    15         args.update(kwargs)
    16         instance = super(Configurable, cls).__new__(impl)
    17         instance.initialize(**args)   #执行initialize方法
    18         return instance
    Configurable
     1 class IOLoop(Configurable):
     2 " 一个大循环,自动根据当前的系统,是 linux 2.5以上选择epoll, mac 选择kqueue, 其他选择select".
     3 @staticmethod
     4 def instance():   #创建一个全局的 IOLoop 单例
     5     if not hasattr(IOLoop, "_instance"):
     6         with IOLoop._instance_lock:
     7             if not hasattr(IOLoop, "_instance"):
     8                 IOLoop._instance = IOLoop()
     9     return IOLoop._instance
    10 
    11 
    12 @classmethod    配置
    13 def configurable_base(cls):
    14     return IOLoop
    15 
    16 @classmethod
    17 def configurable_default(cls):   #根据系统,配置使用epoll还是 kqueue
    18     if hasattr(select, "epoll"):
    19         from tornado.platform.epoll import EPollIOLoop
    20         return EPollIOLoop
    21     if hasattr(select, "kqueue"):
    22         # Python 2.6+ on BSD or Mac
    23         from tornado.platform.kqueue import KQueueIOLoop
    24         return KQueueIOLoop
    25     from tornado.platform.select import SelectIOLoop
    26     return SelectIOLoop
    IOLoop
     1 class PollIOLoop(IOLoop):
     2 "继承自IOLoop, 就是IOLoop 在根据系统选择的时候,真正创建的类对象"
     3 
     4 def add_handler(self, fd, handler, events):
     5     fd, obj = self.split_fd(fd)
     6     self._handlers[fd] = (obj, stack_context.wrap(handler))    #将socket对象的句柄fd作为key, 回调函数handler作为值,添加到 _handlers 字段中, 其实这里的函数就是在TCPServer 启动时添加的 _handle_connection 方法
     7     self._impl.register(fd, events | self.ERROR)   #向_impl (在linux中是epoll,在mac中是kqueue,2.5版本一下的linux中是select)中注册对应句柄fd 的事件(其实就是READ和error事件)
     8 
     9 def start(self):
    10   
    11     try:
    12         while True:   #启动IOLoop 大循环, 这是一个无限循环
    13    
    14             with self._callback_lock:   #如果有上一个循环没有执行完毕的函数,继续拿出来执行
    15                 callbacks = self._callbacks
    16                 self._callbacks = []
    17 
    18         
    19             try:
    20                 event_pairs = self._impl.poll(poll_timeout)   #从epoll中取出已经就绪的事件
    21             except Exception as e:
    22                 if errno_from_exception(e) == errno.EINTR:
    23                     continue
    24                 else:
    25                     raise
    26 
    27             self._events.update(event_pairs)   #将事件更新到 _events dict中
    28             while self._events:
    29                 fd, events = self._events.popitem()
    30                 try:
    31                     fd_obj, handler_func = self._handlers[fd]   #从刚开始添加事件到_handler里面取出对应的回调函数
    32                     handler_func(fd_obj, events)  #执行回调函数, 其实也就是执行TCPServer中的self._handle_connection 方法
    33                 except (OSError, IOError) as e:
    34                         self.handle_callback_exception(self._handlers.get(fd))
    35                 except Exception:
    36                     self.handle_callback_exception(self._handlers.get(fd))
    37             fd_obj = handler_func = None   #清空,准备进入下一次循环
    38 
    39     finally:
    40        ignal.set_wakeup_fd(old_wakeup_fd)
    PollIOLoop
  • 相关阅读:
    ChaosBlade x SkyWalking 微服务高可用实践
    工商银行基于 Dubbo 构建金融微服务架构的实践-服务发现篇
    阿里 双11 同款流控降级组件 Sentinel Go 正式 GA,助力云原生服务稳稳稳
    我在阿里巴巴做 Serverless 云研发平台
    「更高更快更稳」,看阿里巴巴如何修炼容器服务「内外功」
    「云原生上云」后的聚石塔是如何应对 双11 下大规模应用挑战的
    从零入门 Serverless | SAE 的远程调试和云端联调
    利用 Arthas 解决启动 StandbyNameNode 加载 EditLog 慢的问题
    Arthas 实践——生产环境排查 CPU 飚高问题
    RocketMQ 很慢?引出了一个未解之谜
  • 原文地址:https://www.cnblogs.com/hepingqingfeng/p/6655830.html
Copyright © 2020-2023  润新知