目录
one-connection-per-thread
线程池与epoll
线程池函数调用关系
one-connection-per-thread函数调用关系
首页 数据库 mysql教程 MySQL详解(8)----------MySQL线程池总结(二)_MySQL

MySQL详解(8)----------MySQL线程池总结(二)_MySQL

Jun 01, 2016 pm 12:59 PM
线程

这篇文章是对上篇文章的一个补充,主要围绕以下两点展开,one-connection-per-thread的实现方式以及线程池中epoll的使用。

one-connection-per-thread

根据scheduler_functions的模板,我们也可以列出one-connection-per-thread方式的几个关键函数。

static scheduler_functions con_per_functions=

{ max_connection+1, // max_threads

NULL,

NULL,

NULL, // init

Init_new_connection_handler_thread, // init_new_connection_thread

create_thread_to_handle_connection, // add_connection

NULL, // thd_wait_begin

NULL, // thd_wait_end

NULL, // post_kill_notification

one_thread_per_connection_end, // end_thread

NULL // end

};
登录后复制

1.init_new_connection_handler_thread

这个接口比较简单,主要是调用pthread_detach,将线程设置为detach状态,线程结束后自动释放所有资源。

2.create_thread_to_handle_connection

这个接口是处理新连接的接口,对于线程池而言,会从thread_id%group_size对应的group中获取一个线程来处理,而one-connection-per-thread方式则会判断是否有thread_cache可以使用,如果没有则新建线程来处理。具体逻辑如下:

(1).判断缓存的线程数是否使用完(比较blocked_pthread_count 和wake_pthread大小)

(2).若还有缓存线程,将thd加入waiting_thd_list的队列,唤醒一个等待COND_thread_cache的线程

(3).若没有,创建一个新的线程处理,线程的入口函数是do_handle_one_connection

(4).调用add_global_thread加入thd数组。

3.do_handle_one_connection

这个接口被create_thread_to_handle_connection调用,处理请求的主要实现接口。

(1).循环调用do_command,从socket中读取网络包,并且解析执行;

(2). 当远程客户端发送关闭连接COMMAND(比如COM_QUIT,COM_SHUTDOWN)时,退出循环

(3).调用close_connection关闭连接(thd->disconnect());

(4).调用one_thread_per_connection_end函数,确认是否可以复用线程

(5).根据返回结果,确定退出工作线程还是继续循环执行命令。

4.one_thread_per_connection_end

判断是否可以复用线程(thread_cache)的主要函数,逻辑如下:

(1).调用remove_global_thread,移除线程对应的thd实例

(2).调用block_until_new_connection判断是否可以重用thread

(3).判断缓存的线程是否超过阀值,若没有,则blocked_pthread_count++;

(4).阻塞等待条件变量COND_thread_cache

(5).被唤醒后,表示有新的thd需要重用线程,将thd从waiting_thd_list中移除,使用thd初始化线程的thd->thread_stack

(6).调用add_global_thread加入thd数组。

(7).如果可以重用,返回false,否则返回ture

线程池与epoll

在引入线程池之前,server层只有一个监听线程,负责监听mysql端口和本地unixsocket的请求,对于每个新的连接,都会分配一个独立线程来处理,因此监听线程的任务比较轻松,mysql通过poll或select方式来实现IO的多路复用。引入线程池后,除了server层的监听线程,每个group都有一个监听线程负责监听group内的所有连接socket的连接请求,工作线程不负责监听,只处理请求。对于overscribe为1000的线程池设置,每个监听线程需要监听1000个socket的请求,监听线程采用epoll方式来实现监听。

Select,poll,epoll都是IO多路复用机制,IO多路复用通过一种机制,可以监听多个fd(描述符),比如socket,一旦某个fd就绪(读就绪或写就绪),能够通知程序进行相应的读写操作。epoll相对于select和poll有了很大的改进,首先epoll通过epoll_ctl函数注册,注册时,将所有fd拷贝进内核,只拷贝一次不需要重复拷贝,而每次调用poll或select时,都需要将fd集合从用户空间拷贝到内核空间(epoll通过epoll_wait进行等待);其次,epoll为每个描述符指定了一个回调函数,当设备就绪时,唤醒等待者,通过回调函数将描述符加入到就绪链表,无需像select,poll方式采用轮询方式;最后select默认只支持1024个fd,epoll则没有限制,具体数字可以参考cat /proc/sys/fs/file-max的设置。epoll贯穿在线程池使用的过程中,下面我就epoll的创建,使用和销毁生命周期来描述epoll在线程中是如何使用的。

线程池初始化,epoll通过epoll_create函数创建epoll文件描述符,实现函数是thread_group_init;端口监听线程监听到请求后,创建socket,并创建THD和connection对象,放在对应的group队列中;工作线程获取该connection对象时,若还未登录,则进行登录验证若socket还未注册到epoll,则调用epoll_ctl进行注册,注册方式是EPOLL_CTL_ADD,并将connection对象放入epoll_event结构体中若是老连接的请求,仍然需要调用epoll_ctl注册,注册方式是EPOLL_CTL_MODgroup内的监听线程调用epoll_wait来监听注册的fd,epoll是一种同步IO方式,所以会进行等待请求到来时,获取epoll_event结构体中的connection,放入到group中的队列线程池销毁时,调用thread_group_close将epoll关闭。

备注:

1.注册在epoll的fd,若请求就绪,则将对应的event放入到events数组,并将该fd的事务类型清空,因此对于老的连接请求,依然需要调用epoll_ctl(pollfd, EPOLL_CTL_MOD, fd, &ev)来注册。

线程池函数调用关系

(1)创建epoll

tp_init->thread_group_init->tp_set_threadpool_size->io_poll_create->epoll_create

(2)关闭epoll

tp_end->thread_group_close->thread_group_destroy->close(pollfd)

(3)关联socket描述符

handle_event->start_io->io_poll_associate_fd->io_poll_start_read->epoll_ctl

(4)处理连接请求

handle_event->threadpool_process_request->do_command->dispatch_command->mysql_parse->mysql_execute_command

(5)工作线程空闲时

worker_main->get_event->pthread_cond_timedwait

等待thread_pool_idle_timeout后,退出。

(6)监听epoll

worker_main->get_event->listener->io_poll_wait->epoll_wait

(7)端口监听线程

main->mysqld_main->handle_connections_sockets->poll

one-connection-per-thread函数调用关系

(1) 工作线程等待请求

handle_one_connection->do_handle_one_connection->do_command->

my_net_read->net_read_packet->net_read_packet_header->net_read_raw_loop->

vio_read->vio_socket_io_wait->vio_io_wait->poll

备注:与线程池的工作线程有监听线程帮助其监听请求不同,one-connection-per-thread方式的工作线程在空闲时,会调用poll阻塞等待网络包过来;

而线程池的工作线程只需要专心处理请求即可,所以使用也更充分。

(2)端口监听线程

与线程池的(7)相同

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
2 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

8核16线程是什么意思? 8核16线程是什么意思? Feb 02, 2023 am 11:26 AM

8核是指CPU有8颗物理核心,16线程是指CPU最多同时可以有16个线程处理任务。核心数和线程数是电脑CPU的重要性能指标,CPU的核心数越高处理速度就越高;线程数越多越有利于同时运行多个程序,因为线程数等同于在某个瞬间CPU能同时并行处理的任务数。多线程可最大限度地实现宽发射、乱序的超标量处理,提高处理器运算部件的利用率,缓和由于数据相关或Cache未命中带来的访问内存延时。

C++并发编程:如何避免线程饥饿和优先级反转? C++并发编程:如何避免线程饥饿和优先级反转? May 06, 2024 pm 05:27 PM

为避免线程饥饿,可以使用公平锁确保资源公平分配,或设置线程优先级。为解决优先级反转,可使用优先级继承,即暂时提高持有资源线程的优先级;或使用锁的提升,即提升需要资源线程的优先级。

C++并发编程:如何进行线程终止和取消? C++并发编程:如何进行线程终止和取消? May 06, 2024 pm 02:12 PM

C++中线程终止和取消机制包括:线程终止:std::thread::join()阻塞当前线程直到目标线程完成执行;std::thread::detach()从线程管理中分离目标线程。线程取消:std::thread::request_termination()请求目标线程终止执行;std::thread::get_id()获取目标线程ID,可与std::terminate()一起使用,立即终止目标线程。实战中,request_termination()允许线程决定终止时机,join()确保在主线

什么是程序运行时指令流的最小单位 什么是程序运行时指令流的最小单位 Aug 23, 2022 pm 02:16 PM

“线程”是程序运行时指令流的最小单位。进程是指一个具有一定独立功能的程序,而线程是进程的一部分,描述指令流执行状态;线程是进程中的指令执行流的最小单位,是CPU调度的基本单位。一个线程是一个任务(一个程序段)的一次执行过程;线程不占有内存空间,它包括在进程的内存空间中。在同一个进程内,多个线程共享进程的资源;一个进程至少有一个线程。

Java错误:JavaFX线程卡顿错误,如何处理和避免 Java错误:JavaFX线程卡顿错误,如何处理和避免 Jun 24, 2023 pm 05:52 PM

在进行JavaFX应用程序开发的过程中,我们常常会遇到JavaFX线程卡顿错误。这种错误的严重程度不同,可能会对程序的稳定性和性能产生不利的影响。为了保证程序的正常运行,我们需要了解JavaFX线程卡顿错误的原因和解决方法,以及如何预防这种错误的发生。一、JavaFX线程卡顿错误的原因JavaFX是一个多线程的UI应用程序框架,它允许程序在后台线程中执行长时

Go语言中线程和进程的区别解析 Go语言中线程和进程的区别解析 Apr 03, 2024 pm 01:39 PM

Go语言中的进程和线程:进程:独立运行的程序实例,拥有自己的资源和地址空间。线程:进程内的执行单元,共享进程资源和地址空间。特点:进程:开销大,隔离性好,独立调度。线程:开销小,共享资源,内部调度。实战案例:进程:隔离长时间运行的任务。线程:并发处理大量数据。

go语言中协程与线程的区别是什么 go语言中协程与线程的区别是什么 Feb 02, 2023 pm 06:10 PM

区别:1、一个线程可以多个协程,一个进程也可以单独拥有多个协程;2、线程是同步机制,而协程则是异步;3、协程能保留上一次调用时的状态,线程不行;4、线程是抢占式,协程是非抢占式的;5、线程是被分割的CPU资源,协程是组织好的代码流程,协程需要线程来承载运行。

Microsoft计划在Windows上的Outlook经典应用程序中引入AI驱动的Copilot Microsoft计划在Windows上的Outlook经典应用程序中引入AI驱动的Copilot Oct 19, 2023 pm 11:13 PM

Microsoft显然不会将其强大的人工智能支持的Copilot工具保留为新应用程序的独家功能。现在,该公司刚刚宣布计划在Windows上的Outlook经典应用程序中引入Copilot。正如其365路线图网站上发布的那样,预览将于明年<>月开始,直到<>月在当前频道的桌面上在全球范围内推出。Copilot是一种生产力工具,它使用大型语言模型(LLM)来帮助用户完成编写电子邮件、汇总文档和翻译语言等任务。它的主要功能之一是它能够总结电子邮件

See all articles