epoll可以解决多个socket的连接,为什么高并发服务器还要用进程池或者线程池呢?

epoll可以解决多个socket的连接,为什么高并发服务器还要用进程池或者线程池呢?,第1张

socket接受线程:C语言为了高并发所以选择了epoll。当程序启动的时候(g_net_update.c文件中main函数,会启动一个thread见函数create_accept_task)这个thread就处理一件事情,只管接收客户端的连接,当有连接进来的时候 通过epoll_ctl函数,把socket fd 加入到epoll里面去,epoll设置监听事件EPOLLIN | EPOLLET主要是监听的是加入到epoll中的socket是否可读(因为我的需求是客户端连上了server就会马上向server发送一份数据的)。其它的部分在主线程中处理。

主线程:是一个无线循环,epoll_wait 函数相当于把客户端的连接从epoll中拿出来(因为我们监听的是EPOLLIN | EPOLLET)说明这个时候客户端有数据发送过来)。再通过recv_buffer_from_fd 函数把客户端发送过来的数据读出来。然后其他的一切就抛给线程池去处理。

线程池:(代码中我会在池里面创建15个线程) 双向链表。加入线程就是在链表后面加一个链表项,链表的前面会一个一个被拿出来处理。主要是malloc 函数free函数,sem_wait函数sem_post的处理(sem_wait 会阻塞当值大于0是会减一,sem_post是值加一)。typedef void* (FUNC)(void arg, int index)是我们自定义的线程的逻辑处理部分,arg是参数,index是第几个线程处理(我们隐形的给每个线程都标了号),例如代码中的respons_stb_info,更加具体可以看看代码里面是怎么实现的。聪明的你也可以改掉这块的内容改成动态线程池,当某个时刻的处理比较多的时候能够动态的增加线程,而不像我代码里面的是固定的。

数据库连接池:按照我的需求在处理客户端请求数据的时候是要访问数据库的。就是一下子创建出一堆的数据连接。要访问数据库的时候先去数据库连接池中找出空闲的连接,具体可以看下代码。使用的时候可以参考下database_process.c文件(代码中数据库连接池和线程池中的个数是一样的)。这里我想说下get_db_connect_from_pool这个函数,我用了随机数,我是为了不想每次都从0开始去判断哪个连接没有用到。为了数据库连接池中的每个链接都能等概率的使用到,具体的还是可以看下代码的实现。

做服务器,你需要知道服务器都需要什么技术。首先,搭建服务器一般都是在Linux平台,所以你需要了解Linux知识,包括Linux操作命令。

另外,服务器经常需要脚本,你需要知道shell脚本的知识。

然后,就是网络通信,服务器和客户端需要进行通信,你需要知道tcp/ip协议,网络编程,http和https协议,还有单播,组播,广播。

还有,服务器一般还需要数据库做支撑,所以数据库还需要了解。

当然,最基础的编程语言肯定是需要熟练掌握的,最好能懂算法,这样搭建服务器才高效。

最后,还有一些特殊的技术,比如多客户端同时连接服务器问题,epoll,select技术,进程间通信技术,多线程技术,文件操作等。

当然,以上所有技术了解最好,有些是必须熟练使用的。但是有些不用熟练使用,因为服务器,也不会让你全干,分到每个人手上的活只是一部分。

高并发C10K

C10k:服务器同时处理1W个TCP连接。

C10M:服务器同时处理1kw个TCP连接。

实现高并发的本质技术是 事件驱动 和 异步开发 。协程也是依靠这俩实现高并发的。

最简单的,就是一个 UDP请求 。

因为一个UDP请求通常仅由一个网络报文组成。

请求——事件——回调函数

因为常见的HTTP等协议都是基于TCP实现的,TCP是一个面向字节流的协议,所以会导致HTTP请求的大小不受限制。

当一个HTTP请求的大小超过TCP报文的最大长度的时候,就会被拆分为多个报文,然后在接收端的缓冲区重组和排序,所以说,不是每个到达的TCP报文都能生成事件(不完整)。

事件只有2种类型——

第二次握手结束,客户端->服务器的通道就建立好了,客户端就会产生写事件。

第三次握手,客户端发送的ACK报文到达服务器后,服务器产生读事件。

看着有些多此一举

写缓冲区,write函数,进程

关闭连接的时候,被动方会产生读事件,从而调用close函数关闭连接。

服务器里面对资源的操作从快到慢,依次是CPU,内存,磁盘,网络。

前两个都很快,所以不需要考虑事件驱动。

然而磁盘和网络都需要采用 事件驱动的异步方式 来处理。

当下的事件驱动,针对的都是网络事件。

网络事件是由内核产生的,进程使用epoll这样的多路复用技术就可以获取到它们(网络事件)。

太复杂了慢慢看

好我们这里直接进入总结——

网络报文到达后,内核就产生了读写事件,epoll函数的作用则是可以 让进程高效地收集这些事件 。

还要确保在进程中处理每个事件的时间足够短,从而才能及时地处理所有的请求——这个过程中,要避免使用 阻塞socket ,也要把耗时长的操作拆分成多份。

epoll多路复用是一种机制,可以实现C10M的高并发服务。

因为网络消息的传输第一比较慢,第二也不可控,所以用网络事件驱动请求的性价比最高。

TCP报文是如何产生事件的?

可以用多路复用技术获取事件。epoll的优势在于取消了收集事件的时候重复传递大量的socket参数。


欢迎分享,转载请注明来源:夏雨云

原文地址:https://www.xiayuyun.com/zonghe/205919.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-03
下一篇2023-04-03

发表评论

登录后才能评论

评论列表(0条)

    保存