4月刊特别推荐:架构师接龙:岳旭强 VS. 杨卫华

转自:http://www.programmer.com.cn/2767/

主持人

冯大辉彩色冯大辉,阿里巴巴集团旗下支付宝 (中国)网络科技有限公司数据库架构师,负责支付宝数据库架构规划、解决方案等相关工作。

提问嘉宾

岳旭强岳旭强,淘宝网资深架构师,在大型交易网站的设计和调优方面有丰富的经验。2004年加入淘宝,见证了淘宝网业务以及技术上完整的发展过程,参与了淘宝几乎所有核心系统改造,并主导了用来支撑淘宝网未来高速发展的核心业务中心的建设。现在负责网站整体业务架构的设计和规划。

回答嘉宾

杨卫华杨卫华,新浪产品事业部技术经理,专注于开发高并发的分布式应用。对互联网后端技术、分布式、网络编程、XMPP即时通讯等领域感兴趣。曾多次组织广州及珠三角技术沙龙活动。个人Blog:http://timyang.net

岳旭强:企业内部技术产品开源有何好处?需要注意什么?

杨卫华:目前不少心态开放的企业已将一些会给业界带来价值的产品进行开源。新浪也在这方面进行了不少尝试,近几年开源了若干产品。根据我们的体会,产品开源一方面可以促进项目参与人员将技术做得更好,在程序结构、代码风格、代码一致性、代码效率方面会更加谨慎,让源代码及文档达到业内开发人员认可的标准。而业内很多闭源产品通常只要求项目内部范围的可读性及强调代码执行效率,甚至有不少公司项目只关注实现功能,对代码质量和技术文档要求甚少,因此开源在一定程度上是对高标准的自我要求。另一方面开源可以提高公司在业界技术人员中的影响力,增强公司的产品在技术专业人群领域的认可,并有可能吸引潜在的优秀人才加入公司,更重要的是企业的开源产品可以给业界带来价值,减少在相近领域的重复劳动,降低一些同行特别是小公司的开发成本。

但是开源产品并不是提供源代码下载之后就一劳永逸,它需要继续进行后续相关的社区引导,需要项目开源的企业安排专人负责后续跟进。首先要有良好的技术说明文档,如果缺乏文档介绍,感兴趣的开发人员由于对系统缺乏了解而无从下手。可以通过技术文档、博客、技术沙龙等形式将项目向更多的人群介绍,降低开源项目对潜在用户的使用门槛。其次对有兴趣参与后续源代码贡献的开发人员进行更多的沟通,积极介绍项目的设计思路和值得改进的点,对社区提交的代码进行Review审查及最终接受提交并合并进主干库。另外最好还要有相应的项目讨论组或邮件列表供开发者进行讨论。新浪去年也开源了一个SinaDynamoD项目,这是一个类似Dynamo分布式Key-Value实现,由于目前业界对于分布式NoSQL产品比较关注,开源之后也在业内爱好者人群当中引起不少反响。但是由于开源项目主要开发人员工作忙的缘故,后续社区支持工作没有及时跟进,一定程度上延缓了项目向更大范围推广的目标。因此一个开源项目要想赢得长久的生命力,其实需要很多的投入和运营,将源代码开放只是其中很小的一步。

岳旭强:JDK 7给Web带来了什么?协程在老系统上的应用,有哪些挑战?怎么解决?

杨卫华:在Java 7中值得关注的特性之一是JVM底层增加对动态语言新的支持,这对使用Groovy、Jython、JRuby以及Scala等语言的用户是一个好消息。JDK7中还使用了新一代G1垃圾回收算法,垃圾回收算法对于高并发请求Web服务器至关重要。在Web服务器上,如果单位时间请求数过大,大量临时对象需要创建与销毁,Java性能工程师经常要面临临时对象过多造成的OOM(Out of Memory)故障。目前对OOM故障的解决思路主要是投入大量精力去tuning Java GC参数,对当前应用进行全方面压力测试以衡量在生产环境不会出现OOM错误。新一代G1回收算法在一定程度会给高并发Java应用带来很大稳定性改善,同样的应用在Java7上会获得更好的性能。另外值得关注的还有对closure的支持。虽然在过去很长一段时间内,对于JDK7是否要支持closure存在很多不同意见及实现方案,最终结果还是增加了closure,在不少场合极大地简化了Java编程。

服务器开发人员比较关注高并发应用性能,高并发请求最简单的实现方法是每个请求一个线程。但是请求会存在不均衡情况,某段时间请求数过高会导致线程数过多,当线程数超过一定限度后会导致系统出现不稳定现象。目前业界更成熟的做法是使用线程池来处理工作任务,同时用NIO来异步处理网络连接。这种方式的优点是可以处理大部分高并发请求场景,借助一些NIO框架业务实现起来简单,且运行稳定。但是线程池方式也存在一些缺点,由于线程池的工作队列是固定的,一旦工作任务发生阻塞,就可能会导致后续任务全部阻塞。我们也曾经在一些后台服务中遇到过这种情况,比如数据库某个时间段负载过大后导致工作线程等待,从而导致线程池工作线程全部占满,后面新到业务只能等待,从而影响所有业务。虽然数据库访问只是我们所有业务中很小的一部分,但是这一小部分可能最终导致整个系统全部阻塞。另外线程池工作线程不能设太大,否则会因线程切换过多,导致系统大部分开销都消耗在上下文切换上。

由于线程与线程池都存在一定不足并且消耗系统资源过大,目前业界流行一种新的设计思想,用轻量级进程(LightWeight Process)来实现高并发应用。轻量级进程目前并没有统一名称,在某些编程语言中称为协程(coroutine)或者纤程(Fiber)最早带给大家这一设计思想的是Erlang语言,在业界有个著名的试验,英国Richard Jones曾经用Erlang的Mochiweb Web Server成功支持了100万连接,这个对传统语言来说基本是“不可能的任务”最近搜狐公司白社会产品也在生产环境中成功使用了类似架构。除了Erlang之外,基于Java VM的Scala也具有类似轻量级进程(Actor)实现,Twitter的Message Queue产品使用Scala代替了最初的Ruby实现。Google新推出的Go语言其中一大特性是Goroutine,它的设计目标也是一种轻量级进程的实现。因此轻量级进程代表了后端高并发应用的一种设计趋势。

Java现有版本不支持轻量级进程,虽然Scala支持Actor,但是它现有版本的底层是基于Java线程来实现的。Java业界也意识到这种欠缺,于是Doug Lea在Java 7 中设计了一种Fork/Join框架,其基本原理就是轻量级进程设计思想。Fork/Join推出之后,原先基于线程及线程池的应用可以改用Fork /Join来重新实现,编程更简单,系统能处理的并发会更高,任务之间切换的成本将会更低,我们期待这一技术能够早日成熟并得到更广泛的使用。

岳旭强:Web应用的性能、扩展性是业界比较关注的,但是可用性显然更重要,有什么关键措施和经验可以提高系统的可用性?

杨卫华:很多情况下,性能、扩展性和可用性并不矛盾,提高性能的同时可以提高系统可用性。比如新浪博客产品就非常重视改善前端及后端代码的性能,近期几次版本改进的一个重点,就是围绕如何通过提高内部模块的性能,来加速用户页面加载以提高系统的可用性。我们使用了很多方法如增加不同业务逻辑层之间的cache,增加异步处理机制,增加分布式的IDC自治等措施来达成这一目标。提高Web应用的性能及可用性在业界也有很多成熟经验,如《构建可扩展的Web站点》一书中就提到非常多值得借鉴的实用方法。但在另外一些情况下,一些可用性改进方案可能会对系统的性能造成影响,技术架构师通常会对需要进行系统底层调整的需求非常谨慎,这种情况下就需要技术架构师与产品架构师加强沟通,相互理解并最终从用户的角度去考虑及实施方案。

岳旭强:类似Twitter、新浪微博这样的应用,针对第三方开放API接口,如何避免少数应用程序因为用户量激增而对系统带来冲击?对请求数做限制之外有没有更为折衷的办法?

杨卫华:目前大部分开放平台的API设计都是使用HTTP REST 方式接口,HTTP接口的特点是单向请求,服务器无法主动推送数据。针对微博类型的应用,请求方如需获取最新微博数据需要不断轮询。另外由于微博产品的技术特点,用户请求最新数据需要进行一定程度的数据聚合,但由于聚合后的数据经常需要更新也很难有效cache,因此微博接口的请求通常对服务器的资源消耗较大。HTTP单向的特点造成客户端需要更频繁的请求,但是请求消耗资源过大又造成服务器不能承载过于频繁的刷新,因此需要双方进行折衷。新浪微博即将推出的开放平台也和类似平台一样做了请求数限制,这个请求数限制只是为了防止客户端对接口进行过多的滥用,通常不会对正常用户使用造成影响。另外我们也在不断优化技术及架构,希望能不断提高调用上限并最终不加限制。

从原理上来说,能根本解决请求数限制问题的方法是使用推的机制,即服务器一有新的数据就立即推给客户端,而不是客户端不停的询问是否有新数据。目前比较成熟的推的标准技术有XMPP Pub/Sub、Google的PubSubHubbub或类似的HTTP Hook回调方案,但HTTPHook方案要求请求方要有固定公网IP,这无法适用于普通客户端调用的场合,从而限制了这种接口方式的推广。而XMPP Pub/Sub由于对调用方开发的门槛相对要高,普及使用具有一定难度。所以目前来看,HTTP接口方式虽然降低了开发门槛,但存在对服务器性能消耗过大的缺点,目前也没有合适的技术来迅速改变这一现状。

为了防止平台用户激增对系统造成冲击,设计上最好将API平台与Web系统设计成一个相互独立的松耦合体系,避免API用户激增对Web造成影响,而 Twitter中API和Web底层是共用的,一旦出现故障往往是API及Web都会受到影响。另外大部分互联网系统部署的服务器能承载的规模都会比实际访问用户容量大,即使短时间出现大量用户上升,也不会对系统造成太大影响。

岳旭强:最近Twitter、Digg等站点从MySQL迁移到Cassandra,你觉得在国内这会成为趋势吗?你眼中的此类迁移的难点和风险(如果有的话)?

杨卫华:根据我们对相关背景的了解及自身的经验,Twitter等公司目前使用MySQL面临的最大问题是数据急速增长带来的运维及后续开发的挑战。虽然对 MySQL使用了Sharding方案,但是在数据每天增长数千万条记录的情况下,每个月甚至每周都需要增加新的数据库服务器,每次增加都面临分表索引信息的修改,同时由于历史旧数据访问变少,又需将原先多台存放旧数据的服务器进行手工合并,当这些拆分变得越来越频繁但又无法自动化完成时,不停机维护的成本变得非常高。但成熟的产品不希望系统出现停机,于是数据维护变成一个沉重的负担。

另外在开发方面,业务上经常面临新的产品需求要更改数据库字段,但上百台数据库的海量数据让修改字段变得大费周章,大部分情况都是通过增加新表等变通方法实现新的需求,随着零散表的增多,数据访问的复杂性增大,数据架构设计变得不再简洁,系统可维护性变差。在持续海量数据增长的场景下,MySQL的拆分将变成系统运维及架构师的一场噩梦。因此需要一个能够支持数据扩展、自动复制、容错、负载均衡的分布式数据存储产品来解决这一难题。Cassandra的开发人员曾经开发过Dynamo,后来借鉴了BigTable的优点开发了Cassandra,产品完成后经过Facebook在生产环境如Inbox search等产品验证,开源后开发社区非常活跃,是目前解决海量可扩展数据最佳的方案之一。

但是另一方面,架构师也不应盲目追赶潮流,对于国内大部分应用场景来说,如果数据规模单台服务器可以支撑,或者数据增长规模不需要每个月增加新机器的情况下,用传统的MySQL Sharding方案完全可以满足。

岳旭强:在业务不十分明确的情况下,技术决策如何进行?

杨卫华:在业务不明确的情况下,尽量预测各种可能的业务发展方向,找出各个方向的相似点作为技术决策的基本出发点。另外技术架构师也应避免闭门造车,要利用对业界发展方向的一些判断,考虑到新的技术架构中,降低将来潜在的业务调整对技术架构带来的影响。另外架构师及项目开发人员需要具备“拥抱变化”的心态,从用户角度出发,当老的产品设计存在问题时,尽可能积极主动地去重构架构以适应新的业务。

(本文来自《程序员》杂志2010年4月刊)

原文地址:https://www.cnblogs.com/kevinhigher/p/1982983.html