slide: http://blog.daydaygo.top/post/tech-share-1
开始
感谢大家来参加我的分享。今天分享的主题是:高性能服务器入门小探。我会尽量抽象一点,方便小白食用。
按照我参加的技术分享的常见套路,第一部分是「个人简介」。这一部分我会尽量低调。
第二部分是「网络基础」,希望大家关注一下这部分的「分层」设计思想。
第三部分就是今天的主角了,讲讲「服务器编程模型演进」。其实这部分可以简单概括为 —— 说多了都是套路。
最后推荐一点资源,假装一下自己读了一些书。
友情提醒:部分演讲内容不得不使用英文,如果听不懂,这很正常。
下面是个人简介
我的英文名 - daydaygo。为什么起这个名字,大家可以和奶爸交流,奶爸总结了三点。我目前的座右铭是 Coder at Work 编程人生。有一本书也叫这个名字。大家有兴趣可以看看,可以帮助解答一个问题:为什么身边没有超过 40 岁的程序员?他们都去哪了?下面还有三句话,代码,是艺术的一部分。- farbox。本次分享使用的就是 farbox 的幻灯片服务。不过有些样式的问题。第二句话是我仿的,编程,是人生的一部分。- by me。最后一句来自鸟哥的 blog,左右代码,右手诗。- 鸟哥。php7 的作者。如果有看过「GitHub中国区前100名到底是什么样的人?」这篇文章,就很容易找到他。
我的兴趣爱好:跑步、骑行、LOLer
我给自己的标签是:持续创业者。之前做过爬虫、P2P、游戏。目前看来:果然还是金融更有意思一点。目前在 「学堂在线」 上自学《经济学原理》。
我的技术方向:首先是知乎上的签名 - 什么都关注一点的 web 开发。工作内容大部分是服务器编程,平时也在折腾 docker、虚拟化技术、运维相关。当然,最想说的是:我们的征途是星辰大海
第二部分:网络基础
首先网络协议栈架构,无论是OSI七层还是 tcp/ip 四层,都是分层设计的思想。以 tcp/ip 模型为例,可以简单理解为:链路层和物理设备打交道,网络层和 ip 打交道,传输层和数据传输打交道,应用层就是各种应用啦,比如浏览器打开网页,就是 http。
这里有一张概览图,可以对照了看一下。好多英文缩写完全看不懂怎么办?不用管,我来划重点。最下面是链路层,然后是网络层,网络层怎么不只有 ip?不用管,你能用到的基本都是ip。之后是传输层,这里怎么又来了UDP?其实就是两种传输方式,区别在于网络可能会出问题,但是 udp 只管发数据,不管对方收到没有,tcp 做了一些保护措施。大家可以参考「两军问题」,这也是为什么 tcp 连接建立要三次握手。我先给你发个消息,你回复刚才我发的消息以及你自己的消息,然后我把你发的消息再回复给你,这个流程之后,就可以认为我们两个之间的通信是可靠的。当然,网络还是说断就能断,那就是一些其他的技术了。所以,大部分都是 tcp 啦,大家可以想一想 UDP 这样的「不可靠通信」,会在什么地方使用呢?比如监控、直播。不知道大家有没有看视频突然视频跳了一下经历呢?之后就是我们这群后端程序员经常打交道的应用层了。最后还有一点,看到这条线没有,有没有感觉到很屌,居然可以不走传输层直接到应用层。大家可以猜猜这是啥,后面也会提到。
MAC 地址,用来定义互联网中设备的位置。
下面讲讲 IP 地址。首先是本机回环 127.0.0.1,我们家测试同学已经很熟了,当然它还有另一个更熟悉的名字 —— localhost。然后是局域网地址,我们俗称的内网 ip,比如我们现在使用的虚拟机 192.168.100.153.剩下的就是外网地址了。本机回环只能本机访问,内网地址只能内网访问,外网地址才能给天南海北的用户使用。除了这3类地址,还有一个bug级的存在,叫做 0.0.0.0. 这个东西是干嘛的呢?对了,来者不拒,无论是本机、内网、还是外网,都允许访问。另外感兴趣的同学可以去了解一下 网络中的A类、B类、C类地址的划分,这样就可以区分内网地址和外网地址了。
刚才提到 127.0.0.1 和 localhost 的时候,其实就已经能说明「域名」的意义了。网络层要通过 ip 来找到目标设备,但是 ip 地址不好记呀,于是大家就想了一个办法,这就是域名。这里执行了一下 ping
命令,就可以看到域名实际对应的 ip 了。DNS,域名系统,就是专门处理域名和ip对应关系的系统。另外经常听到大家说改 hosts 文件,其实作用是一样的。留个问题给大家,如果我在 hosts 文件里面瞎写了一个 shoufuyou.com 的ip,我还能访问到 shoufuyou.com 么?
再来说一下端口号。可能大家不太熟悉这个。你通过 ip 找到主机地址了,但是怎么找到主机上面提供的服务了?于是就有了端口号。之所以大家不太熟悉这个,是因为很多端口给常用服务预留了。ssh: 22 http: 80 https: 443
好了,最后一个概念了,两个专业名词,封装和分用。可以当做快递来理解,先打包,你收到了之后再拆包裹。
RFC,所有以太网协议的正式标准。
好了,到今天的主角了,服务器编程模型演进
下面基本上都是「老大和小弟还有顾客」的故事。
首先了解一下和服务器通信的流程:accept 接受用户的请求(tcp 建立连接) -》recv 接受用户传递的数据 -》send 处理完后回复数据给用户 -》close 处理完了,关闭
这里简单看一下 php 的代码实现。最开始是这样的,老大建立了一个公司,公司在哪呢?就是这里的 ip 和端口。之后等顾客上门,顾客来了,他就招一个小弟来做事,顾客的事情处理完了,他打发走这个小弟。
听到这里大家就能发现问题了:每次要重新招人,HR 表示这活我干不来了。
联想一下现实中的公司,于是就能想到第二种解决方案:我先招好人先。就是这里,先招了 32 个小弟。
但是,这种方式也有问题。首先我们一开始只招了这么多小弟,那我们最多只能处理这么多的顾客。那是不是可以先招很多很多小弟?先不说老大乐意不乐意,从管理学的角度而言,好的管理者管理的直线汇报关系最好不要超过 7 个。同理,机器能管理的进程数量也是有极限的。最后,还有经典的 C10K 问题。大家可以猜一猜这个词是什么意思?其实 c + 10k,同时保持 1w 连接的问题。最常见的就是聊天室场景。拒 rango 的博客说,qq 早期也有这样的问题,后来通过 udp 扛过去了。
好了,终于要到了我们今天真正的主角了。名词先不管,先来看三个词:select、poll、epoll。select: 可以在一个进程内维持1024个连接。poll: 可以维持任意数量的连接。但是他两都有问题,需要循环检测连接是否有事件。其实就是顾客来了,点菜或者挑衣服啥的,小弟要一个一个问才知道是哪个顾客点菜了。
是不是发现胜利就在眼前,只要解决顾客有需求的时候,能够及时提供服务就行了,于是就有了 epoll。这里来简单看看 epoll 是怎么处理的。Reactor 模型,大家知道这个单词么?反应堆的意思。其实就是老大发现我啥都做的不错,但是管理就是不咋样,于是找了一个管理团队。这个管理团队做的事情也简单,add 它要管哪些人。set 这个人要处理哪些事。del 不管这个人了。callback,这个人遇到这些事要怎么处理。
好了,我们简单看看 php 代码实现。先建一个反应堆,然后建公司,招小弟,小弟来处理用户的需求。
有了这个之后,什么 C100K,C1M,C10M,C100M 都不是问题了。这里提一下 k 和 m。大家可能看到过一句话:这世界有 10 种人。2^10 = 1024 ~= 10^3
好了,最后一部分了,协程。当程序员还沉浸在解决 C10K 问题带来的成就感时,一个新的问题被抛出了。异步嵌套回调太 TM 难写了。我是不是应该膜拜一下在座的 web 大前端。协程其实就像时间静止的游戏一样。国王对他的巫师说,来一车黄金。于是巫师就施展了一个时间静止的法术,等到一年后骑士把黄金运来的时候在解开法术。
学习资源推荐
实验楼,前面有图片就是来自这里,很多小白课程,xx基础,xx入门之类的。
Rango 的博客:本篇的主角主要参考了 rango 的博客来润色
下面就是专业书籍啦。
《Unix环境高级编程》
《TCP/IP网络通信详解》
《高性能 linux 服务器编程》