我刚毕业那会儿,国家还是包分配工作的, 我的死党小明被分配到了一个叫数据库的大城市,天天都可以坐在高端大气上档次的机房里, 在那里专门执行SQL查询优化 , 工作稳定又舒适;

隔壁宿舍的小白被送到了编译器镇,在那里专门把C源文件编译成EXE程序, 虽然累,但是技术含量非常高, 工资高,假期多。

我成绩不太好,典型的差生,四级补考了两次才过, 被发配到了一个不知道什么名字的村庄,据说要处理什么HTTP请求, 这个村庄其实就是一个破旧的电脑, 令我欣慰的是可以上网,时不时能和死党们通个信什么的。

不过辅导员说了, 我们都有光明的前途。

1

Http Server 1.0

HTTP是个新鲜的事物, 能够激起我一点点工作的兴趣, 不至于沉沦下去。

一上班,操作系统老大扔给我一大堆文档: “这是HTTP协议, 两天看完!”

我这样的英文水平,  这几十页的英文HTTP协议我不吃不喝不睡两天也看不完, 死猪不怕开水烫,慢慢磨吧。

两个星期以后, 我终于大概明白了这HTTP是怎么回事: 无非是有些电脑上的浏览器向我这个破电脑发送一个预先定义好的文本(Http request), 然后我这边处理一下(通常是从硬盘上取一个后缀名是html的文件), 然后再把这个文件通过文本方式发回去(http response), 就这么简单。

唯一麻烦的实现, 我得请操作系统给我建立Http层下面的TCP连接通道,  因为所有的文本数据都得通过这些TCP通道接收和发送, 这个通道是用socket建立的。

弄明白了原理,我很快就搞出了第一版程序, 这个程序长这个样子:

(码农翻身注: 详情参加文章《张大胖的socket》)

看看, 这些socket, bind, listen , accept... 都是操作系统老大提供的接口, 我能做的也就是把他们组装起来: 先在80端口监听, 然后进入无限循环,如果有连接请求来了,就接受(accept),创建新的socket,  最后才可以通过这个socket来接收,发送http数据。

老大给我的程序起了个名称, Http Server, 版本1.0 。

这个名字听起来挺高端的, 我喜欢。

我兴冲冲的拿来实验,  程序启动了, 在80端口“蹲守”, 过了一会儿就有连接请求了, 赶紧Accept ,建立新的socket,     成功 !  接下来就需要从socket 中读取Http Request了。

可是这个receive 调用好慢, 我足足等了100毫秒还没有响应 !   我被阻塞(block)住了!

操作系统老大说: “别急啊, 我也在等着从网卡那里读数据,读完以后就会复制给你。 ”

我乐的清闲, 可以休息一下。

可是操作系统老大说:“别介啊, 后边还有很多浏览器要发起连接, 你不能在这儿歇着啊。”

我说不歇着怎么办?  receive调用在你这里阻塞着, 我除了加入阻塞队列, 让出CPU让别人用还能干什么?

老大说: “唉, 大学里没听说过多进程吗?  你现在很明显是单进程, 一旦阻塞就完蛋了, 想办法用下多进程,  每个进程处理一个请求!  ”

老大教训的是, 我忘了多进程并发编程了。

2

Http 2.0 :多进程

多进程的思路非常简单,当accept连接以后,对于这个新的socket ,  不在主进程里处理, 而是新创建子进程来接管。 这样主进程就不会阻塞在receive 上, 可以继续接受新的连接了。

我改写了代码, 把Http server 升级为V2.0,   这次运行顺畅了很多, 能并发的处理很多连接了。

这个时候Web 刚刚兴起, 我这个Http Server 访问的人还不多, 每分钟也就那么几十个连接发过来,我轻松应对。

由于是新鲜事物, 我还有资本给搞数据库的小明和做编译的小白吹吹牛, 告诉他们我可是网络高手。

没过几年, Web迅速发展, 我所在的破旧机器也不行了, 换成了一个性能强悍的服务器, 也搬到了四季如春的机房里。

现在每秒中都有上百个连接请求了, 有些连接持续的时间还相当的长,所以我经常得创建成百上千的进程来处理他们,每个进程都得耗费大量的系统资源, 很明显操作系统老大已经不堪重负了。

他说: “咱们不能这么干了, 这么多进程,光是做进程切换就把我累死了。”

“要不对每个Socket连接我不用进程了, 使用线程? ”

“可能好一点, 但我还是得切换线程啊, 你想想办法限制一下数量吧。”

我怎么限制?  我只能说同一时刻,我只能支持x个连接, 其他的连接只能排队等待了。

这肯定不是一个好的办法。

3

Http Server 3.0 : Select模型

老大说: “我们仔细合计合计, 对我来说,一个Socket连接就是一个所谓的文件描述符(File Descriptor ,简称 fd , 是个整数) , 这个fd 背后是一个简单的数据结构, 但是我们用了一个非常重量级的东西-- 进程 --来表示对它的读写操作,  有点浪费啊。”

我说: “要不咱们还切换回单进程模型?  但是又会回到老路上去, 一个receive 的阻塞就什么事都干不了了”

“单进程也不是不可以,  但是我们要改变一下工作方式。”

“改成什么?” 我想不透老大在卖什么关子。

“你想想你阻塞的本质原因,  还不是因为人家浏览器还没有把数据发过来, 我自然也没法给你, 而你又迫不及待的想去读, 我只好把你阻塞。 在单进程情况下, 一阻塞,别的事儿都干不了。“

“对,就是这样”

“所以你接受了客户端连接以后, 不能那么着急的去读,  咱们这么办, 你的每个socket fd 都有编号, 你把这些编号告诉我,  就可以阻塞休息了 ”

我问道:“这不和以前一样吗? 原来是调用receive 时阻塞, 现在还是阻塞”

“听我说完, 我会在后台检查这些编号的socket,  如果发现这些socket 可以读写, 我会把对应的socket 做个标记, 把你唤醒去处理这些socket 的数据, 你处理完了,再把你的那些socket fd 告诉我, 再次进入阻塞,如此循环往复。”

我有点明白了: “ 这是我们俩的一种通信方式, 我告诉你我要等待什么东西, 然后阻塞,  如果事件发生了, 你就把我唤醒, 让我做事情。”

“对, 关键点是你等我的通知, 我把你从阻塞状态唤醒后, 你一定要去遍历一遍所有的socket fd,看看谁有标记, 有标记的做相应处理。   我把这种方式叫做 select  ”

我用select的方式改写了Http server, 抛弃了一个socket请求对于一个进程的模式,  现在我用一个进程就可以处理所有的socket了。

4

Http Server4.0 : epoll

这种称为select的方式运行了一段时间, 效果还不错, 我只管把socket fd 告诉老大, 然后等着他通知我就行了。

有一次我无意中问老大:“我每次最多可以告诉你多少个socket fd?”

“1024个”

“那就是说我一个进程最多只能监控1024个socket了? ”

"是的, 你可以考虑多用几个进程啊"

这倒是一个办法, 不过"select"的方式用的多了, 我就发现了弊端, 最大的问题就是我从阻塞中恢复以后,需要遍历这1000多个socket fd, 看看有没有标志位需要处理。

实际的情况是,  很多socket 并不活跃,  在一段时间内浏览器并没有数据发过来, 这1000多个socket 可能只有那么几十个需要真正的处理,   但是我不得不查看所有的socket fd, 这挺烦人的。

难道老大不能把那些发生了变化的socket 告诉我吗?

我把这个想法给老大说了下, 他说:“嗯, 现在访问量越来越大, select 方式已经不满足要求, 我们需要与时俱进了, 我想了一个新的方式,叫做epoll”

“看到没有, 使用epoll和select 其实类似“  老大接着说 : ” 不同的地方是第3步和第4步, 我只会告诉你那些可以读写的socket , 你呢只需要处理这些'ready' 的socket 就可以了“

“看来老大想的很周全, 这种方式对我来说就简单的多了。  ”

我用epoll 把Http Server 再次升级, 由于不需要遍历全部集合,  只需要处理哪些有变化的, 活跃的socket 文件描述符,   系统的处理能力有了飞跃的提升。

我的Http Server 受到了广泛的欢迎, 全世界有无数人在使用, 最后死党数据库小明也知道了, 他问我:“ 大家都说你能轻松的支持好几万的并发连接, 真是这样吗? ”

我谦虚的说: “过奖, 其实还得做系统的优化啦。”

他说:“厉害啊,你小子走了狗屎运了啊。”

我回答: “毕业那会儿辅导员不是说过吗, 每个人都有光明的前途。”

(完)

码农翻身相关历史文章推荐:


Java EE

我是一个线程

我是一个Java class

Java:一个帝国的诞生

JDBC诞生记

JDBC后传

一个不安分的JDBC驱动

JSP:一个装配工的没落

Javascript: 一个屌丝的逆袭

Spring本质系列(1) -- 依赖注入

Spring本质系列(2) -- AOP

Http 历险记(上)

Http 历险记(下)—Struts的秘密

三层架构和MVC那点事儿

Java帝国之 Java Bean(上)

Java帝国之 Java Bean(下)

Java帝国之 函数式编程 (上)

Java帝国之 函数式编程 (下)

计算机网络

我是一个路由器

我是一个网卡

TCP/IP之大明邮差

TCP/IP之大明内阁

TCP/IP之蓟辽督师

张大胖的socket

IE为什么把Chrome和火狐打伤了?

对浏览器村的第二次采访

节约标兵IE的自述

EMail诞生记

EMail诞生记(下)

操作系统

我是一个进程

CPU阿甘

CPU阿甘之烦恼

我是一个键盘

我是一块硬盘(上)

我是一块硬盘(下)

那些烦人的同步和互斥问题

冯·诺伊曼计算机的诞生

数据库

小李的数据库之旅(上)

小李的数据库之旅(下)

张大胖学数据库

数据库村的旺财和小王

你看到的只是冰山一角, 更多精彩文章,尽在“码农翻身” 微信公众号, 回复消息"m"或"目录" 查看更多文章

from: http://chuansong.me/n/1392417151737

Http Server : 一个差生的逆袭相关推荐

  1. Javascript:一个屌丝的逆袭

    | 来源:码农翻身 微信公众号(id:coderising). 作者:刘欣 是的, 我就是鼎鼎大名的Javascript,  典型的高富帅,前端编程之王,数以百万计的程序员使用我来编程. 如果你没有用 ...

  2. 如何从一个普通的屌丝逆袭为一个程序员屌丝?(连载)

    零.题记 屌丝逆袭亘古不变的话题,芸芸众生津津乐道的话题,如何从一个普通的屌丝逆袭呢?如果你早个20年问这个问题,可能是去学土木工程,就好像现在众屌丝纷纷涌向了计算机的相关行业.无疑,高新技术是最能刺 ...

  3. 《MacTalk 跨越边界》一一2.4 一个学渣的逆袭

    本节书摘来自异步社区出版社<MacTalk 跨越边界>一书中的第2章,第2.4节,作者: 池建强,更多章节内容可以访问云栖社区"异步社区"公众号查看. 2.4 一个学渣 ...

  4. 记住:从来没有一个屌丝能够逆袭!

    5年前,一个叫Brian Acton的人去Facebook应聘,被无情拒绝. 随后,他开发了一款叫WhatsApp的软件. 5年后的今天,Facebook花190亿美元收购了WhatsApp. 有人说 ...

  5. JavaScript:一个屌丝的逆袭,乘风破浪

    JavaScript:一个屌丝的逆袭,乘风破浪 是的,我是大名鼎鼎的JavaScript,典型性的高帅富,前端开发程序编写之首,数以百计的程序猿应用我程序编写.假如你沒有使用过我也太out了.但是当我 ...

  6. 一个傻瓜的逆袭之路~~投胎是个技术活...

    我们身边的聪明人很多,但能把事儿做成的人却不多.在这一小撮小有成就的人中,如果以各种成绩来衡量,聪明的就更少了,这实在是个让聪明人沮丧的事实. 那么究竟靠什么能把事情做成功呢?就是傻呗!这种傻就是把事 ...

  7. 大厂Java岗春招必看:论一个面渣逆袭之路上必学得那些知识点

    前言 大家都知道 Github 是一个程序员福地,这里有各种厉害的开源框架.软件或者教程.这些东西对于我们学习和进步有着莫大的进步,所以将 Github 上非常棒的七大Java开源项目技术文档整理下来 ...

  8. abd shell关闭所有程序_一个 Shell 脚本逆袭的规范,拿走不谢

    指定一个默认脚本解释器 "#!" 是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种Shell.他指明了当我们没有指定解释器的时候默认的解释器. 为什么建议要在 ...

  9. Javascript:一个屌丝的逆袭之路

    是的, 我就是鼎鼎大名的Javascript, 典型的高富帅,前端编程之王,数以百万计的程序员使用我来编程. 如果你没有用过我就太out了. 不过当我是一个屌丝时, 真的没有想到能发展到如今的地位- ...

最新文章

  1. cannot find main module 解决办法
  2. mSystems:干旱对土壤微生物组的影响
  3. opencv resize_树莓派监控摄像头python+picamera或openCV
  4. Spring和SpringMVC自动扫描注解类的冲突问题
  5. 凭借这份Java面试题集,分布式宝典:限流+缓存+通讯
  6. springboot集成prometheus
  7. [pythonjava爬虫实战]-爬取学院老师信息之-java版本python版本
  8. Swoole Interview
  9. LVS负载均衡-NET、DR模式配置
  10. 【云计算平台】Hadoop单机模式环境搭建
  11. 剑指offer:序列化二叉(前序遍历+层次)
  12. 鸿沟理论(The Chasm Theory)介绍
  13. Postman下载与安装操作步骤(只有两步骤下载)
  14. ThinkPHP自动匹配CP端移动端模板
  15. C# Winform控件贴透明png图片遇到的问题
  16. matlab统计所有股票分析,MATLAB金融算法分析实战:基于机器学习的股票量化分析...
  17. ibm java虚拟机_IBM J9 Java虚拟机正式开源,贡献给Eclipse基金会管理
  18. 一睹风采,见证郁锦香酒店遍布全球核心城市的百变姿态
  19. 西涝东雪!数场冬季风暴轮番侵袭美国 多地预警
  20. 有效使用计算机的,有效的电脑学习方法

热门文章

  1. Linux 线程实现机制分析--转
  2. jquery学习手记(2)jQuery对象和DOM对象相互转换
  3. 4.4 开发模式下的测试:简化我们对链码的测试过程
  4. 顶象深度画像亮相GMIC,用AI提升金融反欺诈
  5. 如何达到高并发的概念?-分享一下微信百亿级红包的金融设计方案
  6. php 表单提交及验证 tp,ThinkPHP表单自动提交验证实例教程
  7. hadoop入门-在windows上编译x64位hadoop
  8. Oracle-数据字典解读
  9. java图形界面猜字游戏,java程序,猜字游戏,希望大神帮忙
  10. hamming weight_popcount或者hamming weight(二进制1的个数问题)