进程通过内核缓存区请求设备I/O的一些事情
- 请求进程,内核缓存区,设备I/O
请求进程无法直接访问设备I/O,而是通过内核缓冲区提交请求数据,等数据就绪后,数据从设备缓冲区提交至进程空间
请求进程把数据提交给内核缓存空间需要等待,内核把数据复制给设备I/O,直到数据就绪,还需要等待,这些等待过程大致可以分为五种模式
- blocking I/O----阻塞式I/O
- NON blocking I/O----非阻塞式I/O
- I/O multiplexing----I/O多路复用
- 信号驱动I/O
- 异步I/O
一个进程要处理两个I/O就必须复用,负责完成不了处理,一个进程处理两个链接,处理多个文件描述符,处理多个请求;一个进程处理一个请求时也得需要I/O多路复用,因为可能涉及本地交互式输入(本地磁盘I/O),
网络交互式输入(网络I/O)
所谓阻塞:任务完成前只能等待
非阻塞:任务完成前,可以接着干别的事情
异步非阻塞(上图)数据从设备I/O复制到内核缓存的过程中,请求处于非阻塞状态,不断轮询内核缓存空间数据是否就绪,实际上降低了性能,尚不如同步阻塞I/O
所谓异步同步指的是对结果是否就绪的了解程度-----等待请求直到就绪谓之同步(一直监控并等待请求结果就绪;也称之闲等),不知道何时就绪,不断轮询是否就绪谓之异步(忙等)
- 异步阻塞
从设备I/O复制数据到内核缓存阶段是阻塞的(我们姑且谓之数据准备阶段),从内核缓存复制数据到用户进程空间也是阻塞的(我们姑且谓之数据复制阶段),之所以谓之异步。是因为准备阶段结束后,我们可选
择阻塞等待数据进入复制阶段,或者干脆待会儿再说,先去处理别的请求。
- 事件驱动I/O
在数据准备阶段,数据就绪后,向进程发起通知,获取数据,隔一段通知一次----谓之水平触发。只进行一次通知,谓之边缘触发,显然边缘触发性能更优。这种通知其实是一种回调机制。(回调类似于留了个联系方式)
;本质是一种I/O复用---event driven I/O事件驱动I/O。
数据就绪后,无需切换线程 epoll /dev/poll kqueue 这三种模型专司事件驱动I/O的处理。
这类I/O的工作特点是,一个线程,内部维持多个连接(每个连接可以独立请求),一旦其中某个就绪,会发生阻塞,把数据从内核缓存复制回进程空间。
一种更高效的机制是:设备I/O把数据映射到内核缓存空间,省略了数据复制的工作----这类机制称之为内存映射机制!(MMAP)
- 异步I/O
工作特点:数据准备和数据复制阶段都不阻塞。通过回调机制,当数据完成从内核缓存到进程空间的复制后,通知请求进程,nginx支持磁盘异步I/O(而不是网络I/O,一次典型的请求包含网络I/O和磁盘I/O),真正的
异步实现起来相当复杂,nginx支持了AIO(异步I/O,MMAP,事件驱动
nginx不依赖于一个线程响应一个请求,取而代之的是事件驱动(和异步)的架构,这样一来他处理的并发连接数非常可观。
nginx比起Apache:
Apache
mpm
prefork 一个进程处理一个请求最多1024
worker一个线程响应一个请求,一个进程多个线程,多进程,在linux规范下,其实比起prefork,仅仅是降低了线程切换的开销
event基于事件驱动
Apache的特性是大而全,功能丰富,但基于事件驱动方面性能逊于nginx。
nginx最常见的功能还是反向代理,基于事件驱动的特性(一个线程处理多个请求,一旦挂掉,全都玩儿完),而基于进程的响应则稳定的多,把Apache作为webserver
- 信号I/O
数据复制阶段完成后向进程发起通知
- I/O多路复用
- 一个典型的网站架构
如果是论坛一类的网站,还可以添加文件上传服务器,上传类型只允许文件,例如ftp服务器上传文件,web服务器下载文件
静态文件服务器响应一般很快,动态内容则不然,以一个4G内存,2颗CPU的主机为例,响应1000个左右动态请求,静态每秒响应5000个5-10K大小的图片,这种性能取决于带宽和磁盘I/O;
所以,为了加快响应请求,可以把不曾修改的内容存为缓存,并添加缓存服务器,可以过滤掉一部分请求,缓存没有的,转发到后台服务器。假如有5万个并发访问,处理每个访问用2秒......那么一天下来可处理的请求十分可观(可能达到20亿个)一天=86400秒,当然这只是理论计算,带宽的实际性能才是观念。
尽管如此,后台MYSQL服务器仍旧繁忙。
- 架构中的mysql服务器
通常,针对mysql的请求中,读-写的比例达到5:1到10:,在不使用连接池的情况下,mysql服务器大概能处理2000个请求,实际上到了1000个左右的请求,性能就开始大幅下降,因为不同于web请求,一个类似于
select * from的操作就会请求大量的数据;如果读的需求很大,尤其是并发访问,导致大量的磁盘I/O,mysql带有缓存机制,但是缓存机制的特点是不断的分配内存,回收内存带来的开销十分浩繁,mysql服务器
既要响应读请求,又要管理缓存,依旧压力山大。所以除了增加mysql读服务器,分担读的请求以外,还应该部署一台主机用于执行负载均衡算法,分担读压力;除此以外,对于热门查询,还可以在应用程序服务器后方
memocache等nosql数据库缓存查询结果
对于php这样的程序语言,在4.0以后会编译成opcode,所以常用命令可以通过xcache缓存到应用程序服务器,memocache不能共享缓存数据,也有一种思路是用PHP的fastcgi实现一个服务器
静态内容----静态服务器
动态-----缓存服务器诸如varnish,varnish通过lvs服务器把请求分摊到应用服务器上
- 架构中对于动态服务的解决方案
假设每个应用服务器可以处理500个请求,那么这个架构理论上最多可以处理2000并发,假设有10000并发请求,且varnish缓存命中率很低,那么可以在负载均衡服务器(LVS)前添加队列服务器,队列服务器可以接收
这10000个请求,并且把其中2000个分发给应用程序服务器,等待空闲时机,在分发剩下的请求,这类队列服务器有些响亮的名字例如 RabbitMq,ZeroMq
- 架构中对于静态内容的解决方案
以淘宝为例,每天商家上传的图片可能多达几十G,因此数据的膨胀显而易见,对于这些图片的请求也并非易事,例如在几百G的硬盘中去查找一个几十K的图片,解决方案是增加静态文件服务器,并且对请求频繁的数据设
置缓存----也就是用varnish服务器缓存静态文件,然后用LVS服务器负载均衡分摊请求到静态文件服务器
尽管如此,在淘宝抢购的业务场景下,这一体系仍面临考验,所以提高缓存命中率是重中之重,缓存本质就是静态文件,这样我们就可以沿用地理法则,根据用户的地理位置,启用智能DNS解析,在每一个大区(华北,华东,华南,中原,西部......)家门口建立varnish集群,分担访问压力;另外mysql服务器分区方案也要足够完善,据说抢购时mysql每秒处理5万个事务(2013年前后数据),事务其实是一种写操作,显然,单纯依赖mysql已经不行了,因为抢购行为涉及到对库存数量的实时更新,操作都发生在工作在内存的nosql上---这一架构即构成了CDN
redis的计数器在这种场景下,较为常用。既支持快速响应又支持持久化。
- 日志分析
面对这样一个复杂的架构,对用户行为进行分析就用到了日志,不妨把日志存入到一个独立的mysql服务器当中,当然这个服务器的磁盘I/O能力要足够好,,然后定期的把日志数据导出到NFS(文件共享)服务器集群,
运行一个并行程序加以处理,分析,我们就不难得出和web请求相关的数据,例如用户访问量,某种商品的销售情况,不一而足,例如淘宝这样的网站一天产生的数据可能多达上百G,所以就用到了Hadoop并行处理平台,
Hadoop依赖于两部式异步,性能受限于短板(处理耗时较长的那个文件),所以对于实时数据分析并不好,日志这种非结构化数据,最后的归宿是文件系统,并进行全量提取分析(用并行处理平台),实时的读写,就用
nosql
- 对架构本身的总结
这样的架构,导致了主机的增多,把系统直接建立在物理硬件上不一定总是合理的。还有一个方案是把所有的主机进行集群,搭建一个云平台。在上面按照职责建立多个虚拟机,这样利用一些备份机制,即使物理及其出现
问题,也能在最短时间内得到解决
对于建立在物理机上的系统,即使出了问题,也能通过软件手段把文件系统迁移到运行良好的主机上
对于虚拟机,势必用到共享存储,并利用存储监控平台,在虚拟机启动时,分配存储资源(虚拟磁盘)
Hadoop别放在虚拟机上,因为虚拟机的I/O能力无法满足,当然对于一个页面的读取,尽可以放在虚拟机上
云服务:ias pas sas mysql可以作为sas
进程通过内核缓存区请求设备I/O的一些事情的更多相关文章
- 在内核中异步请求设备固件firmware的测试代码
在内核中异步请求设备固件firmware的测试代码 static void ghost_load_firmware_callback(const struct firmware *fw, void * ...
- 一个fork的面试题——fork + 缓存区
update : 20140512 题目:请问下面的程序一共输出多少个“-”? #include <stdio.h> #include <sys/types.h> #inclu ...
- 文件分片 浏览器文件大小限制 自定义请求头 在一个资源的加载进度停止之后被触发 arrayBuffer 异步 二进制数据缓存区
js 整数限制 浏览器文件大小限制 https://w3c.github.io/FileAPI/#dom-blob-arraybuffer https://developer.mozilla.org/ ...
- Linux内核入门到放弃-设备驱动程序-《深入Linux内核架构》笔记
I/O体系结构 总线系统 PCI(Peripheral Component Interconnect) ISA(Industrial Standard Architecture) SBus IEEE1 ...
- 笔记:Spring Cloud Hystrix 异常处理、缓存和请求合并
异常处理 在 HystrixCommand 实现的run方法中抛出异常,除了 HystrixBadRequestException之外,其他异常均会被Hystrix 认为命令执行失败并触发服务降级处理 ...
- Service Worker 离线无法缓存Post请求的问题解决
许多非REST API甚至可以用于读取数据的POST请求:典型的例子是graphql.soap和其他rpcpapi.但是,Post请求不能在一个现成的渐进式Web应用程序中缓存和脱机使用.浏览器的缓存 ...
- 关于cin的缓存区影响效果
1. 当缓冲区中有残留数据时,cin函数会直接去读取这些残留数据而不会请求键盘输入.而且,回车符也会被存入输入缓冲区中. int num{}; while(cin>>num) cout&l ...
- Java: 扩大字节缓存区的大小,提升AIO的处理性能(并发性能)
前些日了,对AIO与NIO的并发性能进行了比较,在低并发的情况下,NIO性能表现比AIO好一些,主要原因是,NIO中可以使用FileChannel.transferTo(long position, ...
- 带标准IO带缓存区和非标准IO 遇到fork是的情况分析
废话不多说 直接代码 #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include< ...
随机推荐
- Information retrieval (IR class1)
1. 什么是IR? IR与数据库的区别? 答:数据库是检索结构化的数据,例如关系数据库:而信息检索是检索非结构化/半结构化的数据,例如:一系列的文本.信息检索是属于NLP(自然语言处理)里面最实用的一 ...
- redis数据库安装
一. 简单介绍: REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统. Redis是一个开源的使用A ...
- kafka producer partitions分区器(七)
消息在经过拦截器.序列化后,就需要确定它发往哪个分区,如果在ProducerRecord中指定了partition字段,那么就不再需要partitioner分区器进行分区了,如果没有指定,那么会根据k ...
- Kubernetes---Service(SVC)服务
⒈介绍 kubernetes 通过标签选择的方式来匹配一组pod,然后提供对外访问的一种机制 一组pod可以对应到多个svc的 每一个service(svc)都可以理解为一个微服务 Service有且 ...
- vue开发中利用正则限制input框的输入(手机号、非0开头的正整数等)
我们在前端开发中经常会碰到类似手机号输入获取验证码的情况,通常情况下手机号的输入需要只能输入11位的整数数字.并且需要过滤掉一些明显不符合手机号格式的输入,那么我们就需要用户在输入的时候就控制可以输入 ...
- Apache开启.htaccess 支持
(1) <Directory "${SRVROOT}/htdocs"> # # Possible values for the Options directive ar ...
- Web API 自动生成接口文档
1.添加NuGet程序包 Microsoft ASP.NET Web API 2.2 Help Page (这是微软官方的) A Simple Test Client for ASP.NET ...
- javaIO——PushbackReader
1. 注释解释: A character-stream reader that allows characters to be pushed back into the stream. 一个允许字符被 ...
- 小程序点击图片,png转jpg,再预览方法
//页面数据初始化添加参数:isSignCanvassShow //通过canvas将图片转为jpg,使图片生成白色底便于查看预览 //list为原图片数组列表,index表示当前图片下标, //im ...
- js中的函数提升和变量提升
变量提升和函数提升: 就是将变量声明或者函数全部代码提升到当前作用域(全局作用域或函数作用域)最开始的部分. JavaScript中函数域为最小域范围:for循环.while循环.if语句.switc ...