当前位置: 首页 > 编程日记 > 正文

[原]tornado源码分析系列(三)[网络层 IOLoop类]

引言:由于都是在工作当中抽出时间看源代码,所以更新速度比较慢,但是还是希望通过对好的源码的分析和探讨,大家相互学习,发现不好的地方共同讨论。

上次讲了IOLoop中的几个重要的方法,inistance() 和 add_handler() .. 今天看看Demo中一个最重要的方法,start(),顺带用stop()收尾

    def start(self):"""Starts the I/O loop.The loop will run until one of the I/O handlers calls stop(), whichwill make the loop stop after the current event iteration completes."""if self._stopped:self._stopped = Falsereturnself._running = Truewhile True:# Never use an infinite timeout here - it can stall epollpoll_timeout = 0.2# Prevent IO event starvation by delaying new callbacks# to the next iteration of the event loop.callbacks = self._callbacksself._callbacks = []#先运行注册了的回调函数for callback in callbacks:self._run_callback(callback)if self._callbacks:poll_timeout = 0.0#检查超时事件#方法是,在timeout这个bisect的排序的列表,每次取出头部最小的一个#将deadline与当前时间比较,如果 <= 当前时间,就认为超时,然后调用相应的超时处理的回调函数#这里不好理解的是deadline <= 当前时间 , 如果说deadline 大于当前时间,就代表还没有到#超时条件#循环检查,直到超时事件处理完成#值得一说的是在libevent中是使用了最小堆每次取出当前的最小deadline#由于最小堆的特性,每次从头取出的都是最小的#Nginx的网络模块是用的红黑树来做,原理也是一样的if self._timeouts:now = time.time()while self._timeouts and self._timeouts[0].deadline <= now:timeout = self._timeouts.pop(0)self._run_callback(timeout.callback)#处理完了超时时间之后,需要将epoll最大阻塞时间改为小于当前最小超时时间的绝对值#不然可能在epoll返回后,本来不属于超时事件的事件被超时if self._timeouts:milliseconds = self._timeouts[0].deadline - nowpoll_timeout = min(milliseconds, poll_timeout)#判断“反应堆”是否结束#结束有两个方式,一个是设置_running 标志位,第二个就是往写管道写入"x"if not self._running:break#从注释中可以看出,每次进入epoll等待事件之前都需要把sigalrm清空,以免在#epoll阻塞期间收到信号,在epoll完成后重新设置if self._blocking_signal_threshold is not None:# clear alarm so it doesn't fire while poll is waiting for# events.signal.setitimer(signal.ITIMER_REAL, 0, 0)#进入epoll循环try:event_pairs = self._impl.poll(poll_timeout)except Exception, e:#在 epoll和 select 阻塞过程当中,经常会收到系统或者其他方式发过来的信号,这#时候系统的 errno 会被设置为 EINTR ,如果将遇到这样的情况,直接重启epoll就可以#如果不是这样的错误,则看做是致命错误# Depending on python version and IOLoop implementation,# different exception types may be thrown and there are# two ways EINTR might be signaled:# * e.errno == errno.EINTR# * e.args is like (errno.EINTR, 'Interrupted system call')if (getattr(e, 'errno', None) == errno.EINTR or(isinstance(getattr(e, 'args', None), tuple) andlen(e.args) == 2 and e.args[0] == errno.EINTR)):continueelse:raise#将被阻塞的sigalarm 还原 , 第二个参数是最大阻塞阈值if self._blocking_signal_threshold is not None:signal.setitimer(signal.ITIMER_REAL,self._blocking_signal_threshold, 0)# Pop one fd at a time from the set of pending fds and run# its handler. Since that handler may perform actions on# other file descriptors, there may be reentrant calls to# this IOLoop that update self._events#将新的事件加入到待处理队列中,现代非阻塞的网络库都使用的是这种方式self._events.update(event_pairs)#作者在写这段代码的过程当中不是使用的简单的顺序遍历这个队列,而使用的方式是#将就绪事件逐个弹出,以防止在处理过程当中就绪事件发生改变while self._events:fd, events = self._events.popitem()#在处理过程当中,常常会遇到客户端异常终止的情况#一般情况下如果读取错误,服务端会产生一个 sigpipe信号#这时候需要忽略这个信号#这里我有一个疑问就是为什么在add_handler 的时候 handler是经过 context.wrap包装过的#而在这里是直接调用,按道理应该是通过_running_callback调用,不过这里显然处理了异常情况了try:self._handlers[fd](fd, events)except (KeyboardInterrupt, SystemExit):raiseexcept (OSError, IOError), e:if e.args[0] == errno.EPIPE:# Happens when the client closes the connectionpasselse:logging.error("Exception in I/O handler for fd %d",fd, exc_info=True)except:logging.error("Exception in I/O handler for fd %d",fd, exc_info=True)# reset the stopped flag so another start/stop pair can be issuedself._stopped = False#将定时事件清空if self._blocking_signal_threshold is not None:signal.setitimer(signal.ITIMER_REAL, 0, 0)

这段代码中值得注意的部分就是在几个方面:

1.超时事件的处理,timeout是一个排序后的列表,每次都是取得最前面最小的一个

2.在开始epoll循环的过程当中,设置阻塞sigalarm

3.在处理事件过程当中忽略sigpipe信号

4.在处理就绪事件过程当中,是通过每次pop一个来处理,而不是一次遍历

stop()函数

    def stop(self):"""Stop the loop after the current event loop iteration is complete.If the event loop is not currently running, the next call to start()will return immediately.To use asynchronous methods from otherwise-synchronous code (such asunit tests), you can start and stop the event loop like this:ioloop = IOLoop()async_method(ioloop=ioloop, callback=ioloop.stop)ioloop.start()ioloop.start() will return after async_method has run its callback,whether that callback was invoked before or after ioloop.start."""self._running = Falseself._stopped = Trueself._wake()

简单的设置标志位后,向管道发送"x"停止事件循环

总结:IOLoop差不多就是这些内容,利用python简单和高可读性,看网络模块的实现会让我们更加的专注于

实现,而不是繁琐的基础代码的使用过程。

后面将看看IOStream类,是建立在IOLoop的一个上层封装,实现了基本的buffer事件

转载于:https://www.cnblogs.com/Bozh/archive/2012/07/19/2598696.html

相关文章:

参悟JavaScript

引子 编程世界里只存在两种基本元素&#xff0c;一个是数据&#xff0c;一个是代码。编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力。 数据天生就是文静的&#xff0c;总想保持自己固有的本色&#xff1b;而代码却天生活泼&#xff0c;总想改变这个世…

SQL数据库无法附加 系统表损坏修复 数据库中病毒解密恢复

SQL数据库无法附加 系统表损坏修复 数据库中病毒解密恢复 开发此工具是为了 让手工恢复数据库物理故障时 更加简单便捷直观, 本工具用于物理修复独立处理大部分问题以及与DBCC配合完成修复各种数据库错误.特别是针对大型数据库上百G 上TB数据库&#xff0c;节约大量时间精力。 …

ODP.NET调用存储需要使用事务

今天发生在用ODP.NET调整一个存储过程时发生了两个奇怪的错误。 ORA-08103: object no longer exists ora-01410: invalid rowid网上都说是索引块有错误什么的&#xff0c;我索引也重建&#xff0c;表也重建了&#xff0c;但还是不行。 奇怪的是我直接测试存储过程是有结果的。…

HDU-1698-Just a Hook

HDU-1698-Just a Hook http://acm.hdu.edu.cn/showproblem.php?pid1698 还是成段更新线段树 #include<stdio.h> #include<string.h> #include<stdlib.h> #define N 100005 struct cam {int x;int y;int sum;int val; }list[N*4]; void build(int k,int x,in…

sketchup 255个su常用插件)_SketchUp领域的知乎,有胆来问!

你知道知乎、豆瓣、果壳……但你可能不知道【问吧】这是一个 SketchUp 领域的知乎(点击文末“阅读原文”可直接进入【问吧】)你可以找到关于 SketchUp 的任何话题&#xff1a;SketchUp、Vray、建模、插件、曲面、SUAPP、组件、导入、材质、渲染、导出、贴图、材质、错误报告、L…

js简单的抽屉菜单

闲暇时间用Jquery写了一个js简单的抽屉菜单。。<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml" > <…

checkedListBox的使用

1.添加项checkedListBox1.Items.Add("蓝色"); checkedListBox1.Items.Add("红色"); checkedListBox1.Items.Add("黄色");2. 判断第i项是否选中,选中为true,否则为falseif&#xff08;checkedListBox1.GetItemChecked(i)&#xff09;{return t…

Windows Phone开发(39):漫谈关键帧动画上篇 转:http://blog.csdn.net/tcjiaan/article/details/7550506...

尽管前面介绍的几种动画会让觉得很好玩了&#xff0c;但是&#xff0c;不知道你是否发现&#xff0c;在前面说到的一系列XXXAnimation中&#xff0c;都有一个共同点&#xff0c;那就是仅仅针对两个值的目标值之间产生动画&#xff0c;如果使用By&#xff0c;将在原值和加上By后…

性能定位常用命令整理

统计每秒钟Nginx收到多少请求&#xff1a; cat access.log | grep 2019:20:19:50 | wc -l 解释&#xff1a;access.log为Nginx的日志&#xff0c;通过Nginx的配置文件nginx.conf查看日志文件名称和位置&#xff0c;2019:20:19:50 表示获取20点19分50秒接收的请求数&#xff0c;…

4块硬盘做raid几_HP-P4500存储RAID硬盘离线数据恢复案例

在这里北亚小编分享一篇关于HP-P4500存储RAID硬盘离线数据恢复案例&#xff0c;经客户描述&#xff1a;一台HP-P4500的存储系统&#xff0c;底层是12块1TB的硬盘组的RAID。其中每6个1TB的盘一组&#xff0c;第一组的前面一部分组了一个RAID01&#xff0c;是存放HP-P4500嵌入式系…

十个利用矩阵乘法解决的经典题目

出自matrix67.com 好像目前还没有这方面题目的总结。这几天连续看到四个问这类题目的人&#xff0c;今天在这里简单写一下。这里我们不介绍其它有关矩阵的知识&#xff0c;只介绍矩阵乘法和相关性质。 不要以为数学中的矩阵也是黑色屏幕上不断变化的绿色字符。在数学中&…

maven生命周期理解

你可以仅仅调用clean来清理工作目录&#xff0c;仅仅调用site来生成站点。当然你也可以直接运行 mvn clean install site 运行所有这三套生命周期。 知道了每套生命周期的大概用途和相互关系以后&#xff0c;来逐个详细看一下每套生命周期&#xff0c;Clean和Site相对比较简单&…

安装envi出现cannot find lincese_Ubuntu 16.04 安装 CUDA10.1 (解决循环登陆的问题)

0. 前言直接用 cuda安装文件同时安装 NVIDIA 驱动和 CUDA&#xff0c;没有单独安装更高版本的 NVIDIA 驱动&#xff1b;为避免浪费显存&#xff0c;图形化界面显示是在Intel 集显环境下&#xff0c;NVIDIA 独显做计算&#xff1b;循环登陆问题是因为安装时没有加 --no-opengl-l…

POJ1067_取石子游戏_威佐夫博弈

/* *State: 1067 Accepted 176K 16MS C 435B *题目大意&#xff1a; * 威佐夫博弈 *解题思路&#xff1a; * 略。 */ #include <iostream> #include <stdio.h> #include <cmath> using namespace std;int main(void) {int big,…

cuda cudnn pytorch版本对应关系

1. cuda和cudnn版本对应关系 https://developer.nvidia.com/rdp/cudnn-archive#a-collapse742-10 转载于:https://www.cnblogs.com/yeran/p/11345990.html

【转载】WinCE OAL架构分析

转载自&#xff1a;http://blog.csdn.net/nanjianhui/article/details/3830452 我个人认为OAL应该是WinCE BSP中最为重要的一个模块了&#xff0c;简单回顾一下&#xff0c;WinCE BSP由Bootloader&#xff0c;Drivers&#xff0c;OAL和配置文件组成。Bootloader一般指EBOOT&…

centos7 中搭建gitlab

1、在virtual box中新建一个虚拟机 2、gitlab ce&#xff08;community版本&#xff09;地址&#xff1a;https://about.gitlab.com/installation/#centos-7?versionce 如果在执行如下安装命令提示无法连接&#xff0c; sudo EXTERNAL_URL"http://gitlab.example.com&quo…

androidstudio jni开发_初识NDK开发(一)

“ 前言&#xff1a;初学逆向 请多多指教 昨天在看雪论坛发了篇文章&#xff0c;被标记了优秀&#xff0c;不由得感叹 这一个月没有白学&#xff01; 剩下还有11个月 冲了”学习到的内容—1、了解了什么是NDK&#xff0c;以及在android studio中的环境搭建中注意的事项2、pthre…

http编程学习(C#)

《HTTP Programming Recipes for C# Bots》 第一章 选择GET还是POST取决于传送到服务器的数据的多少。GET传送的数据少&#xff0c;POST几乎对传送的数据无限制。 It is important to note that only one physical file is transferred per HTTP request. 每次HTTP请求只传送了…

服务器远程免密登录

1. 生成本地密钥 ssh-keygen2. 将密钥上传到服务器 ssh-copy-id -p port username192.128.128.128 3. 创建登录脚本 ssh -p port username192.128.128.128 转载于:https://www.cnblogs.com/yeran/p/11348045.html

如何触发AspxGridview的PageIndexChanged 客户端事件

&#xff1f;最近在使用AspxGridview控件时&#xff0c;遇到一个问题&#xff0c;就是在触发AspxGridview分页事件之后&#xff0c;需要在执行js事件&#xff0c;找了好久&#xff0c;在官网上找到处理的办法。 就是在cs页面设置变量在触发PageIndexChanged事件后&#xff0c;改…

Mysql 多表使用 Case when then 遇到的坑

前言&#xff1a; 在做一个订单导出时&#xff0c;遇到多表都含有state这个字段&#xff0c;含有多个状态首先想到的是&#xff1a; case colume when condition then result when condition then result when condition then result else result end 当正常试着写代码时会发现…

nginx反向代理原理及配置详解

nginx概述nginx是一款自由的、开源的、高性能的HTTP服务器和反向代理服务器&#xff1b;同时也是一个IMAP、POP3、SMTP代理服务器&#xff1b;nginx可以作为一个HTTP服务器进行网站的发布处理&#xff0c;另外nginx可以作为反向代理进行负载均衡的实现。 这里主要通过三个方面简…

小鱼易连电脑版_生活多么美好 篇十六:我的桌面改造,有绿植,有小鱼,有大音箱...

原标题&#xff1a;生活多么美好 篇十六&#xff1a;我的桌面改造&#xff0c;有绿植&#xff0c;有小鱼&#xff0c;有大音箱生活多么美好 篇十六&#xff1a;我的桌面改造&#xff0c;有绿植&#xff0c;有小鱼&#xff0c;有大音箱 2020-11-06 22:13:312点赞1收藏1评论想攒一…

菜鸟初涉SQL Server的总结

看完了一遍耿建玲老师的视频&#xff0c;讲的很多&#xff0c;一些细节的东西还是很难去把控。准备总结自己觉得无从下手&#xff0c;觉得很难去把控这个宏观和细节的平衡。但如果不去做这个工作的话&#xff0c;我可能永远都不能学会怎样去做好总结。总之&#xff0c;先这样去…

extjs4.0视频教程下载

发现www.uspcat.com 学习extjs4.0不错的论坛啊 http://www.uspcat.com/portal.php 视频教程下载 http://www.uspcat.com/forum.php?modviewthread&tid197&extra 转载于:https://blog.51cto.com/3450037/687004

开源依旧:再次分享一个进销存系统

开篇 我之前发过一篇博文《两天完成一个小型工程报价系统(三层架构)》&#xff0c;不少朋友向我要源码学习&#xff0c;后来久而久之忘记回复了。今天我再分享一个进销存系统&#xff0c;只为学习&#xff0c;没有复杂的框架和设计模式&#xff0c;有的是我个人的理解&#xff…

kotlin + springboot启用elasticsearch搜索

参考自&#xff1a; http://how2j.cn/k/search-engine/search-engine-springboot/1791.html?p78908 工具版本&#xff1a; elasticsearch 6.2.2、 kibana 6.2.2&#xff0c; 下载地址&#xff1a; elasticsearch、kibana 下载demo 1、kotlin版springboot项目创建 访问https:/…

insert 语句的选择列表包含的项多于插入列表中的项_如何定义和使用Python列表(Lists)

Python中最简单的数据集合是一个列表(list)。列表是方括号内用逗号分隔的任何数据项列表。通常&#xff0c;就像使用变量一样&#xff0c;使用符号为Python列表分配名称。 如果列表中包含数字&#xff0c;则不要在其周围使用引号。 例如&#xff0c;这是测试成绩的列表&#xf…

数据结构之主席树

这里讲静态的主席树&#xff0c;关于静态区间第k小。&#xff08;有兴趣的朋友还可以去看看我写的整体二分&#xff0c;代码实现略优于主席树我觉得&#xff0c;当然静态主席树是很好写的&#xff09; 题目描述&#xff1a; 题目描述 如题&#xff0c;给定N个正整数构成的序列&…