[linux][network]互联网后台模型

前言: 虽然话题的范围有点大,但是在这里作者不打算谈框架,侃架构。 这里也只是作者最熟悉的一种后台架构模型。 并发模型: 多进程模型:

来一个请求,设定环境变量(请求的变量通过环境变量来传递),再fork出来一个子进程来处理,模型简单粗暴。

传统的CGI,很多还基于这种模型。模型简单,缺点同样明显:fork系统调用的成本比较高,处理完一次请求,子进程就需要exit一次,同样需要一次系统调用;另外,还有其他隐式的系统开销----子进程之间的进程切换,同样也有比较高的成本。 进程池模型: 针对于多进程模型的频繁fork-exit,演化出来了进程池模型。初始化阶段一次性fork出来多个(经常是数百个)子进程,子进程内部循环处理请求,并不会退出。 Spawn-fcgi的代码参考:https://github.com/pacepi/spawn-fcgi(原生代码中,spawn-cgi唤醒FASTCGI之后会退出,作者在里面增加了monitor能力,使之能监控FASTCGI的异常退出,并唤醒新的FASTCGI) FASTCGI的代码参考:http://www.lighttpd.net/

那么问题来了:环境变量只能通过进程的父子关系来继承,那么对于常驻进程来说,怎么把请求中的变量通过环境变量来传递呢?

关键代码就是从socket读取到请求变量到内存,然后把内存地址赋值给全局变量environ,这样通过getenv就可以读取到请求变量,做到和CGI的兼容。 线程池模型: 相对于进程池,就是使用多线程来处理。 线程切换比进程切换的优势在哪里呢? 答案是线程之间共享内存(本质来讲,是使用同一个页表),线程之间的切换,不需要CPU刷新TLB(注意,这里不是进程上下文。线程切换也是需要kernel切换thread info的)。 劣势呢? 多线程编程,需要控制好临界区,必要时需要使用锁;进程的栈一般情况下,很少会overflow,但是线程栈在32bit系统中默认是2m,在64bit中默认是8m;而且,用户在自己指定线程栈的情况下,一定不能使用malloc来分配,因为栈的起始地址需要以page大小对齐,应该使用memalign类似的函数(当然也可以使用mmap匿名映射);线程编程还有一个麻烦点,就是CPU cache和内存间的数据不同步,所以尽量不要使用全局变量,就算使用,在逻辑中注意使用atomic族函数(参考https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html)。 IO复用模型: Linux的典型IO复用方案: select:最多1024限制,性能比较差。 epoll:性能强,后台框架的最佳选择。代码参考linux-4.0.4/fs/eventpoll.c。(作者曾经要解决Nginx的accept mutex问题,最终尝试修改epoll,使问题得到解决,这个解决方案也是作者的一个得意之作) 这里说明一点,无论使用select还是epoll,那么代码编写都会相对晦涩难读。所以会有各种各样的高大上的“架构”出来:如抽象成事件模型的libevent,抽象成框架类型的yaaf,抽象成协程模型的state thread。 IO方案: 以QQ为例子:用户请求把QQ好友列表拉取回去:1,获取好友列表(列表中是一个个数字号码),耗时1S;2,使用数字号码拉取好友的昵称,耗时2S;3,使用QQ号码拉取好友的备注名称,耗时3S。 同步模型: 分别顺序执行1,2,3步,那么执行时间的总时长就是1S+2S+3S=6S。 异步模型: 执行第1步,耗时1S。 同时向后端发送请求执行第2部,第3部。那么可以在3S内获取到昵称和备注。 那么,执行的总时长就是1S+3S=4S。

通过异步IO,可以让请求相应更快,并发度更高。 后记: 文章没做代码解读,略显华而不实。 君不见,不提“海量”,不说“框架”,这文章就没法写了么~

新年快乐~

原文发布于微信公众号 - AlwaysGeek(gh_d0972b1eeb60)

原文发表时间:2017-01-28

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏机器之心

代码优化指南:人生苦短,我用Python

选自pythonfiles 机器之心编译 参与:Panda 前段时间,Python Files 博客发布了几篇主题为「Hunting Performance i...

35513
来自专栏公有云大数据平台弹性 MapReduce

EMR上Zeppelin入门

简而言之,就是一个大数据分析平台。用户可以利用提供好的WEB UI,在线编写分析逻辑代码,输出结果,并且能够利用可视化工具,形象生动的在线展示结果。

1631

控制MongoDB中的集合分布

分片标记(Shard tagging)是MongoDB 2.2.0版中的一项新功能。通过对集合进行标记使其被强制写入到本地数据中心,也可以用来将某个集合固定到一...

2256
来自专栏数据和云

如何提高Linux下块设备IO的整体性能?

编辑手记:本文主要讲解Linux IO调度层的三种模式:cfp、deadline和noop,并给出各自的优化和适用场景建议。 作者简介: ? 邹立巍 Linux...

6654
来自专栏孔德雨的专栏

Mongos 与集群均衡

Mongodb 可以以单复制集的方式运行,client 直连mongod读取数据。单复制集的方式下,数据的水平扩展的责任推给了业务层解决(分实例,分库分表),本...

8.8K3
来自专栏Sorrower的专栏

内核必须懂(一): 用系统调用打印Hello, world!

1625
来自专栏漫漫前端路

写个 vue-loading-template 组件

源码(star ? start : start):github.com/jkchao/vue-…

4092
来自专栏云计算与大数据

Linux CPU 如何判断忙

摘录自:http://www.ruanyifeng.com/blog/2016/12/user_space_vs_kernel_space.html

2902
来自专栏Sorrower的专栏

内核必须懂(一): 用系统调用打印Hello, world!

2693
来自专栏JavaEdge

漫谈缓存更新之道

许多人在更新缓存时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载入缓存中。

2162

扫码关注云+社区

领取腾讯云代金券