跳至主要內容

高性能网络设计

LincZero大约 2 分钟

高性能网络设计

reactor

io_uring

版本问题

io_uring 是 aio,Linux也有aio呢?我之前学boost::asio时还说linux网络还没aio呢……现在终于有了!以前就Window有AIO (IOCP)

这个是 Linux Kernel 5.1 版本加入的,并在 5.10 版本后才得到较好支持,libaio 即将埋入黄土。参考:https://zhuanlan.zhihu.com/p/62682475

发行版本发行时间内核版本发布时间
18.042018.04.264.152018.01
18.102018.10.184.182018.08
19.042019.04.185.02019.03
19.102019.10.175.22019.07
20.042020.04.235.42019.11
22.04.2 LTS6.2

版本对照如上

以前的Linux操作是:

  • 网络用epoll
  • 磁盘操作用多线程
  • 大文件和数据库用libaio (io_uring 可能代替之)

不过io_uring现在有系统调用了,但库现在还未调研,不知道支持好不好

同步io、异步、aio

  • 同步
    • read:读->等
    • write
  • 异步
    • read_request
    • write_……
  • aio
    • aio_read

同步与异步用来处理两者之间的关系

实现细节

环形队列

环形队列实现方式

  • 链表
    • 好处:插入简单、删除简单
    • 坏处:有锁(双向链表)
  • 连续内存 (数组):逻辑环,双指针快
    • 好处:无锁队列、原子操作
    • 坏处:读写需要拷贝
  • io_uring 一般选择后者比较多,考量为:
    • 链表容易出现很多小的内存,不好
    • 连续内存的另一个好处是,可以做共享内存的映射
    • 不过链表法还有另一种分支:手动管理内存,也能避免上面那个缺点,也还不错

两个环:

  • submit queue, sq
  • complete queue, sq
  • 这两个环是使用了mmap映射的,这两个环是用户空间和内核空间共享的,所以取的时候是零拷贝

操作流程:

  1. 每次读请求,放到sq
  2. 处理完的结果,放到cq
  3. 遍历cq

io_uring

  • liburing:用户态
  • 3个syscall:内核态

tcp

tcp

  • accept()
  • recv()
  • send()

流程

  1. 客户多次连接,多次accept
  2. recv
  3. send
  4. close

代码

其他

  • fio

  • iops,每秒的io次数

  • iodepth,异步时ring的长度

  • 理论

  • 代码实现

  • 应用场景

  • 更好的解决方案

协程

用户态协议栈 三部曲 uio,数据帧,协议栈

透过tcp server看到网络编程,多线程,网络协议栈

手撕 epoll 组件