百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

MySQL:网络连接框架简析

bigegpt 2024-08-05 11:31 7 浏览


一直对这部分不太了解,稍微看了一下,但由于知识储备有限,错误在所难免。


总的看起来MySQL在这部分依旧使用了常规的 reactor+线程池高并发网络模型,这里我们以poll为列,有如下特点:

  • 主reactor通过poll对listen fd的POLLIN event进行监控,并且设置了非阻塞。
  • 如果主reactor收到新的连接请求,在线程池中获取一个线程
  • 如果线程池中没有可用的线程,则新建线程
  • 新的线程对同样通过ppoll对连接fd的POLLIN event进行监控,并且负责实际业务逻辑的处理。

貌似看起来大佬的手法都是通用的,都是按照一定模式写出来的。当然实际上涉及的东西还是非常多,但是这里我们仅仅了解网络框架部分,对于线程池\vio通信模块\net协议模块不做讨论,因为我也不了解,这里主要看看网络框架。

简要流程分析

  • network_init 这部分主要对实例的端口进行bind->listen,并且设置好poll监控的event为 POLLIN,同时会将listen fd设置为非堵塞,这里还需要注意一点socket的属性设置了SO_REUSEADDR,这表明对于处于TIME_WAIT状态的连接,MySQLD客户端的端口能够快速重用,而不需要等待2MSL超时。
  • connection_event_loop 和所有的网络框架一样,这里需要开启主循环了。循环的目的当然就是不断监控poll的POLLIN和accpet 后返回连接fd,如果打开函数Mysqld_socket_listener::listen_for_connection_event就能看到一上来就是poll开始了。最后会将accpet的连接fd封装到Channel_info返回。并且随后本函数还负责了新线程的建立,这里可以考虑为我们的session即将诞生。随后调用的就是这里主要开始调用Per_thread_connection_handler::add_connection。首先会在线程池中获取一个已经建立好的线程来进行处理,这里和我们的参数thread_cache有关,这种缓存的线程通常在函数Per_thread_connection_handler::block_until_new_connection处堵塞,等待唤醒,一旦有足够的缓存的线程就会唤醒并且完成出队操作。当然了,如果线程吃没有缓存的线程,则新建线程用于新会话的处理。完成这一步后我们的主reactor线程也就是我们main线程就会(注意不是Innodb的master线程)堵塞在poll上等待新的连接请求的到来,来一个处理一个。等待如下,
main 
->mysqld_main
-> Connection_acceptor<Mysqld_socket_listener>::connection_event_loop
->Mysqld_socket_listener::listen_for_connection_event
->poll ()
  • handle_connection 这里新建的线程就是处理和连接fd相关的写入信息了,注意这里是一个for死循环,这是因为对于缓存的线程来讲,需要堵塞在block_until_new_connection,然后等待下一次拿出来处理新的连接请求。同时需要注意来到这里实际上TCP协议的3次握手,但是MySQL net协议的握手还没有完成。已经完成了如下抓包:

对于用户会话线程通常叫做thread_one_connection,接着会调用thd_prepare_connection->login_connection将准备对连接fd进行ppoll的超时参数设置为connect_timeout指定的值,也就是言外之意connect_timeout是在处理连接请求的时候生效的参数。然后thd_prepare_connection->login_connection->check_connection,在函数check_connection中完成主要任务是:

  1. ip_to_hostname函数:host_cache和ip相关的反解析动作,并且判断是否超过了max_connection_errors 参数,如果们设置 skip-host-cache skip-name-resolve就不会有这个动作。
  2. acl_check_host 函数:应该是对登陆网段等进行鉴定,是否符合登陆网段的需求,主要来自mysql.user表。
  3. acl_authenticate 函数:(Perform the handshake, authorize the client)这里应该就是要进行MySQL net的握手了,并且完成如密码认证等操作。如果是native password则调用native_password_authenticate进行密码验证。
  4. check_and_update_password_lock_state函数:主要完成对密码错误登陆次数/密码锁定天数的判定,如果不符合要求则报错Account is blocked for %s day(s) (%s day(s) remaining) due to %u consecutive failed logins. Use FLUSH PRIVILEGES or ALTER USER to reset."

在login_connection的末尾会将连接fd的ppoll的timeout参数设置为read_timeout/write_timeout。最后接下来就是进行命令处理的环节了。也就是do_command。通常我们的会话就堵塞在这里等待客户端命令的到来如下:

#0 0x00007ffff5e2dcff in ppoll () from /lib64/libc.so.6
#1 0x00000000058bba82 in vio_io_wait (vio=0x7fffa801b990, event=VIO_IO_EVENT_READ, timeout=28800000) at /newdata/mysql-8.0.23/vio/viosocket.cc:847
#2 0x00000000058ba4c5 in vio_socket_io_wait (vio=0x7fffa801b990, event=VIO_IO_EVENT_READ) at /newdata/mysql-8.0.23/vio/viosocket.cc:105
#3 0x00000000058bc45b in vio_ssl_read (vio=0x7fffa801b990, buf=0x7fffa800e900 "\001", size=4) at /newdata/mysql-8.0.23/vio/viossl.cc:294
#4 0x00000000039bee83 in net_read_raw_loop (net=0x7fffa800d430, count=4) at /newdata/mysql-8.0.23/sql-common/net_serv.cc:1336
#5 0x00000000039bf1ef in net_read_packet_header (net=0x7fffa800d430) at /newdata/mysql-8.0.23/sql-common/net_serv.cc:1419
#6 0x00000000039c050a in net_read_packet (net=0x7fffa800d430, complen=0x7fffdc4fb9c8) at /newdata/mysql-8.0.23/sql-common/net_serv.cc:2010
#7 0x00000000039c0789 in net_read_uncompressed_packet (net=0x7fffa800d430, len=@0x7fffdc4fba08: 140736889600560) at /newdata/mysql-8.0.23/sql-common/net_serv.cc:2085
#8 0x00000000039c0a77 in my_net_read (net=0x7fffa800d430) at /newdata/mysql-8.0.23/sql-common/net_serv.cc:2161
#9 0x0000000003e23f6e in Protocol_classic::read_packet (this=0x7fffa801a780) at /newdata/mysql-8.0.23/sql/protocol_classic.cc:1404
#10 0x0000000003e25179 in Protocol_classic::get_command (this=0x7fffa801a780, com_data=0x7fffdc4fbb00, cmd=0x7fffdc4fbb2c) at /newdata/mysql-8.0.23/sql/protocol_classic.cc:2975
#11 0x00000000037f063d in do_command (thd=0x7fffa800b980) at /newdata/mysql-8.0.23/sql/sql_parse.cc:1266
#12 0x00000000039c5c91 in handle_connection (arg=0xbe8d880) at /newdata/mysql-8.0.23/sql/conn_handler/connection_handler_per_thread.cc:301
  • 其他 当然我们注意的是,读取命令和返回数据给客户端是通过参数read_timeout/write_timeout控制,但是等待命令的到来是通过参数wait_timeout/interactive_timeout。但是他们同样作用于连接fd的ppoll的timeout参数上。

最后:

这是今年最后一次发公众号,感谢领导同事朋友对工作的支持。顺便灌个鸡汤"让我们一起带着好奇,带着梦想,向星辰大海进发!",来年再战了。


相关推荐

Redis集群对比:主从复制、哨兵模式、Cluster一文看懂所有优缺点

在分布式系统中,Redis作为高性能的内存数据库,其集群方案的选择直接影响到系统的稳定性、可用性和扩展性。本文将全面对比Redis的三种主流集群方案:主从复制、哨兵模式和Cluster模式,帮助开发者...

redis的主从复制,读写分离,主从切换

当数据量变得庞大的时候,读写分离还是很有必要的。同时避免一个redis服务宕机,导致应用宕机的情况,我们启用sentinel(哨兵)服务,实现主从切换的功能。redis提供了一个master,多个sl...

# Redis 入门到精通(九)-- 主从复制(3)

#Redis入门到精通(九)--主从复制(3)##一、redis主从复制-常见问题(1)###1、伴随着redis系统的运行,master的数据量会越来越大,一旦master重启...

redis - 主从复制(Redis主从复制时序图)

1引言在上一篇文章中,我们了解了Redis两种不同的持久化方式,Redis服务器通过持久化,把Redis内存中持久化到硬盘当中,当Redis宕机时,我们重启Redis服务器时,可以由RDB文件或AO...

# Redis 入门到精通(九)-- 主从复制(2)

#Redis入门到精通(九)--主从复制(2)##一、redis主从复制--数据同步阶段注意事项###1、数据同步阶段master说明1)如果master数据量巨大,数据同步阶段应...

Redis主从复制(redis主从复制主节点挂了)

介绍Redis有两种不同的持久化方式,Redis服务器通过持久化,把Redis内存中持久化到硬盘当中,当Redis宕机时,我们重启Redis服务器时,可以由RDB文件或AOF文件恢复内存中的数据。不过...

深入解析 Redis 集群的主从复制实现方式

在互联网大厂的后端开发领域,Redis作为一款高性能的内存数据库,被广泛应用于缓存、消息队列等场景。而Redis集群中的主从复制机制,更是保障数据安全、实现读写分离以及提升系统性能的关键所在。今...

Redis主从架构详解(redis主从架构高可用如何实现)

Redis主从架构搭建Redis主节点配置创建主节点目录(/opt/redis-master),复制redis.conf到该目录下,redis.conf配置项修改#后台启动daemonizeyes...

抖音“四大包塘战神”:承包了全网的快乐

在抖音钓鱼垂类领域,"包塘战神"军团正掀起一场黑色幽默风暴。空军华、大表坑、李赔光、透心良四位创作者,以承包鱼塘为舞台,用连续翻车的钓鱼直播构筑起流量奇观。当钓鱼佬在抖音集体转型喜剧人...

ORACLE 11G RAC 安装-通过VM配置共享磁盘

简介:在自己的电脑上通过VM软件搭建Oracle11GRAC,通过修改VM的参数文件来实现磁盘共享!目标:搭建RAC环境实现:使用VMwareWorkstation8.0.0+ORACLE...

Linux操作系统安全配置(linux系统安全配置包括)

一、服务相关命令systemctlenable服务名#开机自启动systemctldisable服务名#禁用开机自启动systemctlstop服务名#停止服务systemctls...

关于Linux性能调优中网络I/O的一些笔记

写在前面和小伙伴分享一些Linux网络优化的笔记,内容很浅,可以用作入门博文内容结合《Linux性能优化》读书笔记整理涉及内容包括常用的优化工具(mii-tool,ethtool,ifconfig,i...

从 Sonatype Nexus Repository Manager 迁移到 Artifactory

1.Nexus1.1下载下载链接:https://help.sonatype.com/repomanager3/product-information/download/download-archiv...

Ubuntu20安装zabbix5.0企业监控系统亲测教程

前言示例主机:zabbix10.0.100.10,将安装在UbuntuServer上教程说明:因使用官方教程无法安装成功,所以本教程与官方教程有所不同安装前提:已安装UbuntuServer2...

Linux内核设计与实现—进程管理(linux内核程序设计)

进程进程就是处于执行期的程序(目标码存放在某种存储介质上)。进并不仅仅局限于一段可执行程序代码(Unix称其为代码段,textsection)。通常进程还要包含其他资源,像打开的文件,挂起的信号,...