多线程IO模型
服务端编程,首要问题是选取IO模型。即如何处理大量连接,服务更多的客户端?
我们最早有2种解法,各有不足:
1、阻塞IO,每个连接都需要一个线程。
随着连接数增多,线程数剧增,系统开销太大。
2、非阻塞IO,采用“忙轮询”的方式处理多个连接。
空闲连接很多时,太浪费CPU。
现在,业内常用方案是IO复用。
单线程处理大量连接,应用不需要“忙轮询”,内核发现“活跃连接”通知应用。所有连接都空闲时,阻塞应用线程,释放CPU。
目前,最成熟的IO复用方案是epoll,我们今天的主角。
一
epoll的3个API
如上图,epoll的核心是3个API,核心数据结构是:1个红黑树 和 1个链表
1. epoll_create()
功能:创建句柄epollfd。
内核准备数据结构:1个Map(就那个红黑树) 和 1个List(就那个链表)
2. epoll_ctl(epollfd, my_events)
功能:注册我关心的事件(fd, 可读/可写)。
内核把事件写入Map,方便快速查找。
当某个fd发生IO事件时,内核到Map中查找my_events,复制到List。
3. epoll_wait(epollfd, ready_events)
功能:返回就绪事件。
copy一份List返回。
二
2类fd与3件事
服务端支持多连接,标识连接的fd分为2类:
1. listenfd
一般情况,只有一个。用来监听一个特定的端口(如80)。
2. connfd
每个连接都有一个connfd。用来收发数据。
针对这2种fd,服务端主要做3件事,如下图:
1. accept listenfd,创建一个connfd
2. 读/写 connfd
应用/内核间copy数据。
每个connfd对应着2个应用缓冲区:readbuf、writebuf
3. 处理 connfd发来的数据
业务逻辑处理,准备response到 writebuf。
三
单线程下使用epoll
把上文提到的:3个API、2种fd、3件事,揉到一块,用伪码表示。
注:下面的代码,在手机上建议横屏阅读。
四
多线程下的IO模型
我们听过很多多线程IO模型:Reactor、Proactor、领导者/追随者balabala...
太多了,傻傻分不清楚。
从上文,我们知道,服务端IO编程主要处理3件事,我们给这3件事编号:1、2 和 3。
不管单线程,还是多线程,核心都是做这3件事。
各种多线程IO模型的区别就是:这3件事交给哪些线程做了。
按照这个规则,我们把常见的多线程IO模型,整理到一棵“决策树”上。
希望能帮助大家记忆。
1. redis模式
处理:单线程独自干3件事。
类比:饭馆,夫妻店。
老板自己当服务员,把所有的活都干了(接待、点菜、上菜等)。
2. nginx模式
处理:开启8个工作进程,各自独立。
新连接来了,大家一起抢,谁抢到算谁的(这是第1件事,每个进程都调用accept,但只有一个能成功,得到connfd)。
抢到之后(得到connfd),各进程独自干剩下的2件事(读写connfd、业务处理)。
类比:小饭馆。
雇了8个服务员。
新客人一进门,8个服务员一拥而上,谁抢到算谁的。
抢到之后,独自服务该客人。
惊群效应:新客人一进门,8个服务员都被唤醒,注定只有1个能抢到,浪费7个服务员的注意力。
3. 线程分角色
处理:3件事分配给不同的线程。
线程间需要通信,分配任务。
类比:大饭馆。
门口专门站一个“大服务员”(主线程),负责排号。
客人到号了,“大服务员”指派一个专门的“小服务员”,接待客人。
大厅里有一群“小服务员”(工作线程),负责接待客人到餐桌。
“小服务员”还可以再拆分工作(拆出业务线程),领路、点菜、上菜、收钱可以交给不同的“小服务员”做。
4. 领导者/追随者
处理:线程的角色在3种状态间变换,每种角色职责不同。
事件集和数据是公用的,线程间不需要通信。
任一瞬间,最多只有一个Leader线程,负责响应新事件。
Leader:获取事件后,变成Processing,处理、读写数据。
同时指定一个Follower接替自己。
Processing:完成业务处理后,如果没有Leader,自己成为Leader;
如果有Leader,自己成为Follower。
Follower:等待被指派为Leader。
类比:机场出租车。
出租车排了个长队。
队首的出租车,是Leader:响应新乘客。
后面排队的出租车,是Follower:等待成为Leader。
乘客上车后,Leader出租车转为Processing:服务乘客。
转自:http://www.360doc.com/content/17/0807/14/33093582_677312246.shtml
多线程IO模型的更多相关文章
- 高并发之网络IO模型
你好,我是坤哥 今天我们聊一下高并发下的网络 IO 模型 高并发即我们所说的 C10K(一个 server 服务 1w 个 client),C10M,写出高并发的程序相信是每个后端程序员的追求,高并发 ...
- Python并发编程二(多线程、协程、IO模型)
1.python并发编程之多线程(理论) 1.1线程概念 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程(流水线的工作需要电源,电源就相当于 ...
- python笔记9 线程进程 threading多线程模块 GIL锁 multiprocessing多进程模块 同步锁Lock 队列queue IO模型
线程与进程 进程 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需要 ...
- 高性能IO模型浅析
高性能IO模型浅析 服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(Blocking IO):即传统的IO模型. (2)同步非阻塞IO(Non-blocking ...
- 操作系统IO模型
操作系统IO模型 声明:如下内容是根据APUE和mycat两本著作中关于I/O模式的一些内容加上自己的一些理解整理而成,仅供学习使用. 本节内容 UNIX下可用的五种I/O模型 三种I/O模型 Rea ...
- 同步异步,阻塞非阻塞 和nginx的IO模型
同步与异步 同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication).所谓同步,就是在发出一个*调用*时,在没有得 ...
- 几种服务器端IO模型的简单介绍及实现
一些概念: 同步和异步 同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发I/O操作并等待或者轮询的去查看I/O操作是否就绪,而异步是指用户进程触发I/O操作以后便开始做自己的事情,而 ...
- 服务器端高性能的IO模型 转自酷勤网
服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种: (1)同步阻塞IO(BlockingIO):即传统的IO模型. (2)同步非阻塞IO(Non-blockingIO):默认创建的soc ...
- 网络IO模型:同步IO和异步IO,阻塞IO和非阻塞IO
同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞(non-blocking)IO分别是什么,到底有什么区别?这个问题其实不同的人给出 ...
随机推荐
- MySql 利用函数 查询所有子节点
前提:mysql 函数 find_in_set(str,strlist), cast(value as type) 一.find_in_set(str,strlist):如果字符串str是在的 ...
- 2015/8/29 Python基础(3):数值
数字提供了标量储存和直接访问,是不可更改类型,每次变更数值会产生新的对象.Python支持多种数字类型,包括整型.长整型.布尔型.双精度浮点.十进制浮点和复数.在Python中,变量并不是一个盒子,而 ...
- 2015/8/18 Python基本使用(2)
关于判断和循环语句 Python的判断和循环语句非常直观,读起来很接近自然语言. 判断语句if标准的if语句是如下结构: if expression: if_suite 如果expression的表达 ...
- C11简洁之道:lambda表达式
1. 定义 lambda表达式是C++11非常重要也是很常用的特性之一,来源于函数式编程的概念,也是现代编程语言的一个特点.它有如下特点: 声明式编程风格:就地匿名定义目标函数或者函数,不需要额外写 ...
- 用python爬校花网
import requests import re import hashlib,time def get_index(url): response=requests.get(url) if resp ...
- Bzoj4870 [SXOI2017]组合数问题
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 155 Solved: 78 Description Input 第一行有四个整数 n, p, k, ...
- 洛谷金秋夏令营模拟赛 第2场 T11738 伪神
调了一个下午只有八十分QAQ md弃了不管了 对拍也没拍出来 鬼知道是什么数据把我卡了QAQ 没事我只是个SB而已 这题其实还是蛮正常的 做法其实很简单 根据链剖的构造方法 你每次修改都是一段又一段的 ...
- HDU 1205 吃糖果 (数学)
题目链接 Problem Description HOHO,终于从Speakless手上赢走了所有的糖果,是Gardon吃糖果时有个特殊的癖好,就是不喜欢将一样的糖果放在一起吃,喜欢先吃一种,下一次吃 ...
- 如何用js自己实现Animate运动函数
js运动是我们学习js必不可少的研究部分,首先我们要知道js的运动其实仅仅是不断改变元素的某个属性值而已,比如不断改变一个绝对定位div的left值,那么你看到的效果就是这个div不断的向右边运动,那 ...
- Win10默认浏览器怎么设置
1.首先在Win10桌面左下角的开始菜单图标上右键单击鼠标,在弹出的菜单选项中,点击进入“控制面板”,如下图所示. 接下来就可以找到“默认程序”设置了,找到后点击进入设置,如下图所示. 打开Win10 ...