关于IO的同步,异步,阻塞,非阻塞

上次写了一篇文章:Unix IO 模型学习。恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现。中途正好讨论了网络IO的同步、异步、阻塞、非阻塞的概念,当时讲下来,大家的理解各不相同,各执己见。搜索了网络上的一些文章,观点也各不相同,甚至连wiki也将异步和非阻塞当成一个概念在解释。

虽然网络上充斥了大量关于同步、异步、阻塞、非阻塞的文章,但大都是抄来抄去,没有一个权威的说法。但我找到了这一篇文章,该文章引用了《UNIX网络编程 卷1》的介绍,这本书的作者是Richard Stevens。如果有Richard Stevens在这方面的定义或者结论,那么我想,这应该是比较有说服力的了。

关于《UNIX网络编程 卷1》这本书,我特意找了英文原版,也共享出来了:大家可以下载《UNIX网络编程 卷1》的英文原版(CHM格式)。

我看了6.2这节内容,这节内容就是讲IO模型的。刚刚提到的那篇文章,几乎就是翻译这个6.2节的。应该说,这个6.2节,对同步和异步的讲解,算是很清楚的。

下面是我自己理解的重点。

IO模型

目前unix存在五种IO模型(这也和上一篇文章:Unix IO 模型 中提到的一致),分别是:

  • 阻塞型 IO(blocking I/O)
  • 非阻塞性IO(nonblocking I/O)
  • IO多路复用(I/O multiplexing)
  • 信号驱动IO(signal driven I/O)
  • 异步IO(asynchronous I/O)

IO的两个阶段

  1. 等待数据准备好
  2. 将数据从内核缓冲区复制到用户进程缓冲区

同步,异步的区别

那么究竟什么是同步和异步的区别呢?请重点读一下原文6.2节中的信号驱动IO和异步IO中的比较。最后总结出来是:

  • 同步IO,需要用户进程主动将存放在内核缓冲区中的数据拷贝到用户进程中。
  • 异步IO,内核会自动将数据从内核缓冲区拷贝到用户缓冲区,然后再通知用户。

这样,同步和异步的概念就非常明显了。以上的五种IO模型,前面四种都是同步的,只有第五种IO模型才是异步的IO。

阻塞和非阻塞

那么阻塞和非阻塞呢?注意到以上五个模型。阻塞IO,非阻塞IO,只是上面的五个模型中的两个。阻塞,非阻塞,是针对单个进程而言的。

当对多路复用IO进行调用时,比如使用poll。需注意的是,poll是系统调用,当调用poll的时候,其实已经是陷入了内核,是内核线程在跑了。因此对于调用poll的用户进程来讲,此时是阻塞的。

因为poll的底层实现,是去扫描每个文件描述符(fd),而如果要对感兴趣的fd进行扫描,那么只能将每个描述符设置成非阻塞的形式(对于用户进程来讲,设置fd是阻塞还是非阻塞,可以使用系统调用fcntl),这样才有可能进行扫描。如果扫描当中,发现有可读(如果可读是用户感兴趣的)的fd,那么select就在用户进程层面就会返回,并且告知用户进程哪些fd是可读的。

这时候,用户进程仍然需要使用read的系统调用,将fd的数据,从内核缓冲区拷贝到用户进程缓冲区(这也是poll为同步IO的原因)。

那么此时的read是阻塞还是非阻塞呢?这就要看fd的状态了,如果fd被设置成了非阻塞,那么此时的read就是非阻塞的;如果fd被设置成了阻塞,那么此时的read就是阻塞的。

不过程序已经执行到了这时候,不管fd是阻塞还是非阻塞,都没有任何区别,因为之前的poll,就是知道有数据准备好了才返回的,也就是说内核缓冲区已经有了数据,此时进行read,是肯定能够将数据拷贝到用户进程缓冲区的。

但如果换种想法,如果poll是因为超时返回的,而我们又对一个fd(此fd是被poll轮询过的)进行read调用,那么此时是阻塞还是非阻塞,就非常有意义了,对吧!

结论

  1. 判断IO是同步还是异步,是看谁主动将数据拷贝到用户进程。
  2. select或者poll,epoll,是同步调用,进行此调用的用户进程也处于阻塞状态。
  3. javaScript或者nodejs中的读取网络(文件)数据,然后提供回调函数进行处理,是异步IO。
Posted in Java, NIO | Tagged , , , , , | 10 Comments

apache httpd worker模式工作原理及配置

httpd在linux下默认使用prefork, 我们网站的服务器,在编译httpd的时候,就指定了使用worker模式。

简单了解 worker模式与 prefork模式

worker : httpd在启动的时候,会由root进程派生出几个子进程,每个子进程中会有固定数量的线程,到时候提供服务的,就是这些线程,也就是说一个进程能够同时提供多次服务。

prefork : httpd使用进程来提供服务,每个进程在同一时间提供一次服务。

worker 参数配置

由于我比较关注 worker 模式, 所以就特别关注了一下 worker 的一些参数配置。

worker的参数主要有:ServerLimit,ThreadLimit,StartServers,MinSpareThreads,
MaxSpareThreads,ThreadsPerChild,MaxClients,MaxRequestsPerChild。

  • ServerLimit 是设置httpd root进程能够产生的最大进程数限制
  • ThreadLimit 是设置每个httpd子进程能够产生的最大服务线程限制
  • StarServers 是httpd刚启动时,root进程创建的子进程数
  • MinSpareThreads 顾名思义,就是最少的空闲线程数
  • MaxSpareThreads 就是最多的空闲线程数
  • ThreadsPerChild 每个子进程产生的线程数
  • MaxClients httpd同时处理的最大请求数
  • MaxRequestsPerChild 每个子进程提供的请求服务数,如果达到该值,则该子进程结束,由root进程根据需要再次派生新的子进程

其中几个参数之间的联系还是很重要的:

  • ServerLimit 限制了 MaxClients 和 ThreadsPerChild。 因为 MaxClients / ThreadsPerChild = 子进程数, 而子进程数目是受限于 ServerLimit
  • MaxSpareThreads 需要 大于等于 MinSpareThreads + ThreadsPerChild 。 根据我的理解,这也是合理的,因为子进程产生时,线程的数目已经是固定的了,那就需要 [ MinSpareThreads, MaxSpareThreads ] 中有一个线程数对ThreadsPerChild取余能够为0。
下面看看 worker模式下这些参数的默认配置值 :
<IfModule worker.c>
     ServerLimit      16
     ThreadLimit     64
     StartServers     3
     MinSpareThreads  75
     MaxSpareThreads  250
     MaxClients       400  # 16 * 25
     ThreadsPerChild  25
     MaxRequestsPerChild   10000
</IfModule>
Posted in httpd | Tagged , , , | Leave a comment

百度发布SEO指南

Google的搜索引擎优化指南出来将近两年的时候,百度官方也给出了他自己的搜索引擎优化指南

把指南下下来之后,粗略的看了一下,大概是讲了四点,核心思想还是围绕用户体验中心的:

  1. 域名的注册,服务器的租用
    域名简短,让用户很容易记住;服务器这方面,就是对用户的响应速度。
  2. 网站要让用户看懂,也要让搜索引擎看懂
    包括对HTML元标签的使用, 还有尽量少用Flash和JS等搜索引擎还不太懂的东东。
  3. 网站运营的优化
    增强品牌化,增加用户的信任,注重用户体验。
  4. 搜索引擎惩罚
    惩罚不是目的,但是谁影响了搜索引擎对用户的体验,谁就会受到不同程度的惩罚。

对于这四点,大家也都是很清楚的。但最后的FAQ却引起了我的兴趣:

  1. 自然排序和搜索排序是两个不同的部门
    想想也应该是这样子,而且作为一家大公司来讲,追求的应该是长期可持续发展的收入,而不是杀鸡取卵。
  2. 更换空间需要保留旧空间一段时间
    我个人觉得很有必要,而且很有可能baiduSpider会把域名DNS自己做缓存,所以需要保留旧空间一段时间,也是很有道理的。
  3. 百度是支持nofollow的
    这是肯定的,就算现在支持不好,以后也肯定是这个趋势。不过这个问题应该难不倒百度的工程师。
  4. 百度对Https协议的支持很有限
    可以公开的内容就公开吧。
  5. site语法原本就不是查网站收录数的
  6. title和description原则不要做太大的修改
  7. URL尽量静态化
    人性化的URL也是用户体验的一种表现,友好的URL甚至可以让用户直接输入URL来网站的内容。
  8. 国外空间对于排名没有影响
    关键是访问速度和响应时间。

以上就是我看了百度官方的搜索引擎优化指南的一些内容,其实说起来,大家都了解了,只不过是官方发出来的,自然就更坚定了大家的想法。

Posted in SEO | Tagged , | 2 Comments

Unix IO模型学习

这季度学习java nio及其相关的内容和框架,所以就想先看看Unix下的一些IO模型。结合网络上的资料进行学习,自己也写篇日志,加强一下理解吧。

POSIX中对同步IO和异步IO的规定

  • 同步IO操作:引起进程的阻塞直到IO操作完成
  • 异步IO操作:IO操作不会引起进程阻塞

在UNIX下,有5中操作模型

  1. 阻塞IO
  2. 非阻塞IO
  3. IO复用
  4. 信号驱动IO
  5. 异步IO

按照网络上的说法,前四种是属于同步IO,第五种才属于异步IO,对于这个结论,我的理解是根据用户进程是否阻塞来判断的(而不是内核进程)。关于同步和异步的一些讨论,可以参考http://bbs.chinaunix.net/viewthread.php?tid=947563

阻塞IO

这是我们熟悉的IO模型,一个进程在作IO操作时,非要等到数据从内核空间拷贝到用户进程空间,才会返回。这个模型的优点就是简单,而且在阻塞的时候,CPU还可以进行调度,去执行别的进程。

非阻塞IO

一开始我看是非阻塞IO,觉得应该要比阻塞IO模型先进,可是当我一看使用方法的时候,就知道这个模型是不会被实际使用的,仅仅只能作为理论上存在的IO模型。这个模型的观点是:进行IO操作的时候,不阻塞,如果没有数据准备好,就直接返回错误码(或者是别的代码)。因此,使用者就只能不断进行轮询来调用IO函数。这样的后果就是,不仅在宏观上形成了与阻塞IO一共的“阻塞”效果,而且在微观上,CPU一直被用来轮询,造成了CPU的浪费。所以,这个模型还不如阻塞IO模型实用。

IO复用

对于IO复用,我的理解有三点:

  1. 在一次系统调用中,实现了询问多个描述符的IO准备情况 —— 根据事件通知
  2. 为了实现第一点,就需要把阻塞的地方进行转移。把一次系统调用,分为两次系统调用。第一次系统调用可以询问多个描述符的IO准备情况,在这个地方进行阻塞;而第二次系统调用,是针对已经准备好IO的描述符进行调用,此时,理论上(按照我的理解),也是会发生阻塞的,只不过是此时内核已经把数据准备好了,阻塞的时间可以忽略不计罢了。
  3. 本质上,还是阻塞的。

信号IO

我们都知道,信号是UNIX提供了进程间进行通信的一种方式。我们常用的 kill -9 命令(kill是向进程传递信号量,9只是众多信号中的一个代号),或者是 Ctrl + C 的时候,就是向某个进程发出终止的信号,这样进程就退出了。

而对于信号IO的模型,我是这么理解的:进程在发起IO操作,系统调用之后,直接访问,内核会在IO数据准备好之后,以某个信号通知发起IO操作的进程,从而使得该进程的信号处理函数可以读取IO数据的操作。

本质上,这也是阻塞的IO模型,因为在信号处理函数中,同样也是要进行阻塞的,只是在在这个时候发起系统系统,内核已经把数据准备好了。

异步IO

这是真正的异步IO了。实现的机制是:用户在发起异步IO的系统调用时,会把相应的数据处理函数作为回调函数,等到IO数据准备好,内核会主动调用此回调函数。可以看出,用户进程在这种模型下,只调用了一次系统调用,而且是立即返回的,因此,就不会出现让进程阻塞的情况,也就符合了POSIX中异步IO的定义。

其实我理解起来,思路是和信号IO差不多的,唯一不同的地方,对于IO数据的操作,异步IO是由内核主动发起的,而信号IO是由用户进程发起的。

以上是我结合网络资料,对UNIX IO模型的一些学习和理解,如果有错误或者不当的地方,请随时留言指出,谢谢!

Posted in NIO | Tagged , , , , | 2 Comments

杭州收音电台频道

我喜欢听收音机,买了收音机也有一年了,之前一直听的是FM97.9中央人民广播电台经济之声,虽然这个频道的质量很高,比如《冬吴相对论》。但令我郁闷的是,每次周末的下午,中央人民广播经济之声都会放导航仪的广告……

为了在适当的时间收听到适当的电台,我收集了杭州收音各个电台的频道,这里就先放出来(后续如果有可能的话,我会推荐在什么时段听什么频道最合适)!

  • FM88.0 浙江电台新闻综合
  • FM89.0 杭州电台新闻综合 (AM954)
  • FM90.2 中央人民广播电台中国之声
  • FM93.0 浙江电台交通之声
  • FM95.0 浙江电台经济台
  • FM96.8 浙江电台音乐调频
  • FM97.4 浙江电台新闻综合 (AM540/810)
  • FM97.9 中央人民广播电台经济之声
  • FM99.6 浙江电台文艺频率
  • FM102.1 余杭电台
  • FM103.2 杭州电台音乐台
  • FM104.5 浙江电台旅游之声 (AM603/1521)
  • FM105.4 杭州电台西湖之声
  • FM107.0 浙江电台城市之声 (AM1530)
  • FM107.9 萧山电台

以上就是在杭州你能收听到的电台,如果有什么错误,或者有新的电台,也欢迎留言补充 :-)

Posted in life | Tagged , | Leave a comment