问题导读
1.本文是如何解释分布式系统的本质?
2.实现分布式系统的策略是什么?
每月爬取一亿网页,Bitly从事着典型的大数据BI业务。在Bacon会议上,该公司首席应用开发人员Sean O'Connor就Bitly的分布式架构进行了分享,其中重点介绍了“SOA+队列+异步消息”理念。
从表面上看,Bitly是一家主打URL缩短和分享的公司,然而究其根本,Bitly却是一家真正的大数据公司,每月60亿的点击量、6亿的缩短服务、1亿网页的爬取,Bitly可以说从事着典型的大数据BI业务。在HighScalability近日的一篇文章中,其创始人Tod Hoff分享了来自Bitly的分布式系统打造理念。
以下为译文 你是不是曾经很好奇bitly如何实现营利了?一个URL缩短工具怎么可能那么难写?Sean O'Connor,作为Bitly首席应用开发人员,在Bacon讨论会的一次发言中给出了关于bilty如何营利的答案。
Sean解释到,写一个可用的网址缩短工具是很容易,但是要写一个大规模的并且高可用的则并不如想象那么容易。Bitly并不是通过将URL缩短作为一个服务来实现营利的,它的赢利来自一款数据分析产品,这个数据分析工具将URL点击数据和他们从网络上爬取的数据做对比,帮助他们的客户找出什么类型用户关注了那些网页。
数据分析产品开始是作为一个爬取web服务器日志的后端服务,这些日志包含了来自注解链接的数据和cookie数据,这些数据包括用户从哪里点击了链接,哪个用户点击了这个链接,链接的内容是什么等等信息。但是所有的链接都回到了网站的域名。这样的话,如果让链接转向你另一个域名,那么第三方可以分析这些数据,这个主意听起来很可怕,但是它也是一种天才的想法。
这个话题并不是针对Bitly的架构,这是一个关于分布式系统和如何使用分布式系统去解决一系列问题的本质探索。或许从他的发言中我最喜欢的是这句:
SOA+队列+异步消息真的非常强大。这种方式分离了组件,使工作并发进行,使故障独立发生,同时,使组件很容易解释这些行为。
我同样非常喜欢他的“为什么事件式消息比命令式消息好”的解释,我之前从未听过类似的说法。Sean从实践出发,如果你尝试从单主机扩展到集群模式,这个演讲值得观看。这里让我们看看Sean如何解释分布式系统。
统计
每月60亿的点击量
每月6亿的缩短服务
50人的公司,大概20个工程师
400台服务器,并不是所有400台服务器都用来处理重定向,大约30台服务器处理所有来自外部的输入流量,包括网址缩短、重定向、API请求、网页的用户界面等等。其余的用来处理各种服务,如排序和组织用户数据,或者提供各种不同形式的处理和分析(数据库、metrics、网络爬取、文本分析等等)
每月爬1亿网页
来源
关于BITLY构建分布式系统的经验总结
平台
注意,以下这些只是在发言中被提及的一些技术,并不是一个全面的列表。
·HDFS
·S3
·Nagios
·Bilty使用的实时分布式消息系统是Nsq。
·Bitly使用hostpool管理一系列的主机。
·演讲的结尾部分被剪掉了,提及bilty使用了一些不同了类型的数据库。
论分布式系统的本质
1. 高可用的应该就是分布式的,为了获得一定的可用性,就必须实现地理位置多元性。按照定义,如果你在不同的地区有独立的操作系统,它们就必须是分布式的。
2. 创建分布式系统的老方法。建立抽象让你以为事情不是分布式的。
例如,NetApp,创建了无限容量硬盘的错觉。
Oracle作为一个高可用的数据库,让你以为世界不一样了,但实际上不是。
两者都解决了实际问题,但是都很昂贵,所以做一些不一样的事情吧。
3. 新方法通过接受分布式系统固有的特性来处理问题,将这些抽象为工具提供。重大转变在于你如何看待事情,因为抽象更接近于你构建的现实,你可以做更多有力的权衡取舍并因此更高效的去完成某些事情。
4. 带有一个存储器的4个机器总是比带有4个存储器的1个机器要便宜,这就意味着分布式系统是通往大规模和获取高可用的有效方式。
5. 因为我们从一台机器转向了N台机器,分布式系统的问题就出现了。
组件并发:A机器和B机器同时工作,这就是如何获取横向扩展能力。很强大但是成本是需要在不同机器间协调。例如,当锁数据使机器互相等待彼此,这就不能算是并发了。
缺少全局clock:每个机器有一个不完美的clock,当有超过一台机器并且每台机器有它自己的时间定义,这就意味着发生在不同机器上的事件不能基于时间排序,对bilty而言如果事件相差1到2秒,它们就不清楚哪个先发生了。
故障独立发生:如果A发生故障了,B应该继续工作。
6. 有些问题,比如分析数据太大而不能用一台机器来处理,或者至少这么一台机器不在预算内。
实现分布式系统的策略
面向服务的架构
这儿没有一个庞大的Bitly应用,只有很多通过网络通信的小服务。
它是一个抽象,从代码来看更像是函数,但是是系统级别的。
你不需要记住系统的所有细节,只需要关注API边界与结构。
非常有益于开发和运营
Bitly是一个运行了6年的老公司,有很多的代码。你并不需要查看每一行的代码,只需要运用这些服务。
设计良好的服务只有数百行的代码。
从运营上看,非常容易定位到哪个系统出现了问题,然后你可以仔细检查该系统来发现问题的所在。
故障现在意味着功能受限而不是服务停止。一般来说,每个服务都是设计来解决特定的问题。因为它们和自己的持久层是完全独立的,如果其中一个故障了,唯一丢失的是解决那个问题的能力。但是整体的服务仍然是运行中的。Metric系统停止服务决不会影响URL缩短请求。
异步消息
·发送消息而不用等待接收者的回应。
·在组件间删除队列相当容易了,如果A发送消息给B,而B出故障了,这些消息就会排队等候,当B恢复后继续处理。
·更多的错误处理方式。如果一台机器故障了,消息只是会延迟一些处理,A并不需要知道或者关心B的故障。
·不利因素是操作执行的不如同步请求自然。
·一个URL缩短请求是需要完全同步处理的,因为:
·速度。希望能尽快地返回回复给用户。例如,不想处理队列备份。
·一致性。不希望返回同一个缩短的URL给多个用户,与其给予用户无效链接不如返回一个错误。
·Metrics系统是完全异步的。当Bitly的一个链接被点击,并通过HTTP返回,转换的数据被装入队列用来做数据分析和其他下游系统。如果在处理metrics的过程中有一点延迟,也不会有重大影响。
·消息可以被看作命令或者事件。
·命令是“做X”。
·事件则是“X”发生了。
·事件成了比命令更加有用的抽象。
·更好的系统间隔离。一个命令意味着必须知道谁收到了该命令,否则它没有任何意义。说某个事件发生则意味着我们并不需要关心谁消费了该消息。只需要通知X发生了,其他服务则可以做对应的增量更新,或者相应的操作。
·事件通常映射为多个消费者处理的消息。当一个Bitly URL被解码为HTTP重定向,消息会发送给多个服务:一个持久化服务奖它保存到HDFS及S3;一个实时的分析服务;更长一点的离线历史分析服务;一个注解服务。解码服务只需要把这个时间发布,而不需要去了解任何下游服务。而下游服务关心的只是捕获这个服务,而不管谁给它发送。
·非常容易地添加新的消费者。可以建立一个新的服务,与某个事件关联,生产者并不知道也不关心。一个服务如何处理事件的变化同样的不关心生产者。生产者和消费者是分离的,只通过指定的事件状态关联。
使服务更好的运行
在服务间使用backpressure。如果一个服务处于繁忙状态,它就要告诉其他的请求服务节流它们的请求,从而减少过载服务的压力。例如,指数退避(exponential backoff),帮助阻止了级联错误,同样帮助系统更快地恢复。举个例子,一个依赖缓存的服务需要预热时间,如果请求服务在预热期间不具备back-off,那么数据库可能会崩溃。
绕过故障。例如,服务间的负载均衡。Bitly使用hostpool来管理一系列的主机。客户端向主机请求服务,如果发生故障,客户端则会通知该请求对应的hostpool。给予反馈,hostpool可以管理主机分配路由给健康的主机。
监控
1. 如果只有一两台服务器想知道哪台坏掉了并不难,但是如果有数百台的主机你就需要帮助了。
2. 使用类似Nagios的工具来检查主机状况,检查状态比如“机器是否还在运转”?
3. 运行完整性检查。例如,服务是响应了但是返回的数据被破坏了。
4. 集中化的日志。这个非常重要因为你可以检测跨不同主机之间的故障。如果一个用户造成了所有的错误,那么从一台又一台的机器中检测到错误信息将会非常困难。集中化日志式使检测整体的错误变得更容易,就像所有的错误都来自同一个IP地址。
5. 时间到达正确的人,你如何显示来自工具的信息。
例如,Nsq,拥有一个很好用的管理界面来反馈请求是如何运行的,因此你可以知道队列备份了是因为某台主机。
部署系统的用户界面使部署系统和查看部署历史都变得很容易。如果Nagios出问题了,而某个东西又刚刚不熟,那么它肯定脱不了关系。
经验总结
1. 知识就是力量。你知道的关于事情的属性越多,就越容易做出更好的决定使工作变得更高效,效率意味着你可以以更低的成本使系统更大更快。
2. 为抽象漏洞建立解决方案。如果你使用抽象的一层来隐藏分布式的特性,最终必将失败,代码必须发现并处理任何漏洞。
3. 尽可能的放在一个机器里,如果你不需要一个分布式系统那么就不要创建了,要创建它们很复杂并且昂贵。
4. 在面向服务架构中,故障意味着功能受限而不是停机。
5. SOA+队列+异步消息真的非常强大。这种方式分离了组件,使工作并发进行,使故障独立发生,同时,使组件很容易解释这些行为。
6. 当速度和一致性是至关重要的时,使用同步请求。返回给用户错误信息而不是很慢或者错误的答案。
7. 事件式的消息比命令式的消息要更好些。它们使得系统间更好的隔离开,更自然的支持多个消费者。 助保持服务的专注性,而不用担心服务功能之外的事情。
8. 注解而不是过滤。在生产等级适用过滤将疲于应对下游服务关注的链接例子是公共和私有的链接,过滤私有链接意味着对这些私有链接感兴趣的服务无法获得这些它们需要的链接。注解私有或者公共的链接让服务只处理它们关心的事件。
9. 使服务更好的运行,使用back pressure防止服务过载并绕过故障的服务。
10. 如果没有Nagios来检查,就算几乎可以确定损坏了,你都不能知晓。
11. 工具应该对向人们展示信息,使正确的信息在正确的时间到达正确的人。
|