1.ProxySQL 的线程
ProxySQL 由多个模块组成, 是一个多线程的 daemon 类程序. 每个模块都有一个或多个线程去执行任务.
例如, 以下是刚启动 ProxySQL 时的进程情况, 一个 main 进程, 一个主线程, 21 个线程.
- [root@s1 ~]# pstree | grep proxy
- |-proxysql---proxysql---21*[{proxysql}]
下面是正常运行时使用的线程列表:
1.1 Main thread
这其实是一个进程, 该进程只负责引导, 启动核心模块以及启动其它核心线程.
1.2 Admin thread
该线程负责以下几件事:
初始化并引导启动 Admin 接口.
从磁盘数据库或配置文件中加载配置, 为 ProxySQL 的运行提供环境.
启动一个监听者, 让其负责监听并接受到 Admin 接口的新连接, 并为每个这样的连接创建一个新线程.
所以, 每连接一次 admin 接口, 就会新生成一个线程. 每次退出 admin 接口时, 减去一个线程.
1.3 MySQL workers
mysql-threads 线程负责处理 MySQL 流量, 包括所有来自客户端的连接以及所有到后端服务器节点的连接. 也就是: 用少量线程处理任意多数量的连接.
MySQL workers 线程在相同的端口上进行监听. 当新客户端发起连接请求, 其中一个 MySQL worker 线程将成功接受该连接, 并创建一个 MySQL 会话(session): 客户端和会话绑定在该 worker 线程上, 直到连接断开. 换句话说, 在断开连接之前, 某客户端的所有连接总是被同一个 worker 线程处理.
默认情况下, MySQL worker 的线程数量为 4.
- mysql> select @@mysql-threads;
- +-----------------+
- | @@mysql-threads |
- +-----------------+
- | 4 |
- +-----------------+
mysql-threads 变量修改后, 必须重启 ProxySQL 才能生效, 这是少有的需要重启的变量之一(另一个是 mysql-stacksize). 例如, 修改为 8 个 mysql worker 线程.
- set mysql-threads=8;
- save mysql variables to disk;
- select * from runtime_global_variables
- where variable_name='mysql-threads';
- +---------------+----------------+
- | variable_name | variable_value |
- +---------------+----------------+
- | mysql-threads | 4 |
- +---------------+----------------+
- service proxysql stop
- service proxysql start
- select * from runtime_global_variables
- where variable_name='mysql-threads';
- +---------------+----------------+
- | variable_name | variable_value |
- +---------------+----------------+
- | mysql-threads | 8 |
- +---------------+----------------+
1.4 MySQL auxiliary threads
这些线程其实就是空闲线程(idle threads).
如果 proxysql 使用 --idle-threads 选项启动, 每个 worker 线程都会伴随启动一个 auxiliary 线程. 每个 worker 线程以及它的 auxiliary 线程一起工作: 第一个线程处理活动的连接, 并将所有的空闲连接派遣到第二个线程上, 但第二个线程只要等待到了发生在空闲连接上的一个事件(或超时), 就会将连接还给第一个线程.
当活动的客户端连接数量远少于空闲客户端连接数量时, 强烈建议使用 "idle threads". 这使得 ProxySQL 可以处理几十万个连接(测试时是 100W 个连接).
1.5 Monitor 模块相关的线程
monitor 模块有自己的线程管理系统, 还有自己的线程池. 正常情况下, monitor 模块有以下几个线程:
一个 master 线程, 负责生成, 协调其它 monitor 相关的线程.
一个负责监控 connect 的线程.
一个负责监控 ping 的线程.
一个负责监控 read_only 的线程.
一个负责监控 replication lag 的线程.
一个线程池提供 monitor worker 线程, 上面每个监控线程都是任务的生产者, worker 线程从任务队列消费一个任务并执行该任务. 该线程池初始时默认为 mysql thread 的两倍.
线程池负责执行所有的检查任务, 并通过以上各调度线程来监控调度情况. 线程池会基于监控队列中待检查的数量多少而自动增长, 收缩. 基于检查的结果, 会使用相同的线程对结果进行处理, 例如避开一个节点, 重新配置一个主机组.
1.6 Query Cache purge thread
该线程是需要时才生成的, 它扮演的是垃圾收集器, 回收查询缓存. 通过垃圾收集器, 可保证在客户端等待响应的过程中绝不会回收缓存.
1.7 其它线程
在 ProxySQL 运行过程中, 偶尔会派生临时线程, 这些临时线程是为了向后端发送 KILL 语句, 以便杀掉后端服务器上对查询长时间无响应的查询线程.
此外, ilbmariadbclient 库还会使用一些后台线程, 这些线程是为了和后端 MySQL server 进行一些特定的异步交互任务.
还有一些模块, 例如内置的 Http server, 正处于实验阶段的 cluster,ClickHouse Server,SQLite3 Server, 如果启用了这些功能, 则会按需创建它们对应的线程.
2.ProxySQL 的线程池
在 ProxySQL 中, 有两个地方使用了线程池:
快速建立和后端 MySQL 的连接: ProxySQL 为了尽快和后端 MySQL 建立新的 TCP 连接, 使用了一个线程池来等待 accept()返回新连接.
Monitor 模块: 为了尽快执行各监控线程生产的监控任务, monitor 模块提供了一个 monitor worker 线程池, 可以快速从任务队列中消费任务.
需要注意的是, 正常情况下, MySQL worker 线程是最繁忙, 最消耗 CPU 资源的部分, 但在一个极其繁忙的环境下, monitor 模块需要监控的连接数过多, 消耗的 CPU 也是不可忽视的.
3.ProxySQL 的连接池
ProxySQL 同样有两个连接池, 和线程池部分是对应的.
3.1 快速连接到后端 MySQL 节点
线程池是为了快速和后端建立新的 TCP 连接, 而这里的连接池是为了快速和后端建立连接.
ProxySQL 使用一个连接池来存放一定数量的 "之前已经和某后端建立连接, 但当前是空闲连接" 的连接. 当需要向这些连接对应的后端发送新的数据包时, 可以快速地取回连接, 因为这些连接早已经被打开.
当应用程序发送了一个 MySQL 请求给 ProxySQL 时, ProxySQL 首先解析要路由到哪个后端, 如果连接池中已经有和该后端的连接, 将重用该连接, 否则将创建一个新的和后端的连接.
当处理完客户端的请求后, 连接会还回主机组管理器(HostGroup Manager). 如果主机组管理器判断了该连接是可以被安全共享的, 且连接池未满, 则该连接会放进连接池.
放进连接池的连接都是空闲连接, 正在使用的连接是不可能进入连接池的. ProxySQL 会定期发送 ping 消息来维持空闲连接. 如果某连接从上一次 ping 之后, 如果还没有被使用, 则该连接被定义为空闲连接. 对于空闲连接 ping 的时间间隔由变量 mysql-ping_interval_server_msec 控制.
但是, 不是所有的未使用的连接都会放进连接池. 该变量用来控制某后端的空闲连接和最大总连接数的百分比. 对于每个 hostgroup/backend, 主机组管理器只会保持连接池中的最大连接数为
mysql-free_connections_pct * mysql_servers.max_connections / 100
. 池中的每个空闲连接都通过间断性的 ping 来维持它的打开状态.
当一个连接放回连接池时, 会计算这个连接之后还能处理多少个语句, 当处理的语句数量达到该阈值后, 将关闭该连接 (v1.4.3 之前) 或者重置该连接(从 v1.4.4 开始).
3.1.1 相关变量
mysql-ping_interval_server_msec
ProxySQL 为了维持和后端的空闲连接, 每隔一段时间发送一次 ping, 该变量指定发起 ping 的时间间隔. 默认值为 10000 毫秒(即 10 秒).
mysql-ping_timeout_server
ProxySQL 为了维持和后端的空闲连接, 每隔一段时间发送一次 ping. 该变量指定 ping 得到回复的超时时间. 默认值为 200 毫秒.
mysql-connection_max_age_ms
当该变量设置的值大于 0 时 (单位毫秒), 如果某个空闲连接(当前没有任何会话使用) 的空闲时长超过了这里设置的值, 则这个连接会关闭. 默认值为 0, 表示不会因为存活时间而关闭空闲连接.
3.2 Monitor 模块的连接池
Monitor 有它自己的连接池. 当连接池中空闲连接的空闲时长达到了
3 * mysql-monitor_ping_interval
(毫秒)后, 该空闲连接将自动被 purge.
变量
mysql-monitor_ping_interval
的默认值为 1 分钟(60000 毫秒), 所以, monitor 连接池中的空闲连接默认最长维持 3 分钟.
来源: https://www.cnblogs.com/f-ck-need-u/p/9281909.html