对象池、连接池的意义

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 对象池就是一个在程序启动的时候先创建好若干个可以重复使用的对象。 当程序其他地方需要使用该类型对象时,不再是向系统申请创建,而是向池发出请求。 池将会从池内发配出一个对象提供使用,当程序使用完毕后,需要将对象归还给对象池做管理。

这次我们来讲讲对象池、连接池的意义,在此之前我们先了解学习一些其他的基础知识,以便我们结合理解池的意义。


#nginx与php-fpm的进程模型


nginx采用多进程模型,启动之后的进程将包含一个master和多个worker进程。 master是worker的父进程,主要职责是用来管理worker进程的。


  • 向worker进程发送信号,如通知退出
  • 监控worker状态,当worker退出后(无论正常异常),可以重新启动新的worker。


可以实现从容重启:master进程在接收到信号后,会先重新加载配置,然后再启动新进程开始接收新请求,并向所有老进程发送信号告知不再接收新请求并在处理完所有未处理完的请求后自动退出。


worker进程负责处理请求,如果是静态文件则可以直接处理完,如果是php程序还需要调用php来处理,当php处理完成时获取php的返回,并返回给客户端。 采用的是异步非堵塞,当调用php的时候不会堵塞等待,会抽空处理下一个请求,当php处理完成时恢复之前的请求并返回给客户端。 php-fpm是php-cgi的管理器,在php >= 5.3.3就已经集成在php中了。 它的出现提供了更好的php管理方式


  • 可以平滑停止/启动php进程(重载配置生效)
  • 可以配置监控多个端口和使用不同的配置


php脚本的解释器是php-cgi php-fpm是一个管理器,管理对象是php-cgi php-fpm实现了fastcgi协议,当php-fpm启动时,会启动多个cgi解释器进程。 web服务器可以发送数据给php-fpm,php-fpm再把数据发给php-cgi处理。(跟nginx发送数据给php-fpm类似)


#常驻内存下程序的对象回收


常驻内存程序是指把自己装入内存后将控制返回给操作系统,直到运行结束、异常、用户手动退出才会中断运行的程序。 当程序运行时,对象和变量将会一直存在。除非在程序中释放销毁。


#高并发下频繁new对象的资源占用


当我们new一个对象的时候,需要先经过这几个步骤:类加载检查、分配内存空间、设置类的基本信息、调用初始化构造函数。


首先我们看看构造函数这一块,这是在代码中按我们的需求和意愿编写的。 在这一块中我们经常会做一些配置检测、数据初始化、数据库连接(网络io)等。


接下来是分配内存空间 OS的内存分配器一般是预先向OS申请一大段内存。然后每次分配时,再将里面的一小段标记为已分配,释放的时候再标记成未分配。 由于是有很多程序在运行,所以分配和释放会交替存在,得到的结果可能是 分配1段-未分配1段-分配2段-未分配2段 一个一个的未分配就是内存碎片,会占用额外的内存,碎片不一定可以马上被重复使用(当分配不出连续内存时,需要向OS申请更多的内存)


同时,创建和销毁对象时,OS都需要做一些处理工作,也会产生资源占用。


new太多对象,然后导致cpu负载上线让全站死机的概念


若程序未产生IO(网络请求、读写文件等),执行时间等于cpu的占用时间。 频繁地创建销毁对象将会占用更多cpu资源,高并发时容易导致cpu长期处于高负载运行状态。


什么是对象池


对象池就是一个在程序启动的时候先创建好若干个可以重复使用的对象。 当程序其他地方需要使用该类型对象时,不再是向系统申请创建,而是向池发出请求。 池将会从池内发配出一个对象提供使用,当程序使用完毕后,需要将对象归还给对象池做管理。


对象池服务可以减少从头创建每个对象的系统开销。


大并发下多个mysql连接导致mysql繁忙全站崩溃


<?php
function db(){
    return mysqli_connect("localhost","root","root"); 
}
for ($i=0; $i < 10000; $i++) { 
    $name  = "db{$i}";
    $$name = db();
}


这一个demo将会产生报错:Warning: mysqli_connect(): (08004/1040): Too many connections 我们习惯性地在PHP脚本中不会主动关闭mysql连接,而是等到脚本运行完毕之后再由gc自动回收。在这个期间将会继续占用连接资源,而连接资源的数量又是有限制的,所以会更快出现连接不够用的情况。 处理会影响程序的运行,同时还将可能导致全站崩溃


  • mysql是一个连接创建一个线程处理。
  • 创建销毁mysql线程需要的内存等性能消耗、线程缓存命中率下降
  • mysql底层几乎在同时需要处理几百个线程提交的查询请求,而cpu一次只能处理一条指令,并且数据库查询需要产生IO,在IO期间cpu将会切换上下文处理其他的请求,当cpu频繁切换上下文,性能抖动,发生性能下降甚至宕机的情况。


连接池 保护mysql不崩溃


连接池是将已经创建好的连接保存在池中,当有请求来时,直接使用已经创建好的连接对数据库进行访问。


<?php
class Pool{
    private $pool = [];
    private $min = 5;
    private $max = 100;
    private $now;
    public function __construct()
    {
        // 在池创建的时候就先创建好一些连接
        for ($i = 0 ; $i < $this->min; $i++){
            $this->pool[] = mysqli_connect("localhost","root","root");
            $this->now++;
        }
    }
    public function get()
    {
        // 这里要判断当前池还有没有空闲的
        // 若没有,则判断当前已经提供的服务数量大不大于最大数量   如果还没有达到最大数量  可以向系统再申请一个资源到池中
        // 如果已经达到最大数量,并且池内没有服务了,则进行短暂等等看看有没有
        // 需要销毁避免同一个连接多处使用,会冲突
        $connect = array_shift($this->pool);
        return $connect;//伪代码
    }
    public function recovery($connect)
    {
        $this->pool[] = $connect;
    }
}


因为连接池需要长期保持在线,在传统的php脚本中不支持,在swoole中可以常驻内存运行,即可使用连接池


这样省略了创建连接和销毁连接的过程。这样性能上得到了提高。 然而除了性能上的提高外,还有一个意义也很重要:保护服务稳定运行,不发生全站崩溃。 在上面一点我们已经提到,更多的链接将会导致cpu频繁切换上下文,性能抖动,严重情况时将会全站崩溃。 假设本来我们的服务器配置是可以保证1000个连接同时稳定运行,突然某一时刻有3000个人并发,导致连接不够用,那么是保证原有1000人都正常运行好,还是让这3000人争抢资源最终导致机器响应不了全站崩溃好呢?


#连接池的意义此时才得以体现,我们设置连接池的最大数量为机器能承受并且稳定运行的最大数量。


当已经有这么多的数量在服务的时候,后面的请求申请连接资源时需要进行短暂的等待,若时间到了还是没有空余连接提供,则需要熔断服务,返回给客户端失败。 这样子可以保证机器长期稳定服务。若是越来越多的客户端申请不到资源,则需要提高机器配置。(因为我们的连接池最大数量已经是机器的瓶颈,只能通过硬件配置来提升能服务的数量)


nginx - php fpm在大并发下504


在最开始的时候已经介绍过nginx和php的运行进程模型,php-fpm就是一个池管理器,内部装了若干个php-cgi程序,当nginx申请解析php脚本时,php-fpm则分配一个php-cgi出去处理,处理完则收回管理。 在高并发下,nginx会产生504错误,这就是我们上面介绍到的,客户端进行了短暂的 等待 后,仍然申请不到资源,则只能告诉客户端失败。 (在京东、淘宝的大活动期间很有机会碰到504错误哦! 这种情况下我们一般只需要刷新页面即可。 因为再刷新时大几率已经有连接资源空闲了!)


  • Nginx 504 Gateway Time-out的含义是没有请求到可以执行的PHP-CGI。


总结


连接池、对象池的意义不仅仅是可以减少频繁创建销毁对象连接的性能开销 更大的意义是可以保证应有服务客户端的稳定运行。

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
SQL 设计模式 数据库
领域模型:贫血模型与充血模型的深度解析
领域模型:贫血模型与充血模型的深度解析
|
druid Java 数据库连接
什么是连接池?为什么需要连接池呢?连接池的组成原理又是什么呢?
什么是连接池?为什么需要连接池呢?连接池的组成原理又是什么呢?
1871 0
什么是连接池?为什么需要连接池呢?连接池的组成原理又是什么呢?
|
11月前
|
机器学习/深度学习 分布式计算 安全
深度学习之安全多方计算
基于深度学习的安全多方计算(Secure Multi-Party Computation,简称MPC)是一种密码学技术,旨在让多个参与方在不暴露各自数据的前提下,协作完成一个计算任务。
409 0
|
机器学习/深度学习 算法 搜索推荐
【机器学习】机器学习的基本概念、算法的工作原理、实际应用案例
机器学习是人工智能的一个分支,它使计算机能够在没有明确编程的情况下从数据中学习并改进其性能。机器学习的目标是让计算机自动学习模式和规律,从而能够对未知数据做出预测或决策。
717 2
|
druid 网络协议 Java
再有人问你数据库连接池的原理,这篇文章甩给他!
在 Spring Boot 项目中,数据库连接池已经成为标配,然而,我曾经遇到过不少连接池异常导致业务错误的事故。很多经验丰富的工程师也可能不小心在这方面出现问题。 在这篇文章中,我们将探讨数据库连接池,深入解析其实现机制,以便更好地理解和规避潜在的风险。
1070 1
|
人工智能 搜索推荐 机器人
AI发展已经一段时间了,当前社会身边哪些功能已经在运用了AI技术?未来AI技术还将有哪些地方会运用?
AI技术现已被广泛应用在智能家居(如自动化控制与安全)、个性化教育(定制化学习与辅助教学)、精准医疗(疾病诊断与药物研发)、智能服务(如智能客服)和金融服务(风险评估)等领域。未来,预计AI将在AI PC、人机协创、超级视野、机器人和零搜索等领域发挥更大作用,实现信息主动推送、无缝沟通和创新服务。随着技术进步,AI将持续影响并改变我们的生活。【6月更文挑战第2天】
729 0
|
11月前
|
存储 安全 机器人
MemoryScope:为LLM聊天机器人配备的长期记忆系统
如何选择合适的方法构建自己的智能体助理呢?这里向您介绍强大、低延迟、安全可控的MemoryScope开源项目。
|
11月前
|
关系型数据库 MySQL 数据库
深入浅出MySQL索引优化:提升数据库性能的关键
在这个数据驱动的时代,数据库性能的优劣直接关系到应用的响应速度和用户体验。MySQL作为广泛使用的数据库之一,其索引优化是提升查询性能的关键。本文将带你一探MySQL索引的内部机制,分析索引的类型及其适用场景,并通过实际案例演示如何诊断和优化索引,以实现数据库性能的飞跃。
|
调度 索引
传输块大小(TBS)的确定 | 带你读《5G-NR信道编码》之十六
物理块上行和下行数据共享通道是以传输块(TB,Transport Block)为基本单位进行传输数据的。在LTE中,TBS可以用给定的物理资源块(PRB,Physical Resource Block)的数目 NPRB 以及 TBS 的索引 ITBS 通过查表的方式得到。在 5G-NR 标准化过程中,有的公司提出采用公式计算和查表分别量化 不同大小区间的 TBS 的方式来确定 TBS,以实现更大的调度灵活性。
18025 0
传输块大小(TBS)的确定 | 带你读《5G-NR信道编码》之十六
|
Java 数据库连接 Apache
深入理解Apache Commons Pool2池化技术
深入理解Apache Commons Pool2池化技术