GWA2 PHP Memcached自动追加服务器连接?一例缓存服务被击穿的异常分析。

GWA2 PHP Memcached自动追加服务器连接? 一例缓存服务被击穿的异常分析。

最近在一次网络应用服务器巡检时,发现负载特别高,与当时的流量不成比例,于是就进一步地核查看看为何负载高。

首先发现负载高是由于数据库(-MySQL)的查询读取查询异常的多,并发连接有上百个,多数是简单的查询,可见不是数据库结构问题,而是自然流量触发的数据请求。

缓存被击穿了吗?为何这些显而易见的查询会出现那么多并发?稍微留意发现,有些查询SQL是相同的,于是可以大致推断,缓存层出问题。确认缓存被击穿,对一个线上应用来说是一件很恐怖的事情。

@memcached
进一步的诊断缓存服务(-Memcached),使用telnet 工具连接本地缓存服务,通过 stats命令查询,缓存服务正常,有正确的get/set数据,有get_hits/misses统计,缓存服务没有问题。

下一个疑点就是在代码层,PHP连接模块Memcached的地方有问题吗? 调用缓存服务的存取操作有异常吗?

打开 GWA2 PHP 的 inc/config.class 核对连接缓存服务,没有问题,基于IP地址和端口的连接配置;
打开 inc/webapp.class 显示读取缓存的成功与失败日志记录,发现有成功,有失败。
进一步地打开 inc/webapp.class 的 readObject/writeObject的日志记录;打开 inc/cachea.class, inc/memcached.class 中的 set方法的日志记录。

日志记录显示,有成功的,结果是预期的;当失败时,memcached发回的错误代码和错误消息是,35 / Server Marked Dead。

这听起来不可思议,当下的memcached服务,只有一个 127.0.0.1 基于IP的连接配置,怎么会有成功和失败的状况同时存在呢?

更进一步地输出当前 sever list发现,的确有两个缓存服务的配置:

memcached servers:a:2:{i:0;a:3:{s:4:”host”;s:9:”127.0.0.1″;s:4:”port”;i:11211;s:4:”type”;s:3:”TCP”;}i:1;a:3:{s:4:”host”;s:33:”/bin/memcached/memcached.sock”;s:4:”port”;i:11211;s:4:”type”;s:6:”SOCKET”;}}

明明在 inc/config.class 中只配置了 127.0.0.1 的一个缓存服务,而第二个 /bin/memcached/memcached.sock 从哪里来的呢?显然这个 .sock 的连接已经被标注了 DEAD 但并没有从 server list 里移除,这也让人费解,毕竟在 Memcached的连接初始化时声明了自动移除DEAD Server。

$this->mcache = new Memcached(self::persist_ConnId);
$this->mcache->setOption(Memcached::OPT_REMOVE_FAILED_SERVERS, true);
$this->mcache->setOption(Memcached::OPT_LIBKETAMA_COMPATIBLE, true);

一种合理的解释大致是,/bin/memcached/memcached.sock 文件存在,然后Memcached 服务会自动探测,然后追加到当前的 server list里。会这样智能吗? 可能要分析PHP Memcached的扩展模块源码 和 Memcached的服务源码相应的模块才能确认。

导致存在 /bin/memcached/memcached.sock 文件并且使用 127.0.0.1 的原因是,第一次启动 Memcached服务时,指定了 -s /bin/memcached/memcached.sock 然后kill关闭,再次启动时不带 -s 而是指定了 IP/Port,这样 /bin/memcached/memcached.sock 就被遗留下来而没有用。

之所以不再使用 -s /bin/memcached/memcached.sock 模式,是由于该 Memcached服务需要在 PHP和 Java之间共享,而Java读取操作 .sock 文件相对复杂,暂时没有集成到 GWA2 Java中去。而 -s /bin/memcached/memcached.sock 与 IP/Port 在Memached服务看来又不能共存。

由于 /bin/memcached/memcached.sock 是上次启动后遗留下来的,所以其状态可能并不是 DEAD, 所以 OPT_REMOVE_FAILED_SERVERS 也未能生效?

针对这个问题,手工移除 /bin/memcached/memcached.sock , 然后重启 HTTPD ,  GWA2 PHP 再次正常运行,缓存服务不再报错,也没有缓存服务被击穿,导致数据库查询并发大,进而系统负载高的问题出现。


-GWA2 是”通用网络应用架构( General Web Application Architeture )”,基于 -GWA2 可以轻便构建各种网络应用程序,
包括复杂的在线购物商城、 旅游交易平台、社群或者社交网站和新闻资讯网站等,
也包括各种企事业单位网上门户,在线交互及服务作业系统等.
还可以包括为NativeApp做服务器端支持, 甚至是WebApp的全部.
-GWA2 是为数不多的支持跨开发语言的应用框架,目前支持 -Java, -PHP, -Perl, -Aspx and -Python .

-GWA2 is a “General Web Application Architecture” and based on -GWA2 developers can easily build a variety of network applications,
including complex online shopping malls, travel trading platforms, community or social networking sites and news information sites, etc.
Also the applications include various online portals of enterprises and institutions, online interaction and service operations systems.
Moreover it contains server-side support for NativeApp, or even all of the WebApp.
-GWA2 is one of the web frameworks which provide cross-language support for -Java, -PHP, -Perl, -Aspx and -Python at present.

-GWA2 is E.A.S.Y 
Easy Along, Swift Yield
轻松启动, 快速产出.

此条目发表在-GWA2, 编程技术, 计算机技术分类目录,贴了, , 标签。将固定链接加入收藏夹。

GWA2 PHP Memcached自动追加服务器连接?一例缓存服务被击穿的异常分析。》有1条回应

  1. Wadelau说:

    问题仍在重现。
    HTTPD (Apache)在运行一段时间后,仍然莫名地增加 .sock 的连接到 server list,从而进一步地触发了Memcached的存取失败,由于未来得及阅读源码查找深层原因,临时兼容措施:
    if($this->mcache->getResultCode() == 35){
    $this->mcache->resetServerList();
    }
    发现死连接则重置 server list.

Wadelau进行回复 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

Captcha Code