底层通讯协议问题排查案例

最近每天抽调一点时间充当客服工作,解决用户的技术问题,在充当客服工作当中,遇到各种形形色色的问题,才知道以前自认为不是问题的问题现在都成为了问题,在问题的分析,解决过程中相当的困惑人,有时候同一个问题分析好几天,尝试各种方式,最后到问题的解决,解决问题后,那种兴奋是无法用语言来形容,感谢用户容忍我们这么不停的折腾,在这个过程当中,让我了解到一些更底层的东西,对于自身也是一个很大的提高。下面说说遇到几个问题的案例吧
案例一
同一局域网一用户通过tcp协议连接不上我们的服务器,其它用户都是正常的,服务器端没有做任何限制,telnet服务器的端口也不通,从服务器端抓包来看已经收到用户的syn数据包,但是服务器端并没有响应这个数据包,发出ack包,也就没有完成tcp的三次握手,当然连接建立不起来,为什么会发生这种情况?
我们知道在tcp网络程序当中,当我们建立一个连接的情况下,主动断开一方会进入TIME- WAIT状态,而TIME- WAIT状态需要占用机器一个文件描述符,消耗服务器资源,为了提高TCP的性能,“RFC1323 – TCP Extensions for High Performance”提出了 一个机制(http://tools.ietf.org/html/rfc1323#page-29)来替代TIME- WAIT状态的功能。linux实现了它。这个机制通过记录来自每台主机的每个连接的分组时间戳来实现,要求来自同一主机的同一连接的分组所携带的时间戳要比之前记录的时间戳新,以便“防止回绕的序号PAWS机制“(http://tools.ietf.org/html/rfc1323#page-17)丢弃接收属于旧连接的延时分组。这依赖于来自每个主机的每个 TCP连接分组所携带的时间戳要单调递增才能实现。然而经过NAT的连接,其分组携带时间戳每个用户都不同的,也就是说同一个ip ,携带的时间戳不会单调递增。服务器端对同一个ip 过来的包的timestamp做一个验证,导致这些连接分组被认为是属于旧连接的延时分组而被丢弃。在linux上可以通过如下netstat -s|grep timestamp查看具体有多少被drop的包。解决办法就是
echo 0 > /proc/sys/net/ipv4/tcp_timestamps
案例二
同一局域网的所有用户死活连接不上我们的服务器端(udp协议的服务器端),局域网没有任何限制,而且用户到部分其他常用的站点,部分能够打开,部分打不开。为什么呢?
以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的,这个1500字节被称为链路层的MTU(最大传输单元).但这并不是指链路层的长度被限制在1500字节,其实这这个MTU指的是链路层的数据区.并不包括链路层的首部和尾部的18个字节.所以,事实上,这个1500字节就是网络层IP数据报的长度限制.因为IP数据报的首部为20字节,所以IP数据报的数据区长度最大为1480字节.而这个1480字节就是用来放TCP传来的TCP报文段或UDP传来的UDP数据报的.又因为UDP数据报的首部8字节,所以UDP数据报的数据区最大长度为1472字节.这个1472字节就是我们可以使用的字节数。当我们发送的UDP数据大于1472的时候会怎样呢?这也就是说IP数据报大于1500字节,大于MTU.这个时候发送方IP层就需要分片(fragmentation).把数据报分成若干片,使每一片都小于MTU.而接收方IP层则需要进行数据报的重组.这样就会多做许多事情,而更严重的是,由于UDP的特性,当某一片数据传送中丢失时,收方便无法重组数据报.将导致丢弃整个UDP数据报。一些电信运营商为了封堵网络共享,在送的路由器上把mtu给改了,导致用户出现这种情况,这个时候,通过修改路由器的mtu进行问题解决,一般adsl的mtu为1492,如果无法确定的通过ping -f -l mtu数据区大小 网关得到mtu的值,再设置一个值就是了,基本可以完美解决这个问题。
案例三
用户使用一个linux网关连接不上目标服务器,但是从linux网关服务器上telnet目标服务器端口是通的,抓包的结果如下:

从数据来看,三次握手是成功的,客户端也发送了数据给我们服务器端,服务器端也确认了该数据,这个时候应该服务器端返回给客户端才对,不返回也应该发出fin包结束这个连接,后面也看到都是客户端在重试,重新发数据包,到服务器端,服务器端也确认了这个数据,可以确定的是服务器端发给客户端的数据包过大,需要分片,从代理服务器到服务器端中间的某个网络设备配置异常或者因为从代理服务器到目标服务器的“路径”为了响应各种各样的事件(负载均衡、拥塞、断电等等)而被动态地修改——这可能导致路径最大传输单元在传输过程中发生改变——有时甚至是反复的改变。其结果是,在主机寻找新的可以安全工作的最大传输单元的同时,更多的分组被丢失掉了,导致连接失败。为了确定是中间网络设备设置异常,还是其它原因引起的,找一台正常的机器,抓包分析结果如下:

从结构来看,服务器端返回的数据包大小确实是过大,超过一个分组,数据包需要切片,因而可以确定是中间网络设备设置异常引起的。而这个代理服务器既有udp协议又有tcp协议,如果更改通过如下命令
ip link set eth0 mtu 1400
设置mtu的话,有可能出现案例2的问题,导致连接异常,我们知道tcp连接的三次握手过程当中可以协商一个mss(Maximum Segment Size,最大分段大小),连接建立后,以两端最小mss进行数据传输,充分利用这样一个特性就能解决这个连接异常问题,iptables能够修改tcp的包头,利用iptables的这个特性,轻松的解决这个问题,具体设置命令如下:
iptables -t mangle -A POSTROUTING -o eth1 -p -m tcp –tcp-flags SYN,RST SYN -j TCPMSS –set-mss 1400
执行完上述命令后,客户端顺利的连接上服务器端,抓包的结果如下:

案例四
一用户反馈到我们服务器连接非常缓慢,叫用户ping到服务器延迟很低,服务器也没有任何负载,服务器很正常,其它用户连接没有任何问题,而且用户在同网段装的一个虚拟机,虚拟机采用桥接方式上网,虚拟机里面访问没有任何问题,为什么会出现这样一个情况呢?
TCP协议在工作时,如果发送端的TCP协议软件每传输一个数据分组后,必须等待接收端的确认才能够发送下一个分组,由于网络传输的时延,将有大量时间被用于等待确认,导致传输效率低下,为此TCP在进行数据传输时使用了滑动窗口机制,而这个滑动窗口是动态的增长的,也就是说我们常见的采用下载工具下载的时候,看到下载的速度是慢慢的增长,而不是一下子把整个带宽给撑满了。同时tcp还有流控,拥塞控制,出错重发等机制,当在窗口增大的过程中,由于中间某个路由设备出现异常丢掉tcp的分组,导致不能连接当中的窗口不能确认导致,一直持续的小窗口,从而导致整个速率就非常之慢,因此我们在服务器端关闭滑动窗口机制,采用固定的窗口大小(linux默认为64K)进行数据传输,配置方法如下:
echo 0 > /proc/sys/net/ipv4/tcp_window_scaling
linux默认窗口为64K,窗口的大小也可调,通过如下参数进行窗口大小的调整
echo 4096 65536 65536 >/proc/sys/net/ipv4/tcp_rmem
echo 4096 65536 65536 >/proc/sys/net/ipv4/tcp_wmem
案例五
我们的一个同事的问题,非用户的问题,他的两台服务器之间传输数据,a服务器到b服务器拉取数据,速度可以到达1M每秒,而b服务器到a服务器拉取数据只有可怜的50K每秒,说明一下,这个两个机器都是光纤网络环境,中间的带宽都是正常的,没有跑满。为什么存在这个情况?
首先我就抓包进行数据分析,抓包出来的内容如下:

从上面看到tcp的窗口很小只有14,而且不能动态的往上增长,想到上面的那个案例,调整tcp的窗口使用固定的窗口大小
echo 0 > /proc/sys/net/ipv4/tcp_window_scaling
再抓包看到的内容如下:

而从实际的下载速度来看,比前面的不指定窗口的大小要快那么一丁点,还是没有达到我们想要的要求,具体数据如下

而从我们二次抓包的数据看到同一分组多次传输,具体如下图

这个时候想到的中间网络质量有问题,而从另外一台到这台服务器拉取数据正常,这个时候就想确认一下两边是否是对称路由,也就是走的路由的路是否一致,排查网络设备问题,最后用tracert确认路径是一致的也排除中间网络设备的问题,这时候可以确认这台机器有问题,我ifconfig运行了一下,看到这台机器进来这一侧,有错误包,而且还丢包。具体图如下

最后运行一下ethtool eth1看到的内容如下

网卡变成100M,且跟交换机的自动协商功能也关闭了,这个时候通过命令 ethtool -s eth1 speed 1000 autoneg on把网卡设置为1000M并打开自动协商,再测试的速度如下

速度恢复正常,多次ifconfig也没有发现网卡有错误包跟丢包了。
案例六
一个做游戏开发的朋友,他们的一个用户,前几天用户登录游戏还好好的,今天更新一个补丁出去,用户登录不了游戏,而游戏并没有更新网络连接这个模块,他打日志,发现socket连接读取数据出错,报内核缓冲器已满,从打日志的数据来看,客户端接收到的数据不完整,导致连接不上游戏。这是为什么呢?
由于我没有用户的一个服务器端环境,但是我可以提供一个代理给用户,可以抓取通过代理服务器中转到游戏服务器的数据包,我提供一个vpn给用户,用户通过我的vpn连接游戏服务器,在我vpn服务器上进行抓包分析,从抓包的情况来看,具体内容如下

从上面数据来看,连接过程已经传输了好几K的数据,中间也没有丢失分组,而连接的最后被发送了一个rest包,正是因为这个rest包导致连接异常,客户端看到的数据包不完整,这个rest数据包,我的代理服务器不可能发送,这个时候需要确认是否是客户端发送的,还有一种情况是中间网络设备发送的,如果是中间网络设备发送的,这个问题基本没有办法解决,而这个时候需要到用户机器上进行抓包分析,装一个wireshark,进行抓包一看,看到这个rest包有客户端发出的,而对方的游戏,我问了一下,不可能发出这么底层的数据包,这个时候最容易发送这个数据包的就是一些安全软件,这个用户机器上我看了一下装了2个安全软件,一个是某某杀毒软件,一个是某某安全软件,先关闭杀毒软件,还是无法连接,最后关闭某某安全软件,就彻底解决了,用户也连接上游戏服务器了。看来软件冲突也是问题之一啊!
以上就是我在最近工作当中遇到的一下通讯协议的问题排查过程以及解决方法,中间牵涉到一部分内核的调整,在网络上看到很多人未经考虑直接就拿着别人的一些参数直接用上了,而出了问题也不知道怎么去排查。

大量小包的CPU密集型系统调优案例一则

我的blog前面有一篇文章描述了软终端导致单cpu消耗100%,导致机器丢包跟延迟高的问题,文中我只是简单的说明了一下升级内核进行解决的,这个问题我并没有进行一个问题解决的说明,经历了一系列的调整后,单机的并发从单机单网卡承受100M流量到160M流量,到现在的最高的230M流量,在程序没有大规模修改的情况下效果还是十分的明显,这次这篇文章将完整的说一下我的一个解决方法:
先说说我的场景,我目前负责的一个项目,大量的小数据包,长连接,每个数据包都不大,大概10Kbit左右一个包,但是数量十分之大,目前在生产环境中最大的数据包数量高达15W/s的数量,常见的网游系统,小图片cdn系统,这些服务类型都算是这种类型,单网卡流量不大,但是数据包数量极大,我目前调优的结果是
在Xeon E5504, BCM5716的网卡,8G的dell r410的机器,单网卡实现了230MBits大的流量,系统的load为0,8颗cpu每一颗还有10%左右的IDLE,由于我们的系统是数据包的转发,还有一个网卡同期的流量使220M,12.8W的数据包,算上总数,大概可以到450MBits的流量,25.5W的小包,由于人数有限,流量没有跑上去,预计可以跑到480MBits的流量,生产环境的一台机器的数据:
流量及机器的网卡包数量

机器的cpu消耗

首先机器的选型,由于大量小包的cpu密集的系统,当然cpu越性能越高越好咯,但是成本相应的高。对于这种类型的机器,网卡选型也是十分的重要,一定要选择支持msi-x的网卡类型,什么是msi-x大家可以查询google资料去了解一下,目前市面出售的大部分最新的网卡都有这个功能,查看方法lspci -v,看到如下图的内容

再者网卡是否支持多队列,多队列网卡十分的重要,不是多队列的网卡,这篇文章几乎不需要看了,可以直接忽略掉,查看方法cat /proc/interrupts,这个方法并不适用所有的操作系统例如在rhel 5.5的os当中,bcm5716的网卡就看不到,具体我也没有查到怎么查看的方法,麻烦知道的用户告知一声,如果是的话应该可以看到如下图的内容

每一个网卡有8个队列,对于这种大量小包的cpu密集型的系统,多队列的网卡性能至少提供性能50%以上,我们生产环境的有台非多队列的Intel 82574的网卡调优后只能跑到160M左右流量,跟上图明显的一个对比.而同等情况下买一个多队列的网卡明显要便宜很多。
操作系统的选择,目前大部分企业使用的是rhel系列的os,包括标准的rhel跟centos作为一个生产环境的os,目前主力的版本还是rhel 5系列的os,而rhel 5系列的内核版本对于软中断处理并不是很好,调优的结果不是很理想,在rhel 5系列的os上,我们最高流量单网卡也就是160M左右,而且机器的load也很高了,机器已经出现小量的丢包,而且只是使用了4到6个cpu还有几个cpu没有利用上,机器性能没有挖掘完毕,由于我们的机器没有存储的压力,单纯的只是消耗cpu资源,没有io的压力,于是大胆的启用刚出的rhel 6.1的系统,看重这个系统的原因是,该os的内核已经加入了google的两个原本在2.6.35当中才启用的2个补丁——RPS/RFS,RPS主要是把软中断的负载均衡到各个cpu,由于RPS只是单纯把数据包均衡到不同的cpu,这个时候如果应用程序所在的cpu和软中断处理的cpu不是同一个,此时对于cpu cache的影响会很大,那么RFS确保应用程序处理的cpu跟软中断处理的cpu是同一个,这样就充分利用cpu的cache,默认情况下,这个功能并没有开启,需要手动开启开启方法,开启的前提是多队列网卡才有效果。
echo ff > /sys/class/net/<interface>/queues/rx-<number>/rps_cpus
echo 4096 > /sys/class/net/<interface>/queues/rx-<number>/rps_flow_cnt
echo 30976 > /proc/sys/net/core/rps_sock_flow_entries
对于2个物理cpu,8核的机器为ff,具体计算方法是第一颗cpu是00000001,第二个cpu是00000010,第3个cpu是00000100,依次类推,由于是所有的cpu都负担,所以所有的cpu数值相加,得到的数值为11111111,十六进制就刚好是ff。而对于/proc/sys/net/core/rps_sock_flow_entries的数值是根据你的网卡多少个通道,计算得出的数据,例如你是8通道的网卡,那么1个网卡,每个通道设置4096的数值,8*4096就是/proc/sys/net/core/rps_sock_flow_entries的数值,对于内存大的机器可以适当调大rps_flow_cnt,这个时候基本可以把软中断均衡到各个cpu上了,而对于cpu的使用,还有其它的例如use,sys等,这个不均衡的话,cpu还是会浪费掉,同时对我们的程序针对多cpu进行小部分的开发跟重新编译,本身我们程序就是多进程的一个模型,我们采用nginx的进程管理模型,一个master管理work进程,master分配每一个连接给work进程,由work进程处理用户的请求,这样每一个进程都能均衡负担几乎相同的处理请求,同时在6.1的系统中gcc新增一个openmp的指令,这个指令作用针对多核,增加程序的并行计算的功能,不需要大规模的更改代码就能实现多核的并行性计算,具体使用使用方法请见如下url

http://zh.wikipedia.org/zh/OpenMP

针对上面的处理,基本上可以实现cpu按理说可以实现完全的均衡了,但是当我们在实际的使用过程中发现还是cpu还不是100%的均衡,存在1到2个cpu消耗量还是比其它的要大20%左右,导致在高峰期有1到2个cpu的idle使用完毕,导致用户使用存在卡的情况,这个时候,需要手动调节一下cpu的使用情况,在这操作之前先了解几个名词以及其作用
一个是IO-APIC(输入输出装置的高级可编程中断控制器)
为了充分挖掘 SMP 体系结构的并行性,能够把中断传递给系统中的每个CPU至关重要,基于此理由,Intel 引入了一种名为 I/O-APIC的东西。该组件包含两大组成部分:一是“本地 APIC”,主要负责传递中断信号到指定的处理器;举例来说,一台具有三个处理器的机器,则它必须相对的要有三个本地 APIC。另外一个重要的部分是 I/O APIC,主要是收集来自 I/O 装置的 Interrupt 信号且在当那些装置需要中断时发送信号到本地 APIC。这样就能充分利用多cpu的并行性。如果用户对于IO-APIC更感兴趣,请见如下url的中的pdf的说明

http://wenku.baidu.com/view/ccdc114e2e3f5727a5e962e9.html

另外一个就是irqbalance
irqbalance 用于优化中断分配,它会自动收集系统数据以分析使用模式,并依据系统负载状况将工作状态置于 Performance mode 或 Power-save mode.处于 Performance mode时irqbalance 会将中断尽可能均匀地分发给各个CPU以充分利用 CPU 多核,提升性能.处于 Power-save mode时,irqbalance 会将中断集中分配给第一个 CPU,以保证其它空闲 CPU 的睡眠时间,降低能耗
通过这我们就发现我们是一个非常繁重的系统,并没有节能的需求,而是需要充分利用各个cpu的性能,而事实上在一个大量小包的系统上,irqbalance优化几乎没有效果,而且还使得cpu消耗不均衡,导致机器性能得不到充分的利用,这个时候需要把它给结束掉
/etc/init.d/irqbalance stop
同时,手动绑定软中断到指定的cpu,对于一个8个队列的网卡,8核的机器,可以指定一个cpu处理一个网卡队列的中断请求,并根据cpu的消耗情况,手动调整单个网卡的队列到资源消耗低的cpu上,实现手动均衡,具体操作方法,执行如下命令
cat /proc/interrupts

计算cpu的方法第一颗为00000001换算成16进制为1,第2颗cpu为00000010换算成16进制为2,依次类推得出,第8颗cpu为80,这样就可以做如下的绑定了
echo 0001 > /proc/irq/<number>/smp_affinity
这样就可以绑定中断到指定的cpu了,这个时候有可能会问,我的机器是一个2通道的网卡,这个时候如果一个通道一个cpu绑定,这个时候就浪费了6颗cpu了,还是达不到完全均衡负载,为什么不能像前面rps那样,
echo ff > /proc/irq/<number>/smp_affinity
设置一个ff达到所有的cpu一起均衡呢,这个因为io-apic工作的2个模式logical/low priority跟fixed/physical模式,这两个模式的区别在于,前面一个模式能够把网卡中断传递给多核cpu进行处理,后一种模式对应一个网卡队列的中断只能传递给单cpu进行处理,而linux是fixed/physical工作模式,如果你设置上面那个选项,只能第一个cpu进行软中断的处理,又回到未优化前了。那么为什么不开启logical/low priority呢,当一个tcp连接发起,当数据包到底网卡,网卡触发中断,中断请求到其中一个cpu,而logical/lowpriority并不能保证后续的数据包跟前面的包处于同一个cpu,这样后面的数据包发过来,又可能处于另外一个cpu,这个时候同一个socket都得检查自己的cpu的cache,这样就有可能部分cpu取不到数据,因为本身它的cache并没用数据,这个时候就多了多次的cpu的查找,不能充分利用cpu的效率。对于部分机器来说并不能开启logical/low priority模式,一种可能是cpu过多,另外一种是bios不支持。因此对于那种单队列网卡并不能充分发挥cpu的性能。
经过上述的调整基本可以达到几乎完全均衡的效果,每个cpu都能发挥他的效果。也几乎可以到达我调优的效果
对于一个完整的系统来说,不仅有数据包发送的需求还有数据接收的请求,而rps/rfs主要解决数据接收的一个中断均衡的问题,rps/rfs的作者提交了一个xps(Transmit Packet Steering), 这个patch主要是针对多队列的网卡发送时的优化,当发送一个数据包的时候,它会根据cpu来选择对应的队列,目前这个patch已经添加在2.6.38内核版本当中,我们已经在生产环境中,部分机器上已经使用上了,据作者的benchmark,能够提高20%的性能,具体使用方法
echo ff > /sys/class/net/<interface>/queues/tx-<number>/xps_cpus
由于还是新上的系统,还没敢大规模放用户进来,还在测试系统的稳定性,不知道上限具体能到多少,从当前生产环境跑的流量来看,比同等其它的机器,cpu消耗情况,确实要减少一些,流量没有跑上来,效果不是特别的明显,还有待继续测试,得出一个具体的结果。
另外对于intel的网卡的用户,intel有个叫ioat的功能,关于ioat功能大家可以网上查查资料.
而对于centos的用户来说,目前还只是出了6.0的版本,并没有上述功能,要大规模的推广,建议大家编译2.6.38的内核版本,因为2.6.38的版本已经包含了上述几个补丁。编译内核生成内核的rpm包,能快速的在同一批机器上快速部署上去。
以上就是我的对cpu密集型系统的一个优化过程,欢迎大家来讨论。

LAMP调优案例一则

今日同事抱怨我们一个发奖系统,测试过程中工作得很好,今日怎么打开那么的卡,领取一个奖品需要5秒以上,于是登录WEB服务器,通过top,vmstat等,系统都处于正常的水平,怎么会慢呢,先说明一下,我们是采用linux+nginx+mysql+php的环境,于是开log去调试,先打开nginx的log记录中的$upstream_response_time $msec $request_time这几个参数,了解到返回的时间,发现确实有些页面返回时间比较的长,而且都是出现在后端的php环境,由于采用了php框架进行开发的,php框架都是有统一入口,故无法定位到具体某一个php文件执行慢,由于时间紧急也没有时间通过xdebug跟xhprof之类的工具去找具体的那个地方执行的慢,于是打开php-fcgi的慢日志,把执行时间超过1秒的函数大约到log当中,发现都是在连接db慢,于是定位到数据库上,登录上数据库上,通过top等命令,系统的负载非常的高,直接进入mysql种,通过show full process查看,几百个进程都在执行中,其中大部分的状态都是lock,看来是表锁引起的,继续通过show index from table test来看这些表上是否有哪些执行sql语句当中的索引,发现有,看来不是索引能解决该问题,继续通过show full process查看执行的sql语句,发现有几条update,insert的语句,其它的sql语句都是select,看来表的由于更新操作引起的表锁,通过show tables status命令,查看表的引擎,都是mysim,看来得改引擎来解决这个问题,通过ALTER TABLE test ENGINE = InnoDB;,另外改完表的引擎为innodb并不能解决锁的颗粒减少,也就是不能从表锁变成行锁,调出mysql的慢日志,看其中的sql语句中的更新操作中的where条件的字段,在这些字段中通过 create index IX_TEST on test(testcol)建立索引,这样就把锁的颗粒大大的减少,锁的颗粒减少,相应的sql语句之间的lock等待机会就大大的减少,重新进入数据库,通过show full process几乎看不到有lock的sql语句,查看服务器的load,慢慢的进入了正常水平,页面打开的时间也变正常了。
由于该操作过程没有留证据,我只是做一个简单的解决问题的文字说明,文中改表的引擎得注意了,如果从非事物引擎变成事物引擎的表基本上没有什么大的问题,但是从事物引擎变成非事物引擎有可能丢失数据,再者改引擎的过程,会锁表,在生产环境中,千万得注意备份数据。这个优化的案例也体现我们工作中的不足,轻易的上了一套系统,而没有进行相应的压力测试,把问题提前扼杀在摇篮里,另外程序员的水平有高有低,很有可能再次写出同样的系统,这样的系统对用户的体验十分的不好,很容易流失来自不易的用户。

日本最大sns站点mixi因memcached bug引起长时间的宕机

今年的8月10日,日本的最大sns站点mixi因memcached引发的宕机,mixi拥有日本最大的memcached集群,共100多台memcached服务器,他们工程师设计的架构即使宕机其中的十几台都不影响正常的业务。事情的经过时这样的,17点20分左右系统出现大量的memcached服务器memcached直接异常结束,当初他们的工程师也没有想到是由memcached本身的bug引起,memcached服务器一直运行得很好,在这情况下,他们的技术团队,4个人,主要负责人开始分析memcached代码,一个开始进行系统恢复,另外2个人开始查找替代memcached,采用其它cache的方法。23:30分左右,由于整个系统访问量下降,全部恢复完毕,第二天11点20分左右,随着访问量上增大,又发生宕机,11日晚22点50分左右,找到memcached bug,并修护,12日凌晨1点50分左右全部恢复完毕。
事后,通过其官方blog写了3篇文章进行详细的分析,并把分析的结果提交到memchaed邮件组,提交了相关patch及问题重现的程序
事情的大概原因是,mixi使用的memcached服务器版本为memcached-1.4.4 + libevent-1.3b,他们设置了memcached的最大连接数为30K,当连接数超过30K以后,memcached的工作线程跟主线程发生资源竞争,主线程跟工作线程同时访问和修改主线程的event_base,从而引起内存破坏,导致memcached进程异常终止。mixi给出的建议,监控最大连接数目,当快到达最大数,切换到其他的memcached服务器上,使用memcached proxy或者采用memcached udp协议可以完全避免memcached宕机的可能,同时启动memcached时带一个-l的选项,可以在超出连接限制的情况下,memcached输出Too many open connections,memcached进程而不宕机。
从这件事情的本身来看,memcached部署量这么大,还有存在大的bug,各个技术团队更应该加强自身的团队得技术建设,同时也感慨国外企业能第一时间把自身宕机的原因进行详细的分析,并分享出来,这样的宕机案例,比分享一个成功的案例,更难得。笔者在使用日文进行搜索了一下,在这个事情的解决过程中,mixi团队通过twrite跟外部进行沟通,得到了外部大量的问题分析和建议。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值