C++ fastcgi模式下MySQL问题汇总

背景介绍

  • 公司内部自研的WebServer支持fastcgi模式,对于C++语言,需要将代码编译为动态库。当WebServer启动的时候,会根据配置文件,启动指定数量的fastcgi进程,将对应的动态库加载到内存。对于后续的http请求,由WebServer指定空闲的fastcgi进行处理。

MySQL相关问题

频繁创建与销毁MySQL连接

  • 虽然fastcgi是常驻内存的,但每次fastcgi处理请求的时候,如果涉及MySQL处理,需要实时创建MySQL连接,处理完之后再将其销毁。这种方式虽然能正常处理请求,但是频繁地创建和销毁连接,不仅耗时,而且对数据库也会产生不小的压力。既然fastcgi是常驻内存的,那么可以采用单例模式来保存该连接,每次处理请求的时候,如果没有现成的连接,则创建新的连接并存储到单例中,如果已经有现成的连接,那么直接复用即可。

同时连接多个数据库

  • 使用单例维持MySQL连接,可以解决频繁创建与销毁的问题,但是对于需要连接多个数据库的情况,简单的单例模式无法解决问题。此时需要对这种模式进行改进,对于不同的数据库连接,使用不同的名称进行标识。

MySQL请求超时处理

  • WebServer启动的fastcgi的数量是有限的,如果不限制MySQL的处理耗时,则有可能会出现大量fastcgi处理卡在MySQL请求等待的情况,这不仅会导致其他的http请求无法被WebServer正常处理,同时还会导致MySQL服务器连接数过高,无法正常处理其他连接请求。MySQL提供三种超时选项,分别是MYSQL_OPT_CONNECT_TIMEOUT(创建连接超时)、MYSQL_OPT_READ_TIMEOUT(读超时)和MYSQL_OPT_WRITE_TIMEOUT(写超时),默认情况下超时时间为0,表示不做超时处理,对于fastcgi模式,需要在建立连接的时候根据实际场景设置默认超时时间。另外,由于客户端与MySQL服务器之间的通讯使用TCP协议,存在重试机制,实际的超时时间一般比设置的时间更长。

MySQL静默连接超时自动断开

  • 这里的静默连接超时与上文的创建连接超时不一样,创建连接超时指的是在创建连接的时候,客户端在特定时间内未收到服务器的正确返回,客户端主动断开连接,而静默连接超时指的是连接成功创建之后,在特定时间内客户端一直未发起其他请求,服务器主动断开连接。创建连接超时时间可以在客户端建立连接的时候进行设置,而静默超时时间需要在服务器进行设置,可以使用”show variables like ‘wait_timeout’;”命令查看当前设置。对于正常的fastcgi而言,很难出现半个小时或一个小时都没有被激活的情况,因此这种问题较难发现。
  • 上文描述了使用单例模式维持MySQL连接,如果在wait_timeout设置时间内服务器一直未收到客户端发起的其他请求,服务器则会自动断开连接,此时客户端无感知,在处理下一个请求的时候,会出现”MySQL server has gone away”的错误提示。MySQL提供MYSQL_OPT_RECONNECT(静默超时之后自动重连)选项,同时提供mysql_ping接口用于检查连接是否仍然有效。对于fastcgi模式,可以在建立连接的时候设置自动重连,并且在每次执行MySQL请求之前使用mysql_ping检查连接是否仍然有效,若连接已失效,MySQL的API会主动重新建立连接。还有一种方式是在服务端把wait_timeout设置得足够长,但这种方式无法根除类似问题,同时可能导致MySQL连接数过高,因此不建议采用这种方式。