网络编程实战
盛延敏
前大众点评云平台首席架构师
44207 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
网络编程实战
15
15
1.0x
00:00/00:00
登录|注册

32 | 自己动手写高性能HTTP服务器(一):设计和思路

思考题
总结
反应堆模式设计
主要设计思路
设计需求
高性能HTTP服务器设计思路

该思维导图由 AI 生成,仅供参考

你好,我是盛延敏,这里是网络编程实战第 32 讲,欢迎回来。
从这一讲开始,我们进入实战篇,开启一个高性能 HTTP 服务器的编写之旅。
在开始编写高性能 HTTP 服务器之前,我们先要构建一个支持 TCP 的高性能网络编程框架,完成这个 TCP 高性能网络框架之后,再增加 HTTP 特性的支持就比较容易了,这样就可以很快开发出一个高性能的 HTTP 服务器程序。

设计需求

在第三个模块性能篇中,我们已经使用这个网络编程框架完成了多个应用程序的开发,这也等于对网络编程框架提出了编程接口方面的需求。综合之前的使用经验,TCP 高性能网络框架需要满足的需求有以下三点。
第一,采用 reactor 模型,可以灵活使用 poll/epoll 作为事件分发实现。
第二,必须支持多线程,从而可以支持单线程单 reactor 模式,也可以支持多线程主 - 从 reactor 模式。可以将套接字上的 I/O 事件分离到多个线程上。
第三,封装读写操作到 Buffer 对象中。
按照这三个需求,正好可以把整体设计思路分成三块来讲解,分别包括反应堆模式设计、I/O 模型和多线程模型设计、数据读写封装和 buffer。今天我们主要讲一下主要的设计思路和数据结构,以及反应堆模式设计。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

这篇文章深入介绍了设计和构建高性能HTTP服务器的关键技术和设计思路。首先,文章讨论了构建高性能网络编程框架的需求,包括采用reactor模型、支持多线程和封装读写操作到Buffer对象中。接着,详细介绍了反应堆模式设计、I/O模型和多线程模型设计,涉及到event_loop、channel、acceptor、event_dispatcher和channel_map等对象的设计和作用。文章重点分析了event_loop的运行和event_dispatcher的实现,以及channel对象的设计和作用。此外,还提供了思考题,鼓励读者深入思考和交流。 总的来说,这篇文章为读者提供了宝贵的参考和指导,使他们能够快速了解构建高性能HTTP服务器所需的关键技术和设计思路。同时,文章还提供了进一步深入学习的思考题,为读者提供了更多的交流和学习机会。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(30)

  • 最新
  • 精选
  • 吴小智
    map_make_space() 函数里 realloc() 和 memset() 两个函数用的很巧妙啊,realloc() 用来扩容,且把旧的内容搬过去,memset() 用来给新申请的内存赋 0 值。赞,C 语言太强大了。

    作者回复: 显然是看进去了。

    2019-10-22
    2
    7
  • LDxy
    event_loop_handle_pending_add函数中, map->entries[fd] = calloc(1, sizeof(struct channel *)); map->entries[fd] = channel; 这两行都给map->entries[fd] 赋值,后一行不是覆盖上一行的赋值了么?有何用意?

    作者回复: 这块是我的疏忽,应该直接赋值的,可能是开始我撰写的时候channel对象的初始化放到了event_loop_handle_pending_add函数中,后来把channel对象的初始化重构到外面,这里忘记删掉了。 已经更新文稿(待周一编辑更新)和github代码,感谢指正。

    2019-10-21
    7
  • 酸葡萄
    老师你好,问个基础的问题: epoll_dispatcher和poll_dispatcher都有,在添加,删除,更新事件时都有如下的逻辑,其中if条件中的判断怎么理解啊? if (channel1->events & EVENT_READ) { events = events | POLLRDNORM; } if (channel1->events & EVENT_WRITE) { events = events | POLLWRNORM; }

    作者回复: 这里是位与操作,举个例子,EVENT_READ可能为二进制的00000010,如果有可读事件发生,那么在这个位上的bit值一定位1,这样位与的结果就说明这个事件发生了。之所以采用位与,而不是位或,是因为只需要关心这一种类型的事件。

    2019-12-01
    2
    3
  • 沉淀的梦想
    看到map_make_space里面的realloc函数,突然有个疑问,既然操作系统底层支持直接在原数组上扩充内存,为什么Java不支持直接在原数组上扩容呢,ArrayList每次扩容都要重新拷贝一份原来的数据。

    作者回复: 好问题,我试着解读一下: 第一,Java有JVM实现,在Java的世界里,它的对象是统一被JVM管理的,包括GC,对象管理,基于这一层考虑,它不可能使用系统级别的对象内存管理,这两个没有办法调和,就像你举的例子,如果我们创建一个类似ReallocList对象,那么这个对象的内存管理完全不是JVM那套了; 第二,JVM是一个跨OS的实现,我不知道是否Windows也有类似realloc函数,这样就需要JVM做到跨OS的直接内存接管,这和Java的思想是不一致的。

    2019-10-22
    3
    2
  • 凌空飞起的剪刀腿
    int map_make_space(struct channel_map *map, int slot, int msize) { if (map->nentries <= slot) { int nentries = map->nentries ? map->nentries : 32; void **tmp; while (nentries <= slot) nentries <<= 1; tmp = (void **) realloc(map->entries, nentries * msize); if (tmp == NULL) return (-1); memset(&tmp[map->nentries], 0, (nentries - map->nentries) * msize); map->nentries = nentries; map->entries = tmp; } return (0); } 老师,fd不一定是连续的吧,这样会浪费内存存储空间吧?

    作者回复: 很好的问题。 第一,你可以看看实际分配的fd,大概会是什么样子; 第二,除了这个方法,你有别的更高效的方法吗?因为从fd来查找数据,需要非常的快; 我个人的判断,这点内存不算什么,因为我在设计这个结构时,大部分数据都是指针类型的。

    2021-06-07
    1
  • 谁家内存泄露了
    老师好,请问您的代码中关于锁的使用,我想知道您关于每个loop都设计了一个锁,可是这几个mutex都是局部变量吧?他们的作用范围是什么样的呢?这里想不清楚,请指点一下!

    作者回复: 所有的作用范围是全局的,而mutex锁看情况,有些是线程级别的,比如这里: pthread_mutex_lock(&eventLoopThread->mutex);

    2021-04-12
    1
  • Steiner
    如果Channel是一个管道,他连接着哪两个对象?

    作者回复: 连接着client端的套接字和server端的套接字。

    2021-02-18
    1
  • 漠博嵩
    感觉就是仿照netty框架做的

    作者回复: 还真不是。

    2022-05-24
  • 菜鸡
    第二个问题有点疑问。channel_map中元素的空间大小是与fd的值正相关的,而不是跟当前在线的连接数量正相关,这样做是不是有点浪费内存?比如经历了很多次连接、断开之后,fd返回的值比较大,而此时只有几个未断开的连接,那么channel_map有必要申请那么大的内存空间嘛?

    作者回复: 还好吧,channel_map中的元素没几个字节,比起复杂的压缩算法,这点实在是微不足道。而且,你也没办法预测后面的连接情况,准备好一个上限比较大的fd存储空间,其实是效率比较高的。

    2022-05-08
  • 群书
    用sock对通知 唤醒会不会增加逻辑线程或主线程的系统调用次数 限制了吞吐量呢

    作者回复: 不会。因为唤醒是kernel干的,只不过是多了一路I/O而已。

    2021-11-12
收起评论
显示
设置
留言
30
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部