岑文初:模块化来降低耦合性时如何把握模块划分的粒度?如何权衡复用性与粒度过细导致依赖复杂的矛盾?
杨海朝:耦合性是影响软件系统复杂程度和设计质量的重要因素,模块化设计的目标是建立模块间耦合度尽可能松散的系统,通过尽量使用数据耦合,少用控制耦合,公共耦合的范围和一定要避免使用内容耦合来降低接口的复杂性。
在系统架构中模块化设计对于降低耦合性有非常重要的作用,相关的功能合在一起,不相关的功能分离开来。
模块划分的粒度决定着最终划分结果的合理性和有效性。模块划分的粒度越细,越易于定义和开发,但随着模块数的增加,模块之间的接口也随之增加,使得各个模块在组装成系统消耗的时间增加,同时加大了整个系统测试的复杂度。模块划分的粒度越粗,越有利于整个系统的组装,整个系统的测试复杂度也降低,但整个系统的灵活性下降,难以满足用户对系统的多样性需求。
模块划分的粒度是一个不太容易把握的问题,不同的产品和项目有不同的划分粒度方法。模块化的粒度需要根据模块的三大特征(相对性、互换性、通用性)来把握。每个模块的聚合度越高,耦合性就越低,反之亦然。在做模块划分时,应使模块之间尽可能,块内联系尽可能大,块间联系尽可能小,功能模块逐层分解和细化,直至形成若干容易编写的模块。同时还需要结合模块的功能、模块的规模、模块的出入口等诸多因素综合考虑。模块划分的粒度越小,通用范围广,可在较多应用进行复用,但其较小的粒度组装过程烦琐,会导致复用效率降低。反之,模块划分的粒度越大,组装的步骤越少,可复用效率越高,但其复用范围受到。
岑文初:如何处理高并发系统中缓存失效的场景?
杨海朝:从硬件到操作系统,从系统软件到应用软件,我们随处都可以看到缓存的身影。缓存在Web2.0网站中发挥着越来越重要的作用,特别是大流量的高并发系统。缓存在带来性能提升和支持高并发的同时,也带来另一个问题,如果缓存宕机导致所有的缓存失效,所有的流量都压到后端的服务上,例如数据库层。这时,后端服务因为压力过大无法提供服务或快速响应,缓存因为等待后端请求的响应而“热”不起来,最终导致“雪崩”问题。在高并发系统中,解决缓存失效有以下三个思路。
使用Consistent Hashing算法。把数据缓存分片,减少缓存宕机对服务的影响范围。Consistent Hashing能最大限度地抑制Hash键的重新分布,同时要取得比较好的负载均衡的效果,需要在服务器数量比较少时,增加虚拟节点来保证服务器能均匀地分布在圆环上,最大限度地减小服务器增减节点时产生的缓存重新分布问题。
.................
.................
缓存多份。通过应用写多份缓存,或应用写一份缓存由中间件把此份缓存复制多份,在缓存宕机时能切换到另一份缓存上,减少缓存宕机对后端数据存储的影响。这种方式最好采用缓存之间的复制,减少应用开发的复杂度。
解决高并发系统中的缓存失效问题,需要结合业务逻辑进行综合考虑。
实现缓存持久化或半持久化。所谓的持久化就是定期把缓存里面的数据刷到磁盘,保存起来,在缓存失效时能保证大部分数据仍然有效,例如使用Redis或MemcacheDB把一些数据存到磁盘。可能有人会说:“是否在刷磁盘那一刻会影响缓存的高效性?”这可以考虑通过高端硬件(例如Fushion IO或SSD作为存储设备),来减少刷Cache过程中减少对服务的影响。
这些仅仅是实现的三个思路,各有利弊。解决高并发系统中的缓存失效问题,需要结合业务逻辑进行综合考虑。
岑文初:目前是如何做好应用的依赖监控的?例如依赖缓存,是否知道缓存的命中率情况、使用率等;依赖外部服务,是否知道外部服务的消耗时间、成功失败情况等。
杨海朝:应用监控日益成为保障系统安全运行不可或缺的工具,在提高系统可用率和故障的预警能力、最大限度地缩短故障修复时间方面,日益显示出其重要程度。
此外,对应用依赖的服务的监控也非常重要,目前可以建立一整套监控体系,这套监控体系不仅监控应用自身,同时也对外部服务进行监控。应用在调用依赖服务时,打印应用调用的详细日志,记录调用的返回时间,以及成功与否,同时要求外部或依赖服务提供一个统一的接口,用来返回每次调用消耗的时间以及失败率。通过对这些日志的实时分析来发送邮件和短信报警。
岑文初:系统是否有对内或者对外提供服务,如何管理服务的使用权限,如何做服务升级?
杨海朝:在系统中服务的使用权限至关重要,特别是既提供对内服务又提供对外服务的系统。 目前管理服务的使用权限,设置白名单是最简单的方式。通过设置白名单,只有在白名单里面的用户和来源IP才能访问服务,其他的都无权访问。外部调用服务也通过使用appkey的方式,简单地说是API接口的钥匙,只有通过这个钥匙才能打开API的大门,从而获取数据,同时对appkey的申请设置一系列流程来保证其安全性。根据这些appkey来设置不同的权限等级,控制对目标数据的访问以及调用频率。
.................
.................
通过使用Gearman系统进行“热”升级。在负载均衡设备的后端增加一个代理层,升级时通过对代理层的心跳探测页面修改,把落到这台机器上的流量切走,然后对这台机器进行升级,升级完之后进行测试,测试完成之后,再对某一区间机器进行升级,在某一个时间内测试没有问题,再对其他所有区间进行升级。提前准备好回退机制,保证每次升级对用户的影响最小,力求达到无缝升级。
岑文初:对于不同系统之间的耦合如何处理?比如前端系统要求快速响应大量的用户请求,但是依赖于后端的服务体系,而服务系统的瓶颈可能在数据库读写上,如何协同这样需求差异化系统工作?
杨海朝:不同系统之间的耦合性是指各个系统之间的互相依赖程度。需要熟悉各种耦合性的特性,为不同的系统之间选择合适的耦合性。
如果系统之间采用紧耦合,那么涉及对象与对象的直接通信,这些对象通常比在松耦合系统中交互更为频繁。假如两个对象位于不同系统中并且由不同的网络分开,则会导致性能和延迟问题。
如果系统之间采用松耦合以及基于消息的架构,客户端和服务端不需要知道对方如何实现。两端的消息协议符合协商,则客户端或服务器端的实现就可以根据需求进行变更,而不会互相影响。
松耦合提供了紧耦合所不能提供的许多优点,并且它有利于降低客户端和服务端之间的依赖性。例如采用异步策略。对于需要快速响应的系统,尽可能把过程变成异步的,减少请求者所经历的响应延时。如果系统A同步调用系统B,那么A和B是紧密耦合,而紧耦合的系统是需要共同进退,两个系统需要承担相同的量,并且如果B不可用,则A也不可用。如果系统A和系统B之间是异步的方式,不管是通过消息队列、多播消息、批处理还是其他实现方式,那么系统A和系统B是相互的,如果B宕机,A仍然能够继续提供服务,也即所谓的优雅降级策略。这种异步策略能把高并发的写入高峰变成一个平缓的写入速率,减少了硬件的部署成本,同时可以控制消息队列的写入速度以及优化队列来避免后端服务出现压力过高问题。
岑文初:对于系统优化,平时如何查找瓶颈,最后又如何确定优化后是有效的?可以的话请举例说明。
杨海朝:系统上线,首先对系统进行必要的压力测试,量化能承担的最大量。通过对客户端性能指标和非客户端性能指标进行收集,对系统的响应时间、并发用户数、吞吐量、硬件资源的表现等这些关键点进行分析,最终找到系统的性能瓶颈。
同时通过这些压力测试,确定系统在访问量不端增加时,可能出现瓶颈的组件。压力测试过程中输出详细的日志信息,然后对日志信息进行整理,分析各种组件的性能表现情况。
.................
.................
对于已经在线的系统,要部署好各种状态监控系统,最好以图形化的方式呈现出来。在出现性能瓶颈时,能通过这些状态监控信息,找到性能瓶颈点或将性能瓶颈缩短在一定的范围之内,然后对线上系统按逻辑功能进行划分,例如静态池、动态池、缓存层、数据库服务。修改每个功能模块以便输出详细的日志信息,对这些日志信息进行整理和分析,找到瓶颈所在,同时记录各个功能块的性能表现,在优化后,收集相同信息进行对比来确定优化前后的性能差别。对于单个模块可以通过一些 性能分析工具来对程序的性能进行分析,例如Rational Quantify。
下面以数据库的瓶颈分析为例。
收集一天内所有的SQL语句,以及统计每种类型的语句占的比例。 收集当前系统中CPU、内存、硬盘I/O的表现情况,分析硬件资源瓶颈。 收集满日志并对其进行分析整理。
确定每条SQL语句在数据库中的平均执行时间。
对执行效率低、消耗硬件资源、响应慢并且频繁调用的SQL语句进行优化。 将收集优化后的硬件资源表现情况和之前进行对比,最终量化优化提高的比例。
总之对于不同的系统,寻找性能瓶颈的步骤可能会有所不同,但都离不开对关键数据的收集和分析。 主持人介绍:冯大辉,现任丁香园(http://www.dxy.cn)网站CTO。曾历任支付宝架构师、数据库团队负责人等职。
提问嘉宾介绍:岑文初,2006年加入阿里巴巴,2007年初开始负责阿里软件平台架构设计,2007年底开始进入开放平台领域,2009年8月加入淘宝开放平台,现在是淘宝开放平台主架构师。自认没有特长,只是学习能力比较强。
回答嘉宾介绍:杨海朝,新浪首席DBA,负责整个公司的数据库管理工作。热衷于数据库设计、性能优化、分布式部署方案和高可用性方面的研究。在大规模高并发、海量访问特别是大规模数据库运维方面有丰富的管理和维护经验。
五 18
架构师接龙 杨海朝VS. 孙立
主持人:冯大辉
杨海朝:在错综复杂的庞大系统中,如何避免多条线频繁地发布新代码对线上业务的影响?
.................
.................
孙立:在公司或者业务快速发展的过程中,应用系统的功能越来越丰富,系统模块也变得非常繁杂。由于前期没有进行良好的整体架构,后期又为了快速响应需求,所以系统模块、多个业务线之间的耦合性非常强,很可能代码也不太规范,导致出现发布了A系统的A模块的代码后,B系统的B模块出现了问题,而B系统的B模块开发人员花了一整天的时间才发现问题是由于A系统的某个发布版本导致的。所以可能出现在系统长期运行稳定、压力不大的情况下,突然宕机或者报错,经过大量时间的诊断,发现是由于另外一个系统发布了新版本,接口不兼容所导致。解决这些问题,不仅会浪费开发人员的大量时间,而且这些问题对线上业务的影响也是巨大的,如何减少甚至避免这些问题的发生呢?我认为在整个系统架构上应该有下面的考虑。
代码版本回滚。代码回滚功能可以快速地使出现问题的错误版本轻松恢复到上一个正确版本。最简单的方式就是通过svn来实现。如果系统在发布新版本后,出现了没有预估到的错误或者故障,那么就可以快速回滚到上一个发布版本。谁也不能保证新发布的版本万无一失,所以快速回滚功能是需要频繁发布的系统所必需的功能。
分层接口化和组件化。接口化和组件化可以促使系统模块之间更加抽象化,在更换接口的实现方式或者组件时,不更改调用者的代码,就可以使系统稳定地平滑过渡。2010年,手机凤凰网就通过这种方式,在不更改代码、不停机的情况下平滑地将底层存储从TTServer迁移到自行开发的NoSQL存储上。接口化和组件化还能更好地实现代码重用,开发人员可以把接口实现类和组件开发得更加稳定。因此,在系统内部,要尽可能地分层接口化和组件化。
服务化。服务化应该算是对接口化和组件化一个更高的抽象,是将系统需要的某些功能成单独的、稳定的可靠性服务,通过约定的协议进行交互。比如系统的用户登录可以成SSO服务,用户IP归属地功能、文件上传功能、图片处理也都可以分别成单独的服务。我们可以部署一套服务进行抽象化,供所有的系统使用。这样服务和系统的功能都简化和抽象了,也更加容易维护和开发新功能。可以想象,在系统发布新版本后,就不会再影响上传功能、图片处理功能、登录功能的正常运行了。
自动化测试。自动化测试有助于发现人工不好发现的Bug。开发人员在开发程序时,尽量多使用单元测试;在代码发布之前,进行自动化的单元测试检测,只有全部单元测试通过后才允许发布。
应用监控。通过上面的方法并不能100%地避免由于代码频繁发布带来的系统影响,但是我们需要尽可能快地知道带来的影响。所以我们需要对应用进行全面监控,这里的监控不同于系统运维人员使用的Cacti之类的对操作系统、数据库等底层的监
控,而是对系统的输入输出、系统服务接口的进行正确性、响应时间等的监控。
.................
.................
杨海朝:在设计一个大规模伸缩性服务时需要做好哪些准备?是否会考虑分区、故障、自动化、异步等方面的问题?
孙立:在设计一个大规模系统时,我们首先要考虑满足用户需求,如果不能满足,那么这个系统就是废品。其次是系统的可伸缩性,我认为可伸缩性大致可以从以下两个方面来看。
功能和需求的伸缩性。功能和需求的伸缩性是指随着业务的发展,可以在现有系统上方便地增加、删除一些功能,并能快速应付需求变更。系统要想实现功能和需求的伸缩性,架构师不但要深刻理解需求,还要深入到业务中去,要对业务有深刻的理解,然后结合系统设计,考虑各种业务需求可能的变化和发展。
性能的伸缩性。性能的伸缩性是指系统能应付不断的数据量增加和访问量增长。性能的伸缩性可以通过硬件的横向扩展(Scale-Out)或纵向扩展(Scale-Up)来完成。通过升级硬件带来的纵向扩展虽然易于实现,但能力有限,所以在设计大规模系统时,必须采用通过增加机器的横向扩展方案。
要实现横向扩展,最简单的方式就是让系统无状态。比如Web服务,如果不使用本地文件、Session等有状态的模式,即可快速地在负载均衡后端增加机器进行扩容。然而,最终的数据库往往是集中式的,所以还得根据应用场景来进行数据的分区、主从复制等来实现横向扩展。
要保证一个大规模伸缩性服务具有高可靠性、高性能、高可用性,还需要进行一些故障的自动处理(比如故障的自动切换),进行全面的有效监控。面对一些跨机房请求、网络连接处理、I/O密集型、CPU密集型等操作时,我们要考虑是否需要异步化、线程池化、使用事件驱动模型、多种语言的融合使用等。
杨海朝:对基于网络的分布式应用,网络传输是一个影响应用性能的重要因素。如何在架构中合适地使用缓存来节省网络传输带来的开销?
孙立:一个大规模可伸缩性应用,必然是一个基于网络的分布式应用,网络传输在其中扮演着重要的角色。按照网络传输的类型,大致可以分为同机房(局域网)和跨机房(广域网)两种网络传输。
同机房网络传输不但速度快,而且非常稳定。正因为如此,大部分开发人员不曾注意到同机房数据传输潜在的问题,即使是我们常用的千兆交换机、千兆网卡也是有千兆上限的,在高并发下,非常容易跑满上限,影响整体的性能。所以,在架构一个大规模的分布式应用时,需要适量考虑本地Cache、数据压缩传输等以节省内网网络传输量。比如Memcached服务器缓存了大量的大文本信息,那么最好使用压缩,这样不但可以节省网络传输,还能节省内存。
.................
.................
为了解决架构设计中不断出现的超过预估的数据量和访问量,需要做到以下方面: 第一,进行良好的可伸缩性设计; 第二,要对数据量和访问量进行监 控,并保持敏感性; 第三,控制恶意访问。
跨机房网络传输的速度和稳定性都得不到很好的保障,而且带宽还是需要付费的。在国内环境下,跨运营商的网络传输就更加不稳定。如果应用程序通过阻塞的方式进行跨机房请求,在网络不稳定时,对系统的冲击将会是灾难性的。解决跨机房网络传输的方案大致可分为客户端和服务器端两种模式。
客户端模式主要是通过浏览器的跨域处理能力把不同机房的数据组合在一个页面。一般通过iframe、JS回调等方式进行跨机房数据传输,常见的第三方统计系统就是使用的这种方案。客户端模式不但容易实现,而且避免了对服务器端产生额外压力,通过异步化处理,还能提高页面渲染的速度。不过还需要考虑到客户端模式安全性低、不能处理复杂业务逻辑、不支持WAP网站等问题。
服务器端模式处理跨机房网络传输要复杂很多,需要考虑数据一致性、避免阻塞式网络传输影响性能、带宽成本等。一个高并发应用,如果存在大量的阻塞式跨机房请求,不但占用大量的带宽成本,而且性能和访问速度也会急剧下降。根据用户在一定的时间段内上网地点固定不变的原理,那么用户始终都是访问的同一个机房。这样就可以针对用户来做Local Cache,缓解跨机房传输的成本。机房之间通过队列的方式进行异步和压缩传输,不但能极大地提高系统性能,而且对用户来说,几乎也感 觉不到延迟。
杨海朝:在架构设计中如何应对不断出现的超过预估的数据量和访问量?
孙立:系统在实际的运营过程中,虽然经过测试和调研分析了可能的数据量和访问量,但还是有可能因为突发事件、预估不准确而导致数据量和访问量大大超出预期,那么我们一般可以从以下几个方面来解决。
进行良好的可伸缩性设计。出现超过预期的数据量和访问量时,能够快速通过增加机器进行横向扩展,而无需改写和优化系统代码。
一个无状态的应用是最容易扩展的。Web服务器可以很容易地设计成无状态模型,从而可以方便地增加机器进行扩展。数据库和存储可以通过数据分区来进行扩展,数据分区其实也算是对状态的弱化。
要对数据量和访问量进行监控,并保持敏感性。监控能使我们更快地了解系统数据量和访问量增长的情况,甚至可以预测短期内可能的数据量和访问量增长,以便提前进行扩容准备。
.................
.................
控制恶意访问。对恶意攻击性访问,我们必须进行阻止,以防止影响正常的系统访问。比如一些不知名的爬虫恶意爬取、接口调用方由于Bug导致了大量的访问,所以在操作系统层和应用层都应该对恶意访问有所控制。
杨海朝:分布式的数据存储层如何结合应用特点选择合适的存储方式?比如MySQL、Redis、MongoDB等的应用场景。
孙立:选择存储方式首先要考虑满足应用的功能需求,其次要满足应用的伸缩性需求,最后需要考虑的是性能,结合具体的应用场景再进行权衡选择。
Web2.0时代具有大数据量、高并发等特点,所以我们往往会结合应用的特点,把多种数据存储结合起来使用,使它们发挥各自的优点。比如复杂点的关系查询考虑用MySQL,高并发的点击统计考虑用TTServer,列表类型的缓存考虑用Redis,字段不固定的文档存储考虑MongoDB。同一份数据还可以存入到多种存储,根据查询场景分别选择适合的存储查询。
杨海朝:分布式数据库中如何考虑一致性、分区策略和延时问题?
孙立:在系统架构中使用分布式数据库时,我们必须面对一致性、分区策略和延时问题的处理,也就是著名的CAP理论阐述的问题。对CAP的选择需要结合我们的应用场景来选择。
一致性问题。其实延时问题也是一致性问题。一致性可以分为强一致性、弱一致性和最终一致性,并不是所有的应用都需要强一致性。根据应用的特点,为了提高系统的整体性能,我们还可以考虑会话(Session)一致性。比如用户发表的微博、评论数据,用户自己可以马上看到,但是其他用户可能需要等一段时间。还有一些场景需要强一致性,比如支付问题。
MySQL数据库一般会使用Master-Salve复制模式进行扩展。在高压力访问情况下,MySQL数据库主从复制延迟可能变得非常高。我们可以从上面提过的会话一致性来解决复制延迟问题。另外一个方案就是提高复制速度。在MySQL主从复制过程中,从服务器解析出binlog日志后,向从数据库执行写入操作是单线程的。如果你可以修改源代码把MySQL复制变成多线程那就更好了,还可以通过增加从库实例,从库只复制部分表的方式来变相地进行并行复制。MySQL5.1以上版本提供的行复制模式
也可以加快复制速度。
分区策略问题。为了提高数据库的性能和可扩展性,我们往往会根据某些规则把数据进行拆分存储。分区策略应该遵循查询能在一个表完成的原则,尽量避免跨表查询。不管以Hash、Range或者其他
.................
.................
方式都必须遵循这个原则。如果因为有多种关系查询,无法达到一次分区就满足上述原则,那么可以进行多次分区和冗余存储。
主持人介绍:冯大辉,现任丁香园(http://www.dxy.cn)网站CTO。曾历任支付宝架构师、数据库团队负责人等职。
提问嘉宾介绍:杨海朝,新浪首席DBA,负责整个公司的数据库管理工作。热衷于数据库设计、性能优化、分布式部署方案和高可用性方面的研究。在大规模高并发、海量访问特别是大规模数据库运维方面有丰富的管理和维护经验。
回答嘉宾介绍:孙立,去哪儿网高级系统架构师,曾就职于凤凰网、酷6和搜狐。对分布式搜索引擎开发、大数据量网站系统架构优化、运维监控等有丰富的经验。开源项目phplock和phpbuffer的作者,近期开发了NoSQL数据库存储INetDB。
架构师接龙 孙立VS. 孙朝晖
作者: liyn 分类:CTO视点 阅读:3,205 次 添加评论
主持人:冯大辉
孙立:你是如何在架构层面,提高开发人员开发效率的?比如通过合理的分层,不同层安排不同能力的开发人员。
孙朝晖:首先孙立老师已经谈到了这个问题的两个核心,第一是合理的分层,第二是让不同能力层次的队伍有机组合。
对于分层,具体到我们的技术体系,可以清晰地分成四个层次,对应四个技术层次,分别是:
前端(JavaScript开发)、Web应用(PHP开发)、中间件(Java开发)和通信与管理基础(C开发)。各层有的团队,开发人员专注于本层次的技术发展,各层次的开发团队Leader每日进行晨会交流开发进度,每周例会进行技术整合研讨。对于较完整的功能模块,设置有“技术方案评审会”,各团队专家参加,通过对各层技术特点的分析,综合考虑方案的可行性。
对于组织结构保证,每个团队都会有1~2名技术专家,1名团队Leader,若干开发人员。
每个团队的技术专家负责开发基础框架,比如我们PHP应用的MVC框架、Java的Service Framework、前端JavaScript的基础类库,对于不同层次的开发人员根据能力安排角色,决定担任部件级别开发还是组合功能级别开发,保证每个团队都有不同层次的人员合理组合,每个开发人员都
.................
.................
保持技术上升通道。这样会有效地提高开发效率,同时每个技术人员都有清晰的当前定位和未来定位,有利于技术团队的成长。
孙立:要变更数据库结构,有什么经验可以分享?
孙朝晖:这个问题是互联网行业的通用难题,数据量大,数据结构变更的代价太大,对于这个问题,我想从四个方面进行介绍。
在技术方案评审阶段,充分考虑数据存储方式的合理性。不是每种数据都适合采用数据库存
储,有些数据适合采用JSON,或者采用缓存中的List对象存储,而不适合分解到数据单元,这样的数据就没有必要设计成为关系型结构。
在数据结构设计过程中,保留适当的冗余字段,尤其是预估有动态变更的数据结构,而且状
态标志尽量组合成为数据位结构,即典型的Mask应用。需要扩充状态位时,采用位扩充的方式替代字段扩充。
对于数据量很大的数据结构,比如我们业务当中的Feed数据,保持数据按照代龄进行分层,
并且有合理的归档结构,保持活跃数据所在库的规模不过度,对于活跃数据库需要紧急调整的时候,变更代价也是可控制的。
对于数据量非常大的数据需要调整数据结构,那么只能靠数据库架构解决。我们采用的数据
库架构都是M-M-S-S架构,需要进行大规模数据迁移,所以会利用备份库进行轮换下线(或半下线)维护变更,通过轮次的数据结构调整,最终达到数据结构完全变更。
孙立:如何搭建更加有效的测试环境?测试环境和线上环境毕竟不可能完全一样。
孙朝晖:我想分成两个方面来回应。
功能测试环境的建设:功能测试环境主要面对的挑战不是线上、线下系统结构不一致,而是
测试数据的不一致,由于数据不一致导致某些边界条件没有测试出来。对于这个问题,需要保持线上、线下关键数据的增量同步,采用小时间粒度的定期日志备份方法解决,同时要保证活跃数据的规模,以便能够控制线下数据库同步的规模。
功能测试环境组建的另外一个要点是关注网络结构的等价性,通过虚拟机系统增加与现网等价的网络拓扑结构。尤其是在交换设备和域名系统上尽可能保持一致,因为有很多问题是由于物理部署结构引起的,从开发的角度很难发现,只有通过一个相对完整的功能测试环境方可发现这一类问题。
.................
.................
性能测试环境的建设:性能测试环境的建设主要用于发现性能问题和容量规划。对于发现性
能问题的目标,只要保持数据库服务器尽可能使用物理主机,在物理主机上采用多实例隔离的模式部署,其他服务器可采用虚机化技术,这样可以保持测试数据的可用性。
需要解决的主要问题是容量规划这项工作,由于线上与线下服务器的硬件类型和规格不一致,网络拓扑结构也不同,也无法完全模拟线上环境。所以我们一般采用的方法是,对服务器进行角色类型划分,同一种角色的服务器在性能测试环境下必须有统一类型的服务器对应,有对应的确定性物理配置,在性能环境测试后,首先安排预上线测试环境,通过七层交换或者应用程序本身的流量复制,把线上的服务压力导流到预上线环境,进行小规模再测试,得出单机的性能数据与性能测试环境的对比,并根据单机的性能测算对比,做出线上的容量规划。按照容量规划进行系统实施后,根据实际的测试数据再调整,有可能因容量估计过高,服务器能力有冗余,需将服务器标记为空闲,留待后续部署使用。
孙立:你如何看待NoSQL的?
孙朝晖:我们在建设Feed中心时经过了对NoSQL的充分测试,比较了多种NoSQL技术方案,包括Cassendra、MongoDB、Redis和MySQL HandlerSocket,最终我们采用了MySQL HanlderSocket作为我们的NoSQL解决方案。
NoSQL对SNS类的应用场景来说还是很实用且必要的。因为我们要求的Write throughput很大,数据结构简单,仅需要弱一致性,所以在这种场景下使用NoSQL还是比较合适的。
但对于目前主流NoSQL产品推崇的自动分区等高端功能特性,我们经过测试和权衡还是觉得很难用到实际场景下。一方面是这种自动化分区管理功能使得系统自身的复杂性太高,部署和监控复杂;另一方面是NoSQL产品缺乏专用的备份工具,系统出现单点故障后,恢复的代价太高,给运维造成了很大的压力。
我们最终选择实用MySQL HanlderSocket作为NoSQL解决方案的原因是此方案能够利用MySQL数据库本身的全部分布式特性和管理特性,系统可控性更强,对于运维、数据老化处理、性能调整等方面都有成熟的方向。
对于NoSQL本身的发展和应用方向目前我个人还不是看得很清楚,例如几乎全能的Redis出现,大家会如何使用?在我们的技术体系内使用Redis作为内存缓存,替代了Memcached,没有启用持久化功能。
.................
.................
我个人认为,采用NoSQL技术还是需要经过充分评估的,尤其是与物理架构设计师和运维部门充分沟通,平衡开发和运维的整体工作压力。另外使用之前尽量充分阅读源代码,具备自我技术支持能力后再投入使用。
孙立:你如何看待横向扩展(Scale Out)和纵向扩展(Scale Up)?
孙朝晖:我个人认为,Scale Out是互联网服务的必由之路,分布式技术是互联网服务不可或缺的技术能力。但随着服务器规模的不断扩大,运维的压力会越来越大,到了一定系统规模,必须回归到提升单机QPS能力的方向上来。但是我觉得这里的提升单机QPS不是简单的ScaleUp,而是一个综合优化的过程,比如下面这些实例。
我们采用配置了SSD卡的服务器,以本地存储方式替代SAN存储设备作为MySQL数据库
的文件存储,提升了MySQL单机访问能力。
我们正在测试使用虚拟机的方式,将Java中间件的物理服务器分拆成为多个虚拟机服务器。
由于受到JVM的内存,我们的单机中间件服务器始终没有得到充分的利用,可以尝试一分多,提高系统并行访问能力。
对单机的性能提升,我们更倾向于在单机内部采取应用结构内的Scale Out方式,比如刚才
说的虚拟机拆分,还有使用异步I/O替代多线程、对象池技术等,最后可能采取选用内存升级或CPU升级的方案。而Scale Up仅是为了满足某个具体需求采用的综合解决方案的一个组成部分。
孙立:大型网站往往会将多种语言进行融合使用,关于这方面,你有什么经验分享?
孙朝晖:这是一个互联网行业遇到的通用问题,由于互联网行业采用开源软件比较多,往往由于开源软件的引入,引入了一些非本服务体系内的主流开发语言,比如Scala、Erlang等。这个问题我有两点想说。
第一,在我们的技术体系内,我是比较倾向于减少开发语言使用的。我们每个层次采用的技术都比较确定,Web采用PHP,中间采用Java,基础通信部分采用C语言开发,个人认为引入太多的开发语言和技术,会对技术团队成长和线上业务的可维护性带来很大的问题。
第二,虽然我们的开发技术较少,但仍然有异构平台之间的通信问题。在我们的业务中,还有一部分是用Windows平台C#技术开发的。为了解决异构通信的问题,我们自主研发了基于ProtocolBuffer序列化协议和TCP的RPC通信协议,分别使用C#、Java、C(包括PHP Extension)开发了RPC的通信协议栈,解决了跨平台通信问题。当然选用Thift也是一个不错的选择,我们没有选用它主要是为了兼容我们IM软件的采用SIP协议。我认为解决异构系统通信问题的需要考虑以下几点。
.................
.................
在技术层次之间的通信协议尽量不要选用某种语言的私有标准,尤其是数据序列化,这样有
利于扩展到通用的技术平台。
在通信模型上尽量选用通用设计结构。比如我们的进程间通信模型选择了Unix Domain
Socket,保持与远程通信方式接口一致,保持可一致性,方便于服务的物理架构迁移。
在开源软件选择上尽量选择我们技术标准范围内的技术。如果没有找到对应项,一般选择改
造现有相似开源软件或者开发的方向。由于我们选择Java和C开发技术,开源软件很多,目前来看还没有出现某个方面找不到对应功能的开源软件的情况。
孙立:对于大型系统的突发性故障,如何在架构层面帮助快速定位故障的原因?
孙朝晖:互联网应用系统由于涉及多服务集成,以致多数的异步调用造成突发性故障很难排查,针对这个问题我们主要采取以下几点策略。
每次出现故障时进行分析,准确定位故障的源头逻辑节点与物理节点,统计后作为知识库,
标识出每个系统中的脆弱节点,出现故障后,优先挑选脆弱节点排查。
在架构进行Review时,尽量保持每个业务流程保证不超过3个物理节点的请求跳转,尽量
减少物理层次深度。还有保证在一次调用流程中,级联的异步调用至少2次以下。在所有发出连续同步调用的初始节点上负责统一trace,方便故障排查。在物理架构图中标出这些调用流程中的关键节点,出现问题优先从关键节点开始排查。
在物理架构上,尽量明确服务器的角色,在某个角色服务器上部署同类型的服务。对于Java
中间件服务器由于服务数目较多,尽量采用虚拟机技术拆分。单独服务器承载服务,比较容易定义监控策略并发出预警。
每次故障后Review告警与故障的关系,对没有及时告警的部分增加告警监控,告警不准确
的部分及时修正,增强监控和告警的准确性。
在我们的技术体系内开发了针对分布式应用系统的部署和监控系统,应用服务器会集中的监
控服务器汇总系统日志,统一与预警和告警系统集成。
主持人介绍:冯大辉,现任丁香园 (http://www.dxy.cn)网站CTO。曾历任支付宝架构师、数据库团队负责人等职。
提问嘉宾介绍:孙立,去哪儿网高级系统架构师,曾就职于凤凰网、酷6和搜狐。对分布式搜索引擎开发、大数据量网站系统架构优化、运维监控等有丰富的经验。开源项目phplock和phpbuffer的作者,近期开发了NoSQL数据库存储INetDB。
.................
.................
回答嘉宾介绍:孙朝晖,飞信互联网产品首席架构师。负责飞信SNS业务相关产品,空间、开放平台的总体架构设计与飞信
开发团队技术社区建设。2010年加入北京新媒传信科技有限公司。曾历任微软(中国)高级顾问、高级项目经理。
如何穿越团队协作的五重障碍
1、信任缺失 2、惧怕冲突 3、承诺不足 4、逃避担责 5、漠视结果
冯大辉 vs. 王速瑜:支付宝架构师对话腾讯研发总监
作者: zhengke 分类:CTO视点, 架构实践 阅读:16,042 次 添加评论
不久前,我们发表了支付宝架构师冯大辉提出的问题,并邀请了腾讯的研发总监王速瑜先生做出回答,下面登出本次问答的节选,希望广大网友和读者们积极参与,提出你们想要问的问题。
王速瑜,腾讯 R&D研发总监,从事产品研发和管理工作,对互联网产品发展趋势、管理理念、技术架构有浓厚的兴趣和深入研究实践。目前主要关注敏捷开发、大规模应用架构、企业SAAS、Web2.0产品的相关技术和趋势。博客地址:http://blog.thinklet.net/mantian/
冯大辉:假设一家C2C 网站,DB中某表存储买卖双方交易的数据信息,对于一条交易来说,买卖双方数据具有一定程度的耦合性,比如卖家的状态更新对应买家的状态也会更新,对于一个中大规模的电子商务网站,架构师在设计中如何考虑数据分片的问题(假定该表随着数据的膨胀必须拆分)?
王速瑜:对于一个中大规模的电子商务网站,随着网站的不断发展,其相应的数据规模会不断膨胀。数据分片技术是使网站得于实现可扩展性的一种常用解决方案。对于C2C类型的网站,由于交易记录不容易进行水平的数据分割,因此对于这样的应用处理要在进行细分:
.................
.................
1. 买卖双方交易的信息,具备较高的时效性,即交易全部完成后就不会再有更新,因此这部分数据可以与正在交易中的数据区分开来,并可以单独分表,定时归纳。具体的做法可以采用水平分割的数据分片技术,比如可以根据用户号码段范围进行切片,把不同的群体划分到不同的 DB 上,这样可以很好的进行横向水平扩展(Scale Out)。它可以很好的突破单节点数据库服务器的 I/O 能力,解决数据库扩展性问题。
2. 对于正在交易中的数据,主要根据时间进行分表。如果分的更细,则可以分三个表,但是这样在事务
保证方面则要复杂很多,不建议这样做
冯大辉:技术团队在开发过程中是否进行集成测试? 进行与否的理由各是什么? 对于集成测试你是否有其他补充?
王速瑜:有进行集成测试,因为集成测试对于产品版本的发布是一环重要的保证。但是由于互联网产品研发的敏捷性,很难建立一套大而全的集成测试平台,而更多还是在功能级和模块级别上的集成测试。
互联网产品的测试跟传统的软件测试不太一样,互联网产品的特性是短平快,因此敏捷开发的理念在互联网产品研发中非常适合,腾讯很多团队都采用敏捷开发的实践,包括TDD,重构和持续集成。因此集成测试更多是体现在产品的每个小迭代和小发布中。互联网产品技术架构都是分层的,因此对于后台server的集成测试也很重要,这个在迭代过程的测试中容易被忽略。这一块往往需要开发额外的工具来辅助进行,比如对于协议接口的测试,通常会有一些小工具来辅助进行。
冯大辉:对于一个架构师来说,如何与冗杂的会议进行斗争? 你有哪些心得或者贵公司有哪些针对会议的策略呢?
王速瑜:对于架构师,参加会议是必然的,架构师往往都需要深入到具体的项目中去,在项目的开展过程,大概会有几类会议是由架构师发起或重点参与的,包括迭代0的架构设计讨论会、定期的架构和代码Review会等等,项目之外,架构师通常还会参加诸如行业级和公司级别的一些盛会和峰会。对于会议,更多还是抱着有益,高效的态度去参加。在实际工作当中,我觉得有以下几点是可以参考的: 2. 3.
.................
.................
4. 涉及架构发展和改进的会议一定要进行, 而且要在产品研发过程中阶段性进行。有利于保
证架构工作的可持续发展; 由架构师主导的会议,要把握高效会议的原则,包括会议前的充分准备工作、会议进程的把握、会后的关键事项跟进等等;
6. 7. 8.
架构师要积极参加产品的讨论会,了解产品发展的规划和细节,有很多架构工作是需要技术
与业务相平衡的,参加这样的会议有利于架构师更好理解业务和它的发展,从而为架构的平衡做出更好的判断;
10. 11. 12.
架构师要扩展视野和保持不断学习的态度,因此行业技术盛会、公司技术峰会、产品月会等
等类型的会议架构师要主动选择性去参加,可以保证架构师能了解技术趋势,提升自己的能力。
14.
率。
不必要的会议尽量不参加,可以采取其他沟通手段,如邮件,IM工具来替代,提升沟通的效
冯大辉:架构师是否有必要关注用户体验? 如何从架构师的层面关注用户体验?
王速瑜:非常有必要。保证用户体验是所有软件最重要的目标,特别是互联网产品,如果该目标无法实现,再好的架构也没有存在的意义。因此如何在满足用户体验的前提下进行架构设计是架构师的必要素质。
产品的用户体验包括几个方面:产品的功能便利性、产品可用性、性能、安全性等等。例如:战类的游戏,需要优先保证其实时性。而在C2C订单交易中则优先保证其金钱的安全性。因此如何从架构层面就去关注用户体验非常重要。对于架构师来说,通常有以下几点是需要注意的:
2. 用户体验表现在外表,但来源与内在。比如互联网服务的性能设计,能否让用户在1秒内使用你的产
品,将是保证用户继续使用产品的关键所在。架构上如何做得在海量用户的前提下很高的性能,就应该是架构师首要关注的点;
.................
.................
3. 用户体验与架构设计有时候会对立矛盾,架构师需要平衡。比如为了某个用户体验,可能需要架构上
做出重点的调整,可能会带来巨大的运营成本。这个时候就需要架构师来Trade-Off了,柔性可用依然是可以采取的架构原则; 4. 5.
6. 一切以用户体验和价值为核心是每个架构师在架构互联网服务的基本准则。互联网服务不同于传统软
件,UGC型的互联网产品更是如此,没有用户参与,再好的架构都是无益的,因此架构设计需要围绕用户体验和价值来持续进行。
.................
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务