高并发编程必备知识IO多路复用技术select,poll讲解

简介: 高并发编程必备知识IO多路复用技术select,poll讲解

百万级连接和千万级连接的请求就是通过这些模型来做的

epoll:是nginx底层的机制了,运用事件驱动的方式支持千万级连接,像一些大厂使用的代理服务器就用nginx来做

一、select.poll的原理和优缺点:

上篇文章讲解了unix的五种网络编程模型

1、什么是IO多路复用:

   I/O多路复用,I/O指的是网络I/O,就是客户端请求,到服务端响应,多路指多个TCP连接(即socket或者channel),复用指复用一个或几个线程。

   简单来说:就是使用一个或者几个线程处理多个TCP连接,服务器创建线程和时间片的切换是很耗性能的。

   最大优势是减少系统开销小,不必创建过多的进程/线程,也不必维护这些进程/线程。

上面的图中,每一个actor代表一个客户端,每一条线代表10万条请求连接,Linux内核相当于服务器。

然后Linux内核有多个进程/线程去处理连接数,轮询的去处理这些的连接数。IO的多路复用就是这种的意思。

Select:是多路复用的其中一种

基本原理:

   监听文件3类描述符:writefds,readfds和exceptfds,所以在IO多路复用里面有写事件,读事件,异常事件。

在linux里面所有的文件的操作,socket连接都是一个文件描述符,在java编程里面,所有的东西都是对象,在Linux里面一切的东西都是fd,不是百分百,大部分都是这样的。

select的时候会调用一个函数,这个函数会监听用户的30万个连接,监听是否有读和写还有异常事件,调用后select函数会阻塞住,等有数据,可读,可写,或者出现异常,或者超时就会返回。select函数正常返回后,通过遍历30万个连接的请求的数组才能发现哪些句柄发生了事件(来判断哪些是可读或者可写的),来找到就绪的描述符fd,然后进行对应的IO操作。几乎在所有的平台上支持,跨平台支持性好。

这是最原始的多路复用技术。

缺点:

     1):select采用轮询的方式扫描文件描述符,全盘扫描,随着文件描述符FD数量增多而性能下降。因为30万个请求的链接会在用户空间和linux内核空间拷来拷去,是很耗性能的。

     2):每次调用 select(),需要把fd集合从用户态拷贝到内核态,并进行遍历(消息传递都是从内核到用户空间)

     3):最大的缺陷就是单个进程打开的FD有限制,默认是1024(可修改宏定义,但是效率仍然慢)   宏定义:就是java定义的常量      static  final  int MAX_FD=1024000,

所以在select模型支持太多的并发是不可能的,最多有几千个,上万的话性能就会急剧的下降。

poll:

   基本流程:

          select()和poll()系统调用的大体一样,处理多个描述符也是使用轮询的方式,根据描述符的状态进行处理,一样需要把fd集合从用户态拷贝到内核态,并进行遍历

最大的区别是:poll没有最大文件描述符限制(使用链表的方式存储fd,因为链表可以无限的去扩展,单/双向链表都可以无限扩展)

高并发编程必备知识IO多路复用技术-epoll讲解

epoll模型是nginx的模型,nginx底层就可以用这个,可以支持千万级的连接并发

基本原理:在2.6内核中提出的,对比select和poll,epoll更加灵活,没有描述符限制,用户态拷贝到内核只需要一次使用,采用事件通知的方式而不是轮询,通过epoll_ctl注册fd,一旦该fd就绪,内核就会采用callback的回调机制来激活对应的fd,然后进行io事件的处理。

优点:

   1):没fd这个限制,所支持的FD上限是操作系统的最大文件句柄数,这个最大句柄数是可以查看的,一般是65535,不用去在意它,一般是可以修改的,1G内存大概支持10万个句柄,虽然是65535,但是可以去调整它,一把把它调整成几十万,要支持单机百万连接的话,10G的话16G内存就可以解决了,所以单机解决百万的连接是不难的,只要模型用的对,Linux内核配的对就没问题。但是你要说网路IO阻塞了那是没有办法。

    2):效率提高,使用回调通知而不是轮询的方式,不会随着增加FD的数目的增加而效率下降,前面的两种模型是随着FD的数目增加而下降 。采用回调机制callback

   3):通过callback机制通知,内核和用户空间mmap同一块内存实现,不用拷贝来拷贝去,性能非常高。

当启动linux内核的时候:会涉及到下面三个函数

Linux内核核心函数:是c里面的,poll和select采用的是分别一个函数

         1)epoll_create():在系统启动的时候,在linux内核里面申请一个文件系统:B+树,查找效率非常快,返回epoll对象,也是一个fd

          2)  epoll_ctl():操作epoll对象,在这个对象里面修改添加删除对应的链接fd,在epoll对象里面有100万个链接的话,假如有1万个链接是活跃的,1万个fd会就绪放到一个集合里面去,那么这1万个fd就会有对应的回调函数。

          3) epoll_wait():在ctl操作epoll对象的时候,wait就会做对应的处理了。判断并完成对应的io操作,判断这个集合callback是否为空,不为空的话,对集合中的fd都做一个io的操作。

三个函数组成函数组成epoll的高性能,这三个是互相搭配的

缺点:

  编程模型比select/poll复杂

举个例子:100百万个链接,里面有1万个链接是活跃的,在select,poll,epoll三个模型中表现是怎么样的?

在select模型里面:想要支持百万个链接的话,单个进程的话支持1024,在不修改宏定义的情况下该怎么做呢?则需要1000个进程才可以支持100万个连接,1000个进程在一台机器上创建的话给8核16G的话,这时机器会挂掉的,1000个进程每个进程处理1000个连接,cpu是轮询不过来的。性能会特别的差

poll:100万个链接的话,遍历都响应不过来了,还有空间的拷贝消耗大量的资源

epoll:不会遍历整个fd,通过上面的三个函数,第一个函数进行注册,注册好之后,100万个链接进来的时候,有1万个链接活跃,就会操作epoll对象,并绑定一个callback函数,当每一个fd就绪的时候就会触发callback函数,从而调用wait函数进行处理从而完成io的操作。省了两点:不用遍历fd,不用进行内核空间和用户空间之间的拷贝。

相关文章
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
1038 1
Linux C/C++之IO多路复用(aio)
|
缓存 关系型数据库 MySQL
在MySQL中处理高并发和负载峰值的关键技术与策略
采用上述策略和技术时,每个环节都要进行细致的规划和测试,确保数据库系统既能满足高并发的要求,又要保持足够的灵活性来应对各种突发的流量峰值。实施时,合理评估和测试改动对系统性能的影响,避免单一措施可能引起的连锁反应。持续的系统监控和分析将对维护系统稳定性和进行未来规划提供重要信息。
606 15
|
监控 应用服务中间件 Linux
掌握并发模型:深度揭露网络IO复用并发模型的原理。
总结,网络 I/O 复用并发模型通过实现非阻塞 I/O、引入 I/O 复用技术如 select、poll 和 epoll,以及采用 Reactor 模式等技巧,为多任务并发提供了有效的解决方案。这样的模型有效提高了系统资源利用率,以及保证了并发任务的高效执行。在现实中,这种模型在许多网络应用程序和分布式系统中都取得了很好的应用成果。
450 35
|
缓存 NoSQL Java
Java 项目实操高并发电商系统核心模块实现从基础到进阶的长尾技术要点详解 Java 项目实操
本项目实战实现高并发电商系统核心模块,涵盖商品、订单与库存服务。采用Spring Boot 3、Redis 7、RabbitMQ等最新技术栈,通过秒杀场景解决库存超卖、限流熔断及分布式事务难题。结合多级缓存优化查询性能,提升系统稳定性与吞吐能力,适用于Java微服务开发进阶学习。
908 0
|
机器学习/深度学习 API Python
Python 高级编程与实战:深入理解网络编程与异步IO
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧、数据科学、机器学习、Web 开发和 API 设计。本文将深入探讨 Python 在网络编程和异步IO中的应用,并通过实战项目帮助你掌握这些技术。
|
存储 缓存 监控
社交软件红包技术解密(四):微信红包系统是如何应对高并发的
本文将为读者介绍微信百亿级别红包背后的高并发设计实践,内容包括微信红包系统的技术难点、解决高并发问题通常使用的方案,以及微信红包系统的所采用高并发解决方案。
656 13
|
人工智能 缓存 NoSQL
高并发秒杀系统设计:关键技术解析与典型陷阱规避
在电商、在线票务等场景中,高并发秒杀活动对系统性能和稳定性提出极大挑战。海量请求可能导致服务器资源耗尽、数据库锁争用及库存超卖等问题。通过飞算JavaAI生成的Redis + Lua分布式锁代码,可有效解决高并发下的锁问题,提升系统QPS达70%,同时避免缓存击穿与库存超卖。相较传统写法,AI优化代码显著提高性能与响应速度,为高并发系统开发提供高效解决方案。
|
数据库
同步IO模型是一种常见的编程模型
【10月更文挑战第5天】同步IO模型是一种常见的编程模型
313 2
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
916 0
Linux C/C++之IO多路复用(poll,epoll)
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。