Zookeeper,你可把我坑惨了!


1 说多了都是泪

前些日子,我们被自己部署的 Zookeeper 集群 DDOS ***了,惊不惊喜,意不意外?肯定有很多朋友会问,怎么会呢?

一般来说确实不可能,但在一系列条件的配合下,可以把不可能变为可能(感觉好励志有木有!),下面就让我给大家一一道来。

2 交代下前提

在讲故事前,有几个前提先跟大家说明下:

前提一

我们公司服务治理框架用的是 Dubbo,注册中心使用的是 Zookeeper 集群。但是早期规划的时候,为了运维和开发维护简单,将 Zookeeper 的 IP 放到了 F5 的一个 VS Pool 里,后续增加或修改节点直接修改 VS Pool ,应用中注册中心配置的就是这个 VS 地址。

我们年前已经发现这种连接方式存在弊端(应用通过 F5 与 Zookeeper 之间的心跳检测经常中断),并发布了邮件让大家改为直连 Zookeeper 集群,但没有重视,也没有强制要求。

前提二

我们有两个数据中心,且关键业务应用都实现了双活。但因为一些应用没有部署双活,所以存在跨机房服务调用与治理。因此,早期规划的时候 Zookeeper 也是在一个机房部署了集群,但这种模式在 Zookeeper 进行消息广播时,会占用较多的专线带宽。

经监控系统报警后,我们决定在下周进行 Zookeeper 部署改造,一个机房部署普通 Zookeeper 节点,另一个机房部署 Oberserver 节点,同时修改 DNS,让应用连接本机房的 Zookeeper 节点,这样可以有效降低跨机房带宽占用。

3 吃一堑

那是一个周五的下午,大家本应该轻松下班,然后享受周末。突然监控系统报警 F5 流量过高,导致请求被阻塞。紧急来到案发现场,得到的信息是 Zookeeper 集群是流量大户。按照应急处理原则,我们将所有可能的上线都进行了回滚,但问题没有得到改善。于是,我们怀疑是不是某些应用连接 Zookeeper 做了坏事。

通过网络抓包,看了下基本全是 Dubbo 的注册和订阅事件。当时我也非常奇怪,Dubbo 与 Zookeeper 之间只有在心跳检测失败时才会有大量的广播事件,导致流量上升。但我们的 F5 硬件、网络、 Zookeeper 服务都非常正常,一时之间想不到问题的原因,线索又中断了。

所以当时的第一决定是启动紧急上线,即按照前提 1 中提到的,直接修改公司所有应用的配置文件,让大家直连 Zookeeper 集群,而不通过 F5 做代理。这一过程很坎坷,因为涉及的应用太多,但是完成改造后,F5 的流量终于降下来了。

正当我们以为终于解决问题时,灾难再次发生,跨机房专线流量过高,导致电信机房业务受到影响,还是 Zookeeper 在疯狂的广播。当时的第一想法,是不是同时注册引起的,再加上本身专线带宽就不富裕。我们提议将前提 2 中的方案也实施,看一下效果。

经过一番折腾后,专线流量也下来了,同时看业务也恢复了正常,加上人困马乏,我们决定后续再研究下之前抓取的网络包,先让大家回去休息下,以免明天没人支持。

周六的一天,就这样在偶尔的报警中度过了。至于分析网络包,看了几个内容后,发现都是正常的服务注册和订阅事件,也是一头雾水。

然后从周日 5 点开始,部分业务突然报警,网络 Ping 不通。经排查发现,受影响的业务,都是和 Zookeeper 部署在同一宿主机的应用。Zookeeper 吃掉了宿主机 600M 的带宽。由于还是没查询出“内鬼”是谁,我们只能定下临时方案:迁移 Zookeeper ,部署到与业务系统无关的宿主机上。

正当我们赶赴公司,准备完成迁移 Zookeeper 时,突然某个同事发现一个非常大的网络报文。当他把数据包给我看后,真的是柳暗花明的感觉,“内鬼”终于找到了。原来是一个基础服务,配置了很多路由规则,导致一个包的大小有几百 k ,而我们的机房里有将近两千台机器, Zookeeper 的性能又是变态的强,于是一切的巧合安排在一起,一瞬间,流量打死了物理机,打死了专线,打死了 F5……于是,事情就这样发生了。当我们把一堆无用规则删除后,整个世界安静了,所有报警都消失了。

4 长一智

故事讲到这里似乎就结束了,可是等等,我们在这件事故中到底犯了哪些错误,我们来复盘一下:

在前提 1、2 中,我们发现了异常,却没有刨根问底,只是凭感觉认为做个简单处理方案即可。魔鬼在细节,一切的灾难在发生前都是有征兆的,如果再多一丝细心,多一丝警惕,结果也许会全然不同。

同样在前提 1、2 中,整个事件的追踪与跟进完全没有,问题没有闭环,没有协作推进。

监控不完善,不论是内网的流量监控还是 Zookeeper 方面的监控都缺失,完全是靠运气找到了有问题的数据包。

SOA 技术运营缺失,由于功能权限的随意下放,导致造成了灾难的后果。

技术架构选型与搭建时不够谨慎,不管是 Zookeeper 集群的搭建还是 Dubbo 在服务治理那些坑不能踩等等,都没有去仔细讨论与思考。

技术没有好坏之分,关键是看人如何运用。一定避免人云亦云,适合自己公司技术体系的就是最好的。选好自己公司的技术体系后,最重要的就是做好运维与监控工作。监控的每一次报警,就像先兆一样,万万不可掉以轻心。运维的事情,永远是最辛苦最复杂的,但不能因为这些,就将权限随意下放,一定要确保自己可以掌控全局。

喜欢小编轻轻点个关注哦!

原文地址:http://blog.51cto.com/13952975/2319052

时间: 2024-10-14 12:39:36

Zookeeper,你可把我坑惨了!的相关文章

kafka与zookeeper管理之kafka-manager踩坑小记

在elk集群搭建过程中,为了极大程度的利用服务器资源,kafka.zookeeper.logstash规划混跑在了同一组服务器上.随着业务量的增加,要频繁增加调整kafka的topic,出现问题时还要去服务器敲命令查看kafka和zookeeper的相关信息,效率低而且不方便,于是就考虑到用kafka的管理工具kafka-manager,安装配好后,整个集群的状态一目了然,而且可以方便的进行topic的操作.消费情况的查询.broker各种状态指标的查询等,非常方便,各种信息一目了然,安装配置过

实现数组类(C++ 拷贝构造函数、拷贝函数)要判断赋值左右对象不相等,坑惨了

#include <iostream> using namespace std; class ArrayIndexOutOfBoundsException{ // 异常类 public: int index; ArrayIndexOutOfBoundsException(int k){ index = k; } }; class Array{ private: int *data; int size; static const int dSize = 10; // 数组默认大小 public:

zookeeper配置kerberos认证的坑

zookeeper配置了kerberos之后,zkCli.sh 连接认证死活不通过 连接命令: zkCli.sh 报错如下: WatchedEvent state:SyncConnected type:None path:null 2017-08-21 10:11:42,054 [myid:] - ERROR [main-SendThread(localhost:2181):[email protected]] - An error: (java.security.PrivilegedActio

被box2d坑惨了

如图, 这里使用delta周期时间作为物理引擎的步长 物理引擎我这犯了个错误, 一般教学都会把update的周期时间附带给物理引擎, 以让物理引擎达到真实时间平衡的效果, 这样做虽然有好处 但也有坏处, 如果这个delta时间过于长, (卡顿下可能到0.x秒)这个是一次周期的好几倍甚至是几十倍, 这样box2d会直接模拟对象运动到那个时间的位置点, 这样就可能中途经过的任何东西出现穿墙的现象, 解决方法就是固定步长, 1/60就一直不变, 如果update卡顿, box2d也随之卡顿, 这是出现

Ember.js的那些坑

用了一年Ember.js,从2.3到2.10,因为数据量大,以及项(xu)目(qiu)的复(bian)杂(tai)性踩了不少坑,感觉再也不会爱了.在把这个锅甩出去之前,小小总结一下,以示后人,知己知彼方能百战百胜.注意,这篇我只吐槽. 首先 肯定要吐槽一下压缩后仍旧占用几兆的巨无霸内核JS代码.光这点来说,Ember绝对不适合移动端以及小型项目的开发.哪怕像我参与的这个平台级项目,对于这个大小也是深感蛋疼.而且,Ember的默认配置还是只压缩成vender.js与app.js两个文件而已. 此外

一副好牌打得这么臭,记公司2015年坑客户的情况

2015年,公司拿到了某景区的一个票务酒店等综合互联网项目.该客户是一个比较优质的客户,在需求,实施等也很配合.在结款上,简直是难得的好客户.然而公司却从上到下把该客户坑惨了,从需求,开发,实施,维护,响应等等. 先说下甲方背景,该甲方是旅游局下属的一个国企公司. 一.先说公司老总怎么坑的 在刚拿到项目的时候,老总在甲方那开会,甲方老总说大概要8,9月的样子才能上线试运营,而我们的老总,却说6月份就可以搞定,你要是要得快的话5月份就可以给你上,此举把甲方老总坑得没话说.被旅游局的领导批评惨了.

golang爬坑:操作Linux命令

通常在启动项目服务程序的时候,需要判断该服务是否已经被启动,一般的做法有两种,其一是每次启动后将pid写入文件中,启动的时候读取这个文件,如果里面有数值,就表示服务已启动:另一种是通过shell命令查找: ps -ef | grep XXX | grep -v grep | awk '{print $2}' 很多语言都可以直接执行这行命令:偏偏go语言不行,因此,我们可以利用go中提供的一些方法实现它(不说了,直接上代码): func Pipeline(cmds ...*exec.Cmd) (p

字符串转json的坑

被坑惨了,一个post搞了一天,时而正常时而错误! let str = "{'name':'wanglei'}"; let obj = JSON.parse(str); 以上会报错: VM143:1 Uncaught SyntaxError: Unexpected token ' in JSON at position 1 at JSON.parse (<anonymous>) at <anonymous>:1:6 str = '{"name"

react-native的安装步骤,和可能遇见的BUG,react更新太快,官网安装很多坑。

Windows react-native 安装流程和坑 python2.7.x node.js8.7 sdk配置:AS 按官网来即可 o   Tools/Android SDK Build-tools (23.0.1)(这个必须版本严格匹配23.0.1) o   Android 6.0 (API 23)/SDK Platform (1) o   Extras/Android Support Library o   Extras/Android Support Repository 4.环境搭配A