[No000047]好的架构源于不停地衍变,而非设计
对很多创业公司而言,随着业务增长,网站的流量也会经历不同的阶段。从十万流量到一百万流量,再从一百万流量跨越到一千万甚至上亿的流量,网站的架构需要经历哪些变化?在"OneAPM 技术公开课"第一期中,58同城的技术委员会执行主席沈剑对此进行了详细剖析。
以下为演讲整理
本次演讲主要会阐述,58同城从小流量、中等规模流量、大流量,到更大的流量过程中,架构是如何演进的?遇到了哪些问题?以及如何解决这些问题?
好的架构不是设计出来的,而是演进出来的
对很多创业公司而言,很难在初期就预估到流量十倍、百倍以及千倍以后网站架构会是什么样的一个状况。同时,如果系统初期就设计一个千万级并发的流量架构,很难有公司可以支撑这个成本。
因此,这里主要会关注架构的眼花。在每个阶段,找到对应该阶段网站架构所面临的问题,然后在不断解决这些问题,在这个过程中整个架构会一直演进。
在58同城建立之初,站点的流量非常小,可能也就是十万级别,这也就意味着,平均每秒钟也就是几次的访问,此时网站架构的特点是:请求量比较低,数据量比较小,代码量也比较小。这个时候的站点可以被几个工程师轻易搞定,因此根本没什么"架构"可言。
其实这也是很多创业公司初期面临的问题,最开始58同城的站点架构用一个词概括就是"ALL IN ONE",如下图所示:
就像一个单机系统,所有的东西都部署在一台机器上,包括站点、数据库、文件等等。而工程师每天的核心工作就是CURD,前端传过来一些数据,然后业务逻辑层拼装成一些CURD访问数据库,数据库返回数据,数据拼装成页面,最终返回到浏览器。相信很多创业团队初期都面临一个与之类似的情况,每天写代码,写SQL、接口参数、访问数据等等。
这里需要说明一个问题,大家都知道最初58同城使用的是Windows、iis、SQL-Sever、C#这条路。现在很多创业公司可能就不会这么做。
如果可以重来?那么会选择LAMP
很多创业的同学可能会想,初期什么样的一个架构合适? 如果重来,站在现在这个角度上58会选择LAMP,为什么?首先是无须编译,而且快速发布功能强大,从前端到后端、数据库访问、业务逻辑处理等等全部可以搞定,最重要都是成熟的开源产品,完全免费的。如果使用LAMP搭建一个论坛,两天的时间就足够了。所以,如果在创业初期,就尽量不要再使用Windows。
在这个阶段58同城面临的主要问题是什么?其实就是招人,最初工程师写CURD都容易出错。当时引进了DAO和ORM,从而避免直接面对CURD语句,而是面对工程师比较擅长的是面向对象,能够极大的提高工作效率,降低出错率。
中等规模:流量跨过十万的阶段,数据库成为瓶颈
随着58同城的高速增长,系统很快跨越了十万流量阶段。主要需求是什么?网站能够正常访问,当然速度更快点就好了。而此时系统面临的问题有:在流量峰值期容易宕机,因为大量的请求会压到数据库上,所以数据库成为新的瓶颈,从而,人越多访问越慢。而在这个时候,机器数量也从一台变成了多台,所以很自然的行程了分布式架构,如下图所示:
首先,使用了一些非常常见的技术,一方面是动静分离,动态的页面通过Web-Servre访问,静态的像图片等就单独放到了一些服务器上。另外一点就是读写分离。其实,对58同城或者说绝大部分的站点而言,一般来说都是读多写少。对58同城来说,绝大部分用户是访问信息,只有很少的用户过来发贴。那么如何扩展整个站点架构的读请求呢?常用的是主从同步,读写分离。同时原来只有一个数据库,现在使用多个不同的数据库提供服务,这样的话,就扩展了读写,很快就解决了中等规模下数据访问的问题。
在这个阶段,系统的主要矛盾就是"站点耦合+读写延时",58同城是如何进行解耦,如何缓解延时呢?
对58同城而言,典型业务场景是主页,发布信息有发布页,信息聚合、标题聚合有列表页,点开一个标题有详细页,而这些站点都是耦合在一个程序中的,或者说耦合在一个站点中的,当一个站点出现问题,整个站点就会因为耦合一起出问题。
第二个问题,大家都知道做数据库读请求和写请求,分布在不同的数据库上,这个时候如果再读取可能读到的是旧数据,因为读写有一个延时。如果有用户发帖子,马上去找的话肯定找不到,很可能带来的后果就是陆续在发布两条信息,这就是一个很大的问题。尤其是在请求量越来越大的时候,这个问题就更加突出。
在解决这些问题时,最先想到的是针对原来站点的核心业务做切分,然后工程师根据自己的站点和业务场景进行细分。首先,业务拆分是58同城最先尝试的优化——将业务垂直拆分成了首页和发布页。另外,在数据库层面,随之也进行了拆分,将大数据量拆分成一个个小的数据量。这样,读写延时就马上得到了缓解。尤其是在代码拆分成了不同的层面之后,站点耦合也得到了缓解,数据加载速度也提升了很多。
当时,还使用了一些技术,前面也提到了对动态资源和静态资源进行拆分。其中,我们对静态资源使用了CDN服务,便于数据缓存和就近访问,访问速度得到很明显的提升。除此之外,还使用了MVC模式,擅长前端的去做展示层,擅长协作逻辑的工程师就做Contorller,擅长数据的人就负责数据,效率就会逐步的提高,最后就是负载均衡技术。
大流量:将整个Windows技术体系转向了Java体系
流量越来越大,当流量超过一千多万时,58同城面临的最大问题就是性能和成本。此前曾提到58同城最初的技术选型是Windows,整个网站的性能变得非常之低。即使进行了业务拆分和一些优化,依然解决不了这个问题,所以当时做了一个非常艰难的决定,就是转型:将整个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等方式不断地提升网站稳定性。面对更大的流量时,通过垂直拆分、服务化、反向代理、开发框架(站点/服务)等等,不断提升高可用。在面对上亿级的更大流量时,通过中心化、柔性服务、消息总线、自动化(回归,测试,运维,监控)来迎接新的挑战。未来的就是继续实现
移动化,大数据实时计算,平台化……系统架构会一直迭代衍变,就像最初的从零到现在。(整理/OneAPM技术编辑 责编/仲浩)
[No000047]好的架构源于不停地衍变,而非设计的更多相关文章
- 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路
最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...
- 滴滴 CTO 架构师 业务 技术 战役 时间 赛跑 超前 设计
滴滴打车CTO张博:生死战役,技术和时间赛跑-CSDN.NEThttps://www.csdn.net/article/2015-06-25/2825058-didi 滴滴出行首席架构师李令辉:业务的 ...
- 高并发架构系列:如何从0到1设计一个类Dubbo的RPC框架
在过去持续分享的几十期阿里Java面试题中,几乎每次都会问到Dubbo相关问题,比如:“如何从0到1设计一个Dubbo的RPC框架”,这个问题主要考察以下几个方面: 你对RPC框架的底层原理掌握程度. ...
- App后台开发运维和架构实践学习总结(2)——RESTful API设计技巧
前言 移动互联网时代,RESTful API成为越来越重要的移动端和服务器端交互的形式.尤其是在很多互联网公司或者传统行业拥抱移动互联网的时候,一套设计良好的Restful API能够帮助互联网产品支 ...
- 微服务架构案例(05):SpringCloud 基础组件应用设计
本文源码:GitHub·点这里 || GitEE·点这里 更新进度(共6节): 01:项目技术选型简介,架构图解说明 02:业务架构设计,系统分层管理 03:数据库选型,业务数据设计规划 04:中间件 ...
- MySQL高可用架构应该考虑什么? 你认为应该如何设计?
一.MySQL高可用架构应该考虑什么? 对业务的了解,需要考虑业务对数据库一致性要求的敏感程度,切换过程中是否有事务会丢失 对于基础设施的了解,需要了解基础设施的高可用的架构.例如 单网线,单电源等情 ...
- 怎样克服 JavaScript 框架疲劳?
[编者按]Tero Parviainen 著有 Build Your Own AngularJS,曾两次组织 Clojure CUP 竞赛,在 Twitter 上有近两千名关注者. 在本文中.Tero ...
- 升讯威微信营销系统开发实践:(1)功能概要与架构设计( 完整开源于 Github)
GitHub:https://github.com/iccb1013/Sheng.WeixinConstruction因为个人精力时间有限,不会再对现有代码进行更新维护,不过微信接口比较稳定,经测试至 ...
- [转]Algolia的分布式搜索网络架构
转自:http://www.csdn.net/article/2015-03-11/2824176-the-architecture-of-algolias-distributed-search-ne ...
随机推荐
- EWS API 2.0读取日历信息-读取内容注意事项
采用模拟账号的方式读取日历信息,注意下日历的内容读取(Body)读取.代码如下:(采用 EWS API 2.0版本) 1.读取内容前必须设置如下属性:否则会提示:You must load or as ...
- SharePoint 2013 日历视图兼容性问题
在IE11上访问SharePoint 2013 calendar视图,发现加入兼容性视图以后访问,正常,如下图: 不加入兼容性视图IE11访问,出现兼容性问题,如下图: 因为有些环境有问题,有些环境没 ...
- linux系统免密码登陆
有两台机器,系统都是CentOS6.5,IP分别为192.168.2.150,192.168.2.151.现在150需要SSH免密码登陆151. 在150上面执行命令,当前登录用户是root: # s ...
- DevExpress免费线上公开课17日开课
小伙伴们,前几日DevExpress 正式发布了2015的第二次重大版本v15.2.3(更新说明),对于新版本中新增的一些功能和控件,你一定会有一些疑问,比如哪些功能是值得我们关注的,哪些控件有比较重 ...
- AWS EC2 复制实例后,自定义指标无法显示数据
从一个实例创建了一个AMI,然后通过这个AMI创建新的EC2实例,结果发票自定义指标不会显示: 系统一直在邮件中提示: print() on closed filehandle MDATA at Cl ...
- 【转】C++标准库和标准模板库
C++强大的功能来源于其丰富的类库及库函数资源.C++标准库的内容总共在50个标准头文件中定义.在C++开发中,要尽可能地利用标准库完成.这样做的直接好处包括:(1)成本:已经作为标准提供,何苦再花费 ...
- 一个插件让你在chrome直接运行apk
插件的下载地址: https://chrome.google.com/webstore/detail/arc-welder/emfinbmielocnlhgmfkkmkngdoccbadn?utm_s ...
- git 设置 key 到服务器,同步代码不需要输入用户名和密码
1 ssh-keygen -t rsa 2 vim ~/.ssh/id_rsa.pub 3. 添加到git 服务器,这样同步代码就不需要输入密码
- Android中TextView添加删除线
项目中的需求~~~~ 商城中物品的一个本身价格,还有一个就是优惠价格...需要用到一个删除线. public class TestActivity extends Activity { private ...
- Android中应用程序清除data/data,清除cache,超详细
清除data,清除cache,其实在Android原生Setting里面有这个功能的. 需求是把这个功能做到自己的App里面,并计算出cache和data的size. 所以参考了一下Setting的源 ...