11月 24

首先,非常感谢 OneAPM 技术公开课举办的这次活动。本场演讲我主要阐述一下,58 同城从小流量、中等规模流量、大流量,到更大的流量过程中,架构是怎么演进的?遇到了哪些问题?以及如何解决这些问题?

好的架构不是设计出来的而是演进出来的

对很多创业公司而言,在初期的时候,我们很难在初期就预估到流量十倍以后、百倍以后、一千倍以后网站的架构会变成什么样。当然,如果在最初的时期,就设计一个千万级并发的流量架构,那样的话,成本是也是非常之高的,估计很难有公司会这样做。

所以,我们主要来讲架构是如何进行演化的。我们在每个阶段,找到对应该阶段网站架构所面临的问题,然后在不断解决这些问题的过程中,整个战略的架构就是在不断的演进了。

其实,在 58 同城建立之初,站点的流量非常小,可能也就是是十万级别,这也就意味着,平均每秒钟也就是几次的访问。此时网站架构的特点:请求量是比较低,数据量比较小,代码量也比较小。可能找几个工程师,很容易就做一个这样的站点,根本没什么「架构」可言。

其实,这也是很多创业公司初期面临的问题,最开始58同城的站点架构用一个词概括就是「ALL  IN  ONE」,如下图所示:

好的架构是进化来的,不是设计来的

就像一个单机系统,所有的东西都部署在一台机器上,包括站点、数据库、文件等等。而工程师每天的核心工作就是 CURD,前端传过来一些数据,然后业务逻辑层拼装成一些 CURD 访问数据库,数据库返回数据,数据拼装成页面,最终返回到浏览器。相信很多创业团队,初期做的工作也是类似,每天写代码,写 SQL、接口参数、访问数据等等。

这里需要说明一个问题,大家都知道目前 58 同城使用的是 Windows、iis、SQL-Sever、C# 这条路。现在很多创业公司可能就不会这么做。58 同城为什么当时选择了这条路?原因是公司招聘的第一个工程师和第二个工程师只会这个,所以只能走这条路。

如果可以重来?那么会选择LAMP

很多创业的同学可能会想,如果我们初期希望做一个产品的话,我们应该使用什么架构? 如果让我们重来,可能我们现在会选 LAMP,为什么?首先是无须编译,而且快速发布功能强大,从前端到后端、数据库访问、业务逻辑处理等等全部可以搞定,最重要的是因为开源产品,是完全免费的。如果使用 LAMP 搭建一个论坛,两天的时间就很足够了。所以,如果在创业初期,就尽量不要再使用 Windows 的技术体系了。

好的架构是进化来的,不是设计来的

在这个阶段 58 同城面临的主要问题是什么?其实就是招人。很多工程师可能都是再培训学校里培训了3月就过来上班,所以他们写 CURD 的话很容易出错。当时,我们引进了 DAO 和 ORM。虽然那些培训了几个月的工程师可能写CURD不是特别的擅长,但是他们写面向对象的一些程序引入了 DAO 和 ORM,让他们不再直接面对 CURD 语句,这样就会相对容易一些。因为工程师比较擅长的是面向对象的数据,不是 CURD,所以我们当时引入了 ORM,总的来说,如果大家现在的项目处于一个初期孵化的阶段,DAO 和 ORM 能够极大的提高效率,而且可以降低出错的概率。

中等规模:流量跨过十万的阶段,数据库成为瓶颈

随着 58 同城的高速增长,我们很快跨越了十万流量的阶段。主要需求是什么?网站能够正常访问,当然速度更快点就好了。而此时系统面临问题包括:在流量的高峰期容易宕机,因为大量的请求会压到数据库上,所以数据库成为新的瓶颈,而且人多的时候,访问速度会很慢。这时,我们的机器数量也从一台变成了多台。现在的架构就采用了分布式,如下图所示:

好的架构是进化来的,不是设计来的

首先,我们使用了一些非常常见的技术,一方面是动静分离,动态的页面通过 Web-Servre 访问,静态的像图片等就单独放到了一些服务器上。另外一点就是读写分离。其实,对 58 同城或者说绝大部分的站点而言,一般来说都是读多写少。对 58 同城来说,绝大部分用户是访问信息,只有很少的用户过来发贴。那么如何扩展整个站点架构的读请求呢?常用的是主从同步,读写分离。我们原来只有一个数据库,现在使用多个不同的数据库提供服务,这样的话,就扩展了读写,很快就解决了中等规模下数据访问的问题。

在这个阶段,系统的主要矛盾就是「站点耦合+读写延时」,58 同城是如何进行解耦,如何缓解延时呢?

对 58 同城而言,典型业务场景是主页,发布信息有发布页,信息聚合、标题聚合有列表页,点开一个标题有详细页,而这些站点都是耦合在一个程序中的,或者说耦合在一个站点中的,当我们有一个站点出现问题的时候,整个站点就会因为耦合一起出问题。

好的架构是进化来的,不是设计来的

第二个问题,大家都知道做数据库读请求和写请求,分布在不同的数据库上,这个时候如果再读取可能读到的是旧数据,因为读写有一个延时。如果有用户发帖子,马上去找的话肯定找不到,很可能带来的后果就是陆续在发布两条信息,这就是一个很大的问题。尤其是在请求量越来越大的时候,这个问题就更加突出。

在解决这些问题是,最先想到的是针对原来站点的核心业务做切分,然后工程师根据自己的站点和业务场景进行细分。首先,业务拆分是 58 同城最先尝试的优化。我们将业务垂直拆分成了首页和发布页。另外,在数据库层面,我们也随之进行了拆分,将大数据量拆分成一个个小的数据量。这样,读写延时就马上得到了缓解。尤其是在代码拆分成了不同的层面之后,站点耦合也得到了缓解,数据量加载速度也提升了很多。

好的架构是进化来的,不是设计来的

当时,还使用了一些技术,前面也提到了对动态资源和静态资源进行拆分。其中,我们对静态资源使用了 CDN 服务,便于数据缓存和就近访问,访问速度得到很明显的提升。除此之外,我们还使用了 MVC 模式,擅长前端的去做展示层,擅长协作逻辑的工程师就做 Contorller,擅长数据的人就负责数据,效率就会逐步的提高,最后就是负载均衡技术。

大流量:将整个 Windows 技术体系转向了 Java 体系

流量越来越大,当流量超过一千多万时,58 同城面对最大的问题就是性能和成本。此前,我提到58同城最初的技术选型是 Windows,应该是在 2006 年的时候,整个网站的性能变得非常之低。即使进行了业务拆分和一些优化,但是依然解决不了这个问题,所以我们当时做了一个非常艰难的决定,就是转型:将整个 Windows 技术体系转向了 Java 体系,这涵盖了操作系统、数据库等多个维度。

好的架构是进化来的,不是设计来的

其实,现在很多大的互联网公司在流量从小到大的过程中都经历过转型,包括京东、淘宝等等。对技术的要求越来越高,任何一个站点都不能挂,对站点的可用性要求也是越来越高。

就在这个时候,58 同城业务量也出现一个爆发期。于是我们招聘了很多的工程师,大家一起写越来越多的站点,但是发现效率很低,经常做一些重复性的工作比如参数解析等等。同时,业务之间相互依赖,无论是分类的子系统还是信息的子系统,二手车业务、房产业务都要访问用户和信息等一些底层数据,代码之间频繁的沟通,效率也不可能很高。

问题随之而来,站点数越来越多,数据量越来越大,机器数从最开始的几台上升到几百台的级别。那么如何提供整个架构的可用性呢?首先,在上层我们进行了一些改进和优化,再做进一步的垂直拆分,同时我们引入了 Cache,如下图所示:

好的架构是进化来的,不是设计来的

在架构的改进上,我们构建了一个相对独立的服务层,这个服务层做的每个业务线都会写对应的代码。如果用户发出请求,就由这个服务层统一来管理,所有的上游业务线就像调用本地函数一样,通过 IDC 的框架来调用这个服务。整个用户登录先访问 Cache,如果 Cache 变动了就直接返回,如果 Cache 不变动,就会访问数据库,这样把数据库的数据拿到本地再放回 Cache,再打回上一轮。如此一来,业务逻辑全部封装在这个服务的上游管理,该业务逻辑只有服务层能够编写代码,然后由这个服务层集中管理、集中优化,这样就提高了效率。

好的架构是进化来的,不是设计来的

除此之外,为了保证站点的高可用,我们主要使用了反向代理技术。因为用户而言,他主要为了使用 58 同城的服务,他不关注访问是58同城或者有十台首页的服务器。58 同城通过反向代理技术,通过 DNS 群,通过 LVS 技术,来保证接入层的高可用性,同时还保证了服务层、站点层、数据层的高可用。另外,为了保证高可用我们经常使用冗余的方法,无论是站点服务和数据服务都可以使用这种方式进行解决,一个站点不可用,我们就换一个站点,一个数据库不够用,我们就多加几个。当然,数据冗余也会带来一些副作用,如果数据量更新的话,那就需要将所有的“冗余”都要进行更新。

58同城也做了一个图片存储系统,开始都是存储在操作系统之上,随着新增站点、新增服务,压力就变得越来越大。于是,58 同城就自建了站点框架和服务框架,现在这两个框架也已经开源(如何降低站点开发成本?https://github.com/58code/Argo  如何降低服务开发成本? https://github.com/58code/Gaea )只需要修改一些基本的配置就可以使用了。

当架构变成「蜘蛛网」,人肉已很难搞定!

随着用户量、数据量并发量进一步的增长,58同城也拓展了很多的新业务,那么对产品迭代速度要求就非常高,整体的架构对自动化的要求越来越高。

好的架构是进化来的,不是设计来的

为了支撑业务的发展,技术团队对架构做了进一步的解耦,另外就是引入了配置中心,如果要访问任何一个服务,不会直接在本地的配置中留下一个服务,配置中心告诉这个服务的特点,如果扩展的话,配置中心自动下达消息,如果有机器要下线的话,配置中心会反向通过发邮件的方式进行通知。

而柔性服务是指当流量增加的时候,自动的新增服务。可以看到进一步解耦之后,有垂直业务、无线业务、集成业务等等,这些子系统之间都是通过配置中心相应之间发生关系的。

另一点就是关于数据库,当某一点成为一个业务线重点的时候,我们就会集中解决这个点的问题。最初期的时候每个业务线都要访问数据库,访问缓存,访问用户数据,于是我们把代码集中的放到了服务层。现在数据量越来越大,大家都要做数据切分,每个业务线都做切分,这个时候58同城的每个页面都面对这样的痛点,于是把这个痛点拿到集中的层面来解决。

最后一点就是效率矛盾,此时很多问题,靠「人肉」已经很难进行搞定了。这就需要自动化,包括回归、测试、运维、监控等等都要回归到自动化。

这里需要补充一点,就是在产品层面,我们引入了智能化,比如说智能推荐,主动推荐一些相关的话题;智能广告,通过一些智能的策略,让用户对广告的点击更多,增加对 58 同城的收录;智能搜索,在搜索的过程中加入一些搜索的策略,可以提高搜索的权重,也可以增加 58 同城的 PV。当然,所有的自动化的产品背后都是由技术在驱动。

未来的挑战

现在,58同城的流量已经突破的 10 亿的量级,那么架构上未来面临哪些挑战呢?一方面是无线化、移动化。另一方面就是需求的变化,我们必须加快迭代一些东西。如果拥有10亿的流量,却跑在一亿的架构上肯定是不行的。未来,我们会使用更多的并行计算、实时计算,如果能做到实时推荐,效果肯定非常好,这也是我们的挑战。最后一点,58同城现在的服务器大概在3000台左右,未来将拓展到 10000 万,这就是运维的挑战了。

好的架构是进化来的,不是设计来的

总结:

最后做一个小的总结,网站在不同的阶段遇到的问题不一样,而解决这些问题使用的技术也不一样,流量小的时候,我们主要目的是提高开发效率,在早期要引入 ORM,DAO 这些技术。随着流量变大,使用动静分离、读写分离、主从同步、垂直拆分、CDN、MVC 等方式不断提升网站的稳定性。面对更大的流量时,通过垂直拆分、服务化、反向代理、开发框架(站点/服务)等等,不断提升高可用。在面对上亿级的更大流量时,通过中心化、柔性服务、消息总线、自动化(回归,测试,运维,监控)来迎接新的挑战。未来的就是继续实现 移动化,大数据实时计算,平台化…

原文:http://news.oneapm.com/shenjian-oneapm-course/

written by ocean

11月 23

移动互联网、云计算和大数据的成熟和发展,让更多的好想法得以在很短的时间内实现为产品。此时,如果用户需求抓得准,用户数量将很可能获得爆发式增长,而不需要像以往一样需要精心运营几年的时间。然而用户数量的快速增长(尤其是短时间内的爆发式增长),通常会让应用开发者有些吃不消,不得不面临一些严峻的技术挑战:如何避免因为单台机器当机导致服务不可用;如何避免在服务容量不足时,用户体验下降,等等。在系统构建之初就采用高可用和可伸缩架构,将能有效避免这些问题。

如何构建高可用和可伸缩架构呢?七牛云存储首席架构师李道兵在3月22的「开发者最佳实践日」第十期沙龙活动上给出了自己的想法。他结合自己多年的实践经验,针对一些不太复杂的业务场景,从入口层、业务层、缓存层和数据库层四个层面细致讲述了如何构建高可用和可伸缩系统。希望大家读完这篇文章,能觉得高可用和可伸缩不是一个高不可攀的东西,投入不高的成本就能在项目早期把高可用和可伸缩纳入架构设计之中。

如何实现高可用

入口层

入口层,通常指Nginx和Apache等层面的东西,负责应用(不管是Web应用还是移动应用)的服务入口。我们通常会将服务定位在一个IP,如果这个IP对应的服务器当机了,那么用户的访问肯定会中断。此时,可以用keepalived来实现入口层的高可用。例如,机器A 的IP是 1.2.3.4,机器 B 的 IP 是 1.2.3.5, 那么再申请一个 IP 1.2.3.6(称为?跳IP), 平时绑定在机器A上,如果A当机,IP会自动绑定在机器B上;如果B当机,IP会自动绑定在机器A上。对于这种形式,我们将DNS绑定到心跳IP上,即可实现入口层的高可用。

但这个方案有一点小问题。第一,它的切换可能会有一到两秒的中断,也就是说,如果不是要求到非常严格的毫秒级就不会有问题。第二,对入口的机器会有些浪费,因为买了两台机器的入口,可能就只有一台机器用上。对一些长连接的应用可能会导致服务中断,这时候就需要客户端做配合做一些重新创建连接的工作。简单来说,对于比较普通的业务来说,这个方案就能解决一部分问题。

这里要注意,keepalived在使用上会有一些限制。

  • 两台机器必须在同一个网段,不是在同一个网段,没有办法实现互相抢IP。

  • 内网服务也可以做心跳,但需要注意的是,以前为了安全我们会把内网服务绑定在内网IP上,避免出现安全问题。但为了使用keepalived,必须监听在所有IP上(如果监听在心跳IP上,那么机器没有持有该IP时,服务无法启动),简单的方案是启用 iptables, 避免内网服务被外网访问。

  • 服务器利用率下降,这时可以考虑做混合部署来改善这一点。

比较常见的一个错误是,如果有两台机器,两个公网IP,DNS上把域名同时定位到两个IP,就觉得已经做了高可用了。这完全不是高可用,因为如果一台机器当机,那么就有一半左右的用户无法访问。

除了keepalive,lvs也能用来解决入口层的高可用问题。不过,与keepalived相比,lvs会更复杂一些,门槛也会高一些。

业务层

业务层通常是由PHP、Java、Python、Go等写的逻辑代码构成的,需要依赖于后台数据库及一些缓存层面的东西。如何实现业务层的高可用呢?最核心的就是,业务层不要有状态,将状态分散到缓存层和数据库。目前大家通常喜欢将以下几种数据放入业务层。

第一个是session,即用户登录相关的数据,但好的做法是将session放在数据库里,或者一个比较稳定的缓存系统中。

第二个是缓存,在访问数据库时,如果一个查询很慢,就希望将这些结果暂时放到进程里,下次再做查询时就不用再访问数据库了。这种做法带来的问题是,当业务层服务器不只一台时,数据很难做到一致,从缓存拿到的数据就可能是错误的。。

一个简单的原则就是业务层不要有状态。在业务层没有状态时,一台业务层服务器当掉了之后,Nginx/Apache会自动将所有的请求打到另外一台业务层的服务器上。由于没有状态,两台服务器没有任何差异,所以用户完全感受不到。如果把session放在业务层里面的话,那么面临的问题是,这个用户以前是登录在一台机器上的,这个进程死掉后,用户就会被登出了。

友情提醒:有一段时间比较流行cookie session,就是将session中的数据加密之后放在客户的cookie里,然后下发到客户端,这样也能做到与服务端完全无状态。但这里面有很多坑,如果能绕过这些坑就可以这样使用。第一个坑是怎么保证加密的密钥不泄露,一旦泄露就意味着攻击者可以伪造任何人的身份。第二个坑是重放攻击,如何避免别人通过保存 cookie 去不停地尝试的验证码,当然也还有其他一些攻击手段。如果没有好办法解决这两方面的问题,那么cookie session尽量慎用。最好是将session放在一个性能比较好的数据库中。如果数据库性能不行,那么将session放在缓存中也比放在cookie里要好一点。

缓存层

非常简单的架构里是没有缓存这个概念的。但在访问量上来之后,MySQL之类的数据库扛不住了,比如在SATA盘里跑MySQL,QPS到达200、300甚至500时,MySQL的性能会大幅下降,这时就可以考虑用缓存层来挡住绝大部分服务请求,提升系统整体的容量。

缓存层做高可用一个简单的方法就是,将缓存层分得细一点儿。比如说,缓存层就一台机器的话,那么这台机器当了以后,所有应用层的压力就会往数据库里压,数据库扛不住的话,整个网站(或应用)就会随之当掉。而如果缓存层分在四台机器上的话,每台只有四分之一,这台机器当掉了以后,也只有总访问量的四分之一会压在数据库上面,数据库能扛住的话,网站就能很稳定地等到缓存层重新起来。在实践中,四分之一显然是不够的,我们会将它分得更细,以保证单台缓存当机后数据库还能撑得住即可。在中小规模下,缓存层和业务层可以混合部署,这样可以节省机器。

数据库层

在数据库层面实现高可用,通常是在软件层面来做。例如,MySQL有主从模式(Master-Slave),还有主主模式(Master-Master)都能满足需求。MongoDB也有ReplicaSet的概念,基本都能满足大家的需求。

总之,要想实现高可用,需要做到这几点:入口层做心跳,业务层服务器无状态,缓存层减小粒度,数据库做一个主从模式。对于这种模式来讲,我们做的高可用不需要太多服务器,这些东西都可以同时部署在两台服务器上。这时,两台服务器就能满足早期的高可用需求了。任何一台服务器当机用户完全无感知。

如何实现可伸缩

入口层

在入口层实现伸缩性,可以通过直接水平扩机器,然后DNS加IP来实现。但需要注意,尽管一个域名解析到几十个IP没有问题,但是很多浏览器客户端只会使用前几个IP,部分域名供应商对此有优化(如每次返回的IP顺序随机),但这个优化效果不稳定。

推荐的做法是使用少量的Nginx机器作为入口,业务服务器隐藏在内网(HTTP类型的业务这种方式居多)。另外,也可以把所有IP下发到客户端,然后在客户端做一些调度(特别是非HTTP型的业务,如游戏、直播)。

业务层

业务层的伸缩性如何实现?与做高可用时的解决方案一样,要实现业务层的伸缩性,保证无状态是很好的手段。此外,加机器继续水平部署即可。

缓存层

比较麻烦的是缓存层的伸缩性,最简单粗暴的方式是什么呢?趁着半夜量比较低的时候,把整个缓存层全部下线,然后上线新的缓存层。新的缓存层启动起来之后,再等这些缓存慢慢预热。当然这里一个要求,你的数据库能抗住低估期的请求量。如果扛不住呢?取决于缓存类型,下面我们先可以将缓存的类型区分一下。

  • 强一致性缓存:无法接受从缓存拿到错误的数据 (比如用户余额,或者会被下游继续缓存这种情形)

  • 弱一致性缓存:能接受在一段时间内从缓存拿到错误的数据 (比如微博的转发数)。

  • 不变型缓存:缓存key对应的value不会变更 (比如从SHA1推出来的密码, 或者其他复杂公式的计算结果)。

那什么缓存类型伸缩性比较好呢?弱一致性和不变型缓存的扩容很方便,用一致性Hash即可;强一致性情况稍微复杂一些,稍后再讲。使用一致性Hash,而不用简单Hash的原因是缓存的失效率。如果缓存从9台扩容到10台,简单Hash 情况下90%的缓存会马上失效,而如果使用一致性Hash情况,只有10%的缓存会失效。

那么,强一致性缓存会有什么问题?第一个问题是,缓存客户端的配置更新时间会有微小的差异,在这个时间窗内有可能会拿到过期的数据。第二个问题是,如果扩容之后再裁撤节点,会拿到脏数据。比如 a 这个key之前在机器1,扩容后在机器2,数据更新了,但裁撤节点后key回到机器1,这时候就会拿到脏数据。

要解决问题2比较简单,要么保持永不减少节点,要么节点调整间隔大于数据的有效时间。问题1可以用如下的步骤来解决:

  1. 两套hash配置都更新到客户端,但仍然使用旧配置;

  2. 逐个客户端改为只有两套hash结果一致的情况下会使用缓存,其余情况从数据库读,但写入缓存;

  3. 逐个客户端通知使用新配置。

Memcache 设计得比较早,导致在伸缩性高可用方面的考虑得不太周到。Redis 在这方面有不少改进,特别是 @ngaut 团队基于 redis 开发了 codis 这个软件,一次性地解决了缓存层的绝大部分问题。推荐大家考察一下。

数据库

在数据库层面实现伸缩,方法很多,文档也很多,此处不做过多赘述。大致方法为:水平拆分、垂直拆分和定期滚动。

总之,我们可以在入口层、业务层面、缓存层和数据库层四个层面,使用刚才介绍的方法和技术实现系统高可用和可伸缩性。具体为:在入口层用心跳来做到高可用,用平行部署来伸缩;在业务层做到服务无状态;在缓存层,可以减小一些粒度,以方便实现高可用,使用一致性Hash将有助于实现缓存层的伸缩性;数据库层的主从模式能解决高可用问题,拆分和滚动能解决可伸缩问题。

本文中分享的这些技巧和方法,主要想帮助不太复杂的业务场景或者中小型应用快速搭建起高可用可伸缩的系统。关于如何构建高可用和可伸缩系统还有很多更为细节的点和实践经验值得探讨,望以后能与大家做更充分的交流。

from 

http://www.infoq.com/cn/articles/high-availability-scalable-architecture-practical-experience

written by ocean

11月 21

前言

    一个成熟的大型网站(如淘宝、京东等)的系统架构并不是开始设计就具备完整的高性能、高可用、安全等特性,它总是随着用户量的增加,业务功能的扩展逐渐演变完善的,在这个过程中,开发模式、技术架构、设计思想也发生了很大的变化,就连技术人员也从几个人发展到一个部门甚至一条产品线。所以成熟的系统架构是随业务扩展而完善出来的,并不是一蹴而就;不同业务特征的系统,会有各自的侧重点,例如淘宝,要解决海量的商品信息的搜索、下单、支付,例如腾讯,要解决数亿的用户实时消息传输,百度它要处理海量的搜索请求,他们都有各自的业务特性,系统架构也有所不同。尽管如此我们也可以从这些不同的网站背景下,找出其中共用的技术,这些技术和手段可以广泛运行在大型网站系统的架构中,下面就通过介绍大型网站系统的演化过程,来认识这些技术和手段。

一、最开始的网站架构

    最初的架构,应用程序、数据库、文件都部署在一台服务器上,如图:

image

二、应用、数据、文件分离

    随着业务的扩展,一台服务器已经不能满足性能需求,故将应用程序、数据库、文件各自部署在独立的服务器上,并且根据服务器的用途配置不同的硬件,达到最佳的性能效果。

image

三、利用缓存改善网站性能

    在硬件优化性能的同时,同时也通过软件进行性能优化,在大部分的网站系统中,都会利用缓存技术改善系统的性能,使用缓存主要源于热点数据的存在,大部分网站访问都遵循28原则(即80%的访问请求,最终落在20%的数据上),所以我们可以对热点数据进行缓存,减少这些数据的访问路径,提高用户体验。

251844453265971

    缓存实现常见的方式是本地缓存、分布式缓存。当然还有CDN、反向代理等,这个后面再讲。本地缓存,顾名思义是将数据缓存在应用服务器本地,可以存在内存中,也可以存在文件,OSCache就是常用的本地缓存组件。本地缓存的特点是速度快,但因为本地空间有限所以缓存数据量也有限。分布式缓存的特点是,可以缓存海量的数据,并且扩展非常容易,在门户类网站中常常被使用,速度按理没有本地缓存快,常用的分布式缓存是Memcached、Redis。

四、使用集群改善应用服务器性能

    应用服务器作为网站的入口,会承担大量的请求,我们往往通过应用服务器集群来分担请求数。应用服务器前面部署负载均衡服务器调度用户请求,根据分发策略将请求分发到多个应用服务器节点。

251844471702801

    常用的负载均衡技术硬件的有F5,价格比较贵,软件的有LVS、Nginx、HAProxy。LVS是四层负载均衡,根据目标地址和端口选择内部服务器,Nginx是七层负载均衡和HAProxy支持四层、七层负载均衡,可以根据报文内容选择内部服务器,因此LVS分发路径优于Nginx和HAProxy,性能要高些,而Nginx和HAProxy则更具配置性,如可以用来做动静分离(根据请求报文特征,选择静态资源服务器还是应用服务器)。

五、数据库读写分离和分库分表

    随着用户量的增加,数据库成为最大的瓶颈,改善数据库性能常用的手段是进行读写分离以及分表,读写分离顾名思义就是将数据库分为读库和写库,通过主备功能实现数据同步。分库分表则分为水平切分和垂直切分,水平切换则是对一个数据库特大的表进行拆分,例如用户表。垂直切分则是根据业务不同来切换,如用户业务、商品业务相关的表放在不同的数据库中。

260851219209749

六、使用CDN和反向代理提高网站性能

  假如我们的服务器都部署在成都的机房,对于四川的用户来说访问是较快的,而对于北京的用户访问是较慢的,这是由于四川和北京分别属于电信和联通的不同发达地区,北京用户访问需要通过互联路由器经过较长的路径才能访问到成都的服务器,返回路径也一样,所以数据传输时间比较长。对于这种情况,常常使用CDN解决,CDN将数据内容缓存到运营商的机房,用户访问时先从最近的运营商获取数据,这样大大减少了网络访问的路径。比较专业的CDN运营商有蓝汛、网宿。

  而反向代理,则是部署在网站的机房,当用户请求达到时首先访问反向代理服务器,反向代理服务器将缓存的数据返回给用户,如果没有没有缓存数据才会继续走应用服务器获取,也减少了获取数据的成本。反向代理有Squid,Nginx。

260851254513595

七、使用分布式文件系统

    用户一天天增加,业务量越来越大,产生的文件越来越多,单台的文件服务器已经不能满足需求。需要分布式的文件系统支撑。常用的分布式文件系统有NFS。

260851282647353

八、使用NoSql和搜索引擎

    对于海量数据的查询,我们使用nosql数据库加上搜索引擎可以达到更好的性能。并不是所有的数据都要放在关系型数据中。常用的NOSQL有mongodb和redis,搜索引擎有lucene。

260851321075527

九、将应用服务器进行业务拆分

    随着业务进一步扩展,应用程序变得非常臃肿,这时我们需要将应用程序进行业务拆分,如百度分为新闻、网页、图片等业务。每个业务应用负责相对独立的业务运作。业务之间通过消息进行通信或者同享数据库来实现。

260851352481788

 

十、搭建分布式服务

    这时我们发现各个业务应用都会使用到一些基本的业务服务,例如用户服务、订单服务、支付服务、安全服务,这些服务是支撑各业务应用的基本要素。我们将这些服务抽取出来利用分部式服务框架搭建分布式服务。淘宝的Dubbo是一个不错的选择。

260851397174320

小结

    大型网站的架构是根据业务需求不断完善的,根据不同的业务特征会做特定的设计和考虑,本文只是讲述一个常规大型网站会涉及的一些技术和手段。

 

 

参考资料:

《大型网站技术架构》 ——李智慧

《海量运维运营规划》 ——唐文

http://www.cnblogs.com/leefreeman/p/3993449.html

written by ocean

11月 19

From

http://www.cnblogs.com/huangxincheng/category/555253.html

written by ocean

11月 16

一、VS2010编译器中常见的环境变量有:
$(OutDir)、$(TargetName) 、 $(TargetExt)、$(ProjectName)、$(TargetFileName)

 
二、环境变量含义:
解决方案目录:$(SolutionDir)即为*.sln文件所在文件夹,尾带   ‘/’
工程目录:$(ProjectDir) 即 为*.vcproj文件所在文件夹,尾带   ‘/’   
输出目录(OutDir):  $(ProjectDir)$(PlatformName)/$(ConfigurationName) 
中间目录(IntDir): $(OutDir)/Intermediate 
输出文件:$(OutDir)/$(ProjectName).exe 
平台名称:$(PlatformName) 一般是Win32,除非你的工程选项选的是"Itanium"或者"Pocket PC 2003 (ARMV4)"
解决方案配置名称:$(ConfigurationName) 一般是Debug或者Release,$(PlatformName)\$(ConfigurationName)的一个示范是等于“Win32\Debug”
 
三、其它
编译事件支持的命令:
copy/del/xcopy…
如:copy "$(OutDir)$(TargetName)$(TargetExt)" "e:\"
默认输出文件:$(OutDir)$(TargetName)$(TargetExt),默认等于$(TargetPath)。

written by ocean \\ tags: