机房360首页 CalConv();
当前位置:首页 » 数据中心资讯 » 高可用架构的Uber容错设计与多机房容灾方案

高可用架构的Uber容错设计与多机房容灾方案

来源:ArchNotes 作者:DJ编辑 更新时间:2015-7-23 14:17:49

摘要:在7月21号的全球架构师峰会深圳站上,美国科技公司Uber的高级工程师赵磊做了主题演讲“Uber高可用消息系统构建”,本文分享了分布式系统中的各种错误处理的方案。

window.getPageInfoURLFileName('0')

  赵磊在7月21号的全球架构师峰会深圳站上,做了主题演讲: Uber高可用消息系统构建, 对于这个热门主题,高可用架构群展开了热议,大家对分布式系统中的各种错误处理非常感兴趣。Tim Yang特邀赵磊通过微信群,在大洋彼岸的硅谷给大家进一步分享。

  分布式系统单点故障怎么办?

  non-sharded, stateless类型服务非常容易解决单点故障。 通常load balancer可以按照固定的时间间隔,去health check每个node, 当某一个node出现故障时,load balancer可以把故障的node从pool中排除。

  很多服务的health check设计成简单的TCP connect, 或者用HTTP GET的方式,去ping一个特定的endpoint。当业务逻辑比较复杂时,可能业务endpoint故障,但是health endpoint还能正常返回,导致load balancer无法发现单点故障,这种情况可以考虑在health check endpoint中增加简单的业务逻辑判断。

  对于短时间的network故障,可能会导致这段时间很多RPC call failures。 在RPC client端通常会实现backoff retry。 failure可能有几种原因:

  TCP connect fail,这种情况下retry不会影响业务逻辑,因为Handler还没有执行。

  receive timeout, client无法确定handler是不是已经收到了request 而且处理了request,如果handler重复执行会产生side effect,比如database write或者访问其他的service, client retry可能会影响业务逻辑。

  对于sharded service,关键是如何找到故障点,而且将更新的membership同步到所有的nodes。下面讨论几种sharding的方案:

  将key space hash到很多个小的shard space, 比如4K个shards。 通过zookeeper (distributed mutex) 选出一个master,来将shard分配到node上,而且health check每一个node。当遇到单点故障时,将已经assigned的shards转移到其他的nodes上。 因为全局只有一个single master, 从而保证了shard map的全局一致。当master故障时,其他的backup node会获得lock成为Master

  Consistent hashing方式。consistent hashing 通常用来实现cache cluster,不保证一致性。 因为每个client会独立health check每一个node, 同时更新局部的membership。 在network partition的情况或者某一个node不停的重启, 很可能不同的client上的membership不一致,从而将相同的key写在了不同的node上。 当一致性的需求提高时,需要collaborative health check, 即每个node要monitor所有其他node的health。 Uber在这里使用的是gossip protocol,node之间交换health check的信息。

  大面积故障怎么办?

  大面积故障时,比如交换机故障(rack switch failure),可用的机器不足以处理所有的请求。 我们尽可能做的就是用50%的capacity 处理50%的请求或者50%用户的所有请求。而尽量避免整个服务故障。 当设计一个服务的时候,它的throughput应该是可linear scale的。

  在同样的CPU占用情况下,1个机器应该处理100个请求,那么5个机器应该可以处理500个请求。

  而且在同样的机器数量下,20%的CPU可以处理200个请求,那么60%的CPU应该可以处理3倍即600个请求。

  后者是很难实现的,而且当CPU越高的时候,服务的throughput并不是线性的。 通常在80%CPU以上的情况,throughput会下降非常快。 随着CPU使用增加,request的latency也会提高。 这对上下游的服务可能都是一个挑战,可能会导致cascade failure。

  对于nodejs或者java nio一类的async IO框架来说,另外一个问题就是event loop lag。 这两者可能导致connection数量增加。下面举两个例子

  有些RPC transport支持pipelining但不支持multiplexing (out of order responses), pipelining是指在同一个TCP连接上可以连续发出Req1, Req2, Req3, Response1, Response2, Response3,即Response的顺序必须和Request的顺序是一致。Req1如果需要很长时间,Req2和3就都不能返回。一个Request如果占用太长时间,会导致后面的很多个Request timeout。RPC client通常也会限制在一个TCP connection上面的max pending requests。但timeout发生,或者max pending requests情况下,client会主动创建新的connection。

  event loop lag 是指程序占用太长时间执行连续的CPU intensive任务。 只有当任务结束时,event loop才会handle IO events,比如从socket上面读数据。否则收到的数据只能保存在kernel 的TCP buffer里,通常这个buffer size小于64KB。当buffer满时(而且service又很长时间没有读buffer),socket的远端就不能发送更多的数据。这时也会导致远端的transport error。同样的,client会主动创建新的connection,当connection增加到预设的fd limit时,service就不能继续accept新的TCP connection了,其实是不能open新的文件了。而且,绝大部分的程序没有测试过达到fd limit的场景。很多API需要open file, 比如logging和core dump. 所以,一旦达到fd limit, 就像out of memory一样,将很难recover,只能crash process. 而这时正是过载的时候,重启实际上减少了capacity。 任何crash在过载的情况下只会更糟。

  facebook在这防止过载上做的很好,在C++实现的thrift server上,有一个或者多个threads只负责accept TCP connections. 你可以指定最多的connections for thrift calls。 这个connection limit是远小于fd limit, 当connection太多时,thrift server可以fail fast。所以,这种情况下可以让service能一直保持在max qps。

机房360微信公众号订阅
扫一扫,订阅更多数据中心资讯

本文地址:http://www.jifang360.com/news/2015723/n500170377.html 网友评论: pubajax('/comment.aspx','id=126517924270&commCount=1&ChID=0&Today=0','gCount1265179242708730');条 阅读次数:pubajax('/click.aspx','id=126517924270','click_126517924270');
版权声明:凡本站原创文章,未经授权,禁止转载,否则追究法律责任。
相关评论
正在加载评论列表...
function GetCommentList(page) { var Action='id=126517924270&ChID=0&CommentType=GetCommentList&page='+page; var options={ method:'get', parameters:Action, onComplete:function(transport) { var returnvalue=transport.responseText; if (returnvalue.indexOf("??")>-1) document.getElementById("Div_CommentList").innerHTML='加载评论列表失败'; else document.getElementById("Div_CommentList").innerHTML=returnvalue; } }; new Ajax.Request('/comment.aspx?no-cache='+Math.random(),options); } GetCommentList(1);
评论表单加载中...
function GetAddCommentForm() { var Action='id=126517924270&ChID=0&CommentType=GetAddCommentForm'; var options={ method:'get', parameters:Action, onComplete:function(transport) { var returnvalue=transport.responseText; var arrreturnvalue=returnvalue.split('$$$'); if (arrreturnvalue[0]=="ERR") document.getElementById("Div_CommentForm").innerHTML='加载评论表单失败!'; else document.getElementById("Div_CommentForm").innerHTML=arrreturnvalue[1]; } }; new Ajax.Request('/comment.aspx?no-cache='+Math.random(),options); } GetAddCommentForm(); function CommandSubmit(obj) { if(obj.UserNum.value=="") { obj.UserNum.value="Guest"; } if(obj.Content.value=="") { alert('评论内容不能为空'); return false; } var r = obj.commtype; var commtypevalue = '2'; for(var i=0;i
推荐图片