1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Linux服务器7 --- 多路IO复用+线程池服务端模型(高并发)分析

Linux服务器7 --- 多路IO复用+线程池服务端模型(高并发)分析

时间:2019-05-28 19:06:56

相关推荐

Linux服务器7 --- 多路IO复用+线程池服务端模型(高并发)分析

一、服务端特性概述

1、使用EPOLL模型在服务器中加入(网络IO监听,大量的监听能力)

EPOLL采用边缘触发模式(后话)

2、线程池模型进行并发处理业务(并发处理能力)

1)提高线程重用性(避免频繁创建销毁线程)。

2)线程管理能力较强(根据需求扩容缩减)。

3)预创建处理线程,可以更为及时有效地为客户端服务。

3、不要让处理线程与客户端绑定(影响并发),处理线程可以重用为不同的客户端服务。

4、不要让线程池与业务绑定,使用者自行定义实现业务并传递给线程池, 线程负责执行即可。

5、服务端任务传递采用生产者消费者模式(EPOLL生产者, 线程池消费者)。 生产者消费者模型采用条件变量完成线程控制(挂起与唤醒)。

6、管理者角色,负责对线程池进行监控, 完成线程控制(扩容与缩减)。

7、业务分类,可以根据不同网络IO就绪,制定不同的业务(当然也可以根据客户端协议制定业务)。

8、考虑线程安全,全局资源访问用互斥手段。

二、服务端处理流程分析

1、首先userA客户端去connect服务端,连接请求被epoll监听到,生产者是主控线程控制epoll,通过epoll模型监听到就绪并传递任务。serverfd绑定业务A(建立连接),clientfd绑定业务B(处理请求),serverfd就绪产生了业务A,生产者就会将业务A添加到投放到线程池的业务队列中,线程池一般会先预创建一些线程,这些线程都是消费者,一生产者,多消费者,消费者从业务队列里面取出业务,拿到业务以后去执行,比如某一消费者取到的是业务A,那么就会去建立连接(accept),然后将返回的新的clientfd添加到监听集合中。如果取到的是业务B,处理完以后反馈给客户端,如果某一时刻客户端异常退出,将其对应的网络IO从监听树中删除。

2、主控线程生产者,普通线程消费者,还有一个单独的线程是管理者,负责对线程池中的普通线程进行扩容和缩减,监管普通线程,线程池

线程的扩容和缩减条件,线程执行业务,线程被占用,一段时间内不能再执行其他业务,线程状态busy,没有任务线程状态就是idle,创建多少线程,就有多少线程存活,线程数量计数的时候一般不算生产者和管理者。扩容条件一,忙线程占存活线程数量的70%,扩容条件二,当前任务数量>=闲线程数量。缩减条件为闲线程是忙线程的倍数。

三、服务端模块分析

#include<SOCKET_API.h>/* 服务端宏定义 */#define SERVER_IP "127.0.0.1"#define SERVER_PORT 8000#define BUFSIZE 1500#define BACKLOG 128#define TIMEOUT 2 //等待超时#define IPSIZE 16#define EPOLLSIZE 90000#define TRUE 1#define FALSE 0#define THREAD_CODE 10 //扩容缩减量int epfd; //监听树描述符pthread_mutex_t busines_lock; //业务锁/* 结构体定义 */typedef struct{void * (*BUSINES_ADDR)(void *); //业务地址 函数指针 哪个业务void * BUSINES_ARG; //业务参数 socket}busines_t; //业务类型//业务传给线程处理typedef struct{/*线程池阈值*/int thread_shutdown; //线程池开关0/1 , 根据开关决定是否结束线程池int thread_max; //线程最大值int thread_min; //线程最小值int thread_busy;//繁忙线程数int thread_alive; //有效线程数量int thread_exitcode; //用于线程缩减pthread_t * customer_tids; //消费者线程tid数组pthread_t manager_tid; //保存管理者线程tidbusines_t * busines_queue; //保存业务的唤醒队列int b_front; //业务队列头索引int b_rear; //业务队列尾索引int b_max; //业务队列最大数int b_cur; //业务队列当前业务数pthread_mutex_lock thread_lock; //互斥锁pthread_cond_t not_full; //生产者条件变量pthread_cond_t not_empty; //消费者条件变量}thread_pool_t; //线程池类型/* 服务端模型模块分析 */void thread_pool_error(const char * strerror , int exitcode , int errno);//如果errno==0则是标准错误处理,如果errno>0则是线程函数错误处理 将错误处理分成两类int thread_pool_net_init(void); //成功返回serverfd , 失败返回-1 //服务端网络初始化int thread_pool_epoll_init(int Sockfd); //成功返回监听树描述符,失败返回-1 //服务端epoll初始化 且监听serverfdthread_pool_t * thread_pool_create(int Max , int Min , int QueMax); //线程池创建初始化,成功返回线程池地址int thread_pool_destroy(thread_pool_t *); //释放销毁线程池资源 int thread_pool_epoll_listen(int epfd , thread_pool_t * p,int sockfd);//负责网络IO事件监听,辨别就绪并添加任务 producerint thread_pool_add_busines(thread_pool_t * , busines_t); //生产者向线程池中添加业务void * thread_pool_customer_job(void * arg); //消费者默认工作,创建时传递线程池参数 从任务队列中取任务void * thread_pool_manager_job(void * arg); //管理者默认工作,创建时传递线程池参数 需要线程池中的阈值int if_thread_alive(pthread_t); //测试一个线程是否存活 ? 返回0表示线程已经结束,1表示线程存活void * BUSINES_ACCEPT(void * arg); //TCP连接业务void * BUSINES_RESPONSE(void * arg); //业务处理

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。