网站在刚开始的时候大概只是一个想法:一个产业的模型,快速地将它产生出来。“快”是第一位的,不须要花太多精力在架构设计上。在网站进入扩张期才须要对架构投入更多的精力来承载网站在爆发时的流量。程序员
饿了么成立已经8年,如今日订单量突破900万,咱们也有了较为完善的网站架构。数据库
1、网站基础架构安全
初期,咱们使用了可以更容易拓展SOA的框架。咱们用SOA的框架解决两件事情:微信
1. 分工协做架构
网站初期,程序员可能就1~5个,那时你们忙同一个事情就能够了。彼此之间的工做都互相了解,每每是经过“吼”的方式就把问题解决了。
负载均衡
但随着人员的增长,这种方式显然是不行的,不可能一我的更新了代码再把其余人的全部代码从新上线一遍吧?因而就要考虑分工协做的问题。框架
2. 快速扩展编辑器
看一下咱们的现状,中间是咱们整个架构的体系,右侧是和服务化相关的一些基础,包括基础的组件或者服务。分布式
先说语言,咱们原来的网站是在PHP上的,后来慢慢转型。性能
WebAPI主要作一些HTTPS卸载、限流,还有安全校验等一些通用的和业务逻辑无关的操做。
Service Orchestrator是服务编排层,经过配置的方式实现内外网的协议转换、服务的聚合裁剪。
架构图右边是一些围绕这些服务化框架的辅助系统,好比说用于按期执行一个任务的Job系统。咱们有将近快1000个服务,这些系统怎么监控?因此必须有一套监控系统。刚开始只有30多我的时,咱们更擅长的是跑到机器上去搜一下Log,但到了900多人时,你不可能都到机器上去搜一遍Log,须要有个集中式的日志系统。其它的系统这里就不一一赘述了。
罗马不是一天建成的,基础架构是个演进的过程。咱们精力有限,那先作什么呢?
2、服务拆分
当网站变大了,原来的架构跟不上发展的节奏了。咱们要作的第一件事情就是:
把大Repo拆成一个小Repo,把大服务拆成小服务,把咱们的集中基础服务,拆分到不一样的物理机器上去。
光是服务拆分用了一年多的时间才作完,这是一个比较漫长的过程。
这个过程当中,首先要对API作一个很好的定义。由于一旦你的API上线以后,再作一些修改的成本是至关大的。会有不少人依赖于你的API,不少时候你也并不知道有谁依赖于你的API,这是一个很大的问题。
而后再把一些基础服务抽象出来。不少原来的服务实际上是耦合在原来的业务代码里面的。好比说支付业务,业务很单一时,紧耦合的代码没有关系,可是扩展出的愈来愈多的业务都须要支付服务时,你每个业务(好比说支付的功能)都要去作一个吗?因此咱们要把这些基础服务抽离出来,好比支付服务、短信服务、推送服务等。
拆服务看似很简单、没什么价值,但这偏偏是咱们刚开始就要作的事情。其实在这个时期,前面全部的那些架构均可以日后拖,由于不作架构调整其实不会死人,可是拆服务你不作的话,真的会死人。
服务拆分一定是一个漫长的过程,可这实际是一个很痛苦的过程,也须要不少配套系统的系统工程。
3、发布系统
发布是最大的不稳定因素。不少公司对发布的时间窗口有严格的限定,好比说:
每周只有两天能够发布;
周末是绝对不能够发布的;
业务的高峰期绝对不容许发布;
等等……
咱们发现,发布的最大问题在于发布上去以后没有简单可执行的回退操做。回退操做究竟是谁来执行,是发布人员就能够执行,仍是须要专人来执行?若是是发布人员的话,发布人员并不是24小时在线工做,出了问题找不到人怎么办?若是是有专人来执行回退,而又没有简单、统一的回退操做,那这我的须要熟悉发布人员的代码,这基本上不可行。
因此咱们就须要有发布系统,发布系统定义了统一的回退操做,全部服务必须遵循发布系统的定义回退操做。
在饿了么对接发布系统是对全部人的强制要求,全部的系统必须所有接入发布系统。发布系统的框架很重要,这个东西其实对于公司是很重要的一件事情,须要放到第一优先级的队列里面去考虑。
4、服务框架
紧接着就是饿了么的服务框架,把一个大的Repo拆分红一个小的Repo,把一个大的服务拆成一个小的服务,让咱们的服务尽可能独立出去,这须要一套分布式服务框架来支撑。
分布式服务框架包含的服务注册、发现、负载均衡、路由、流控、熔断、降级等功能,这里就不一一展开了。前面已经说起,饿了么是多语言的生态,有 Python的,也有Java的,咱们的服务化框架对应也是多语言的。这对咱们后来一些中间件的选型是有影响的,好比说DAL层。
5、DAL数据访问层
当业务量愈来愈大的时候,数据库会变成一个瓶颈。
前期能够经过提高硬件的方式来提高数据库的性能。好比:
升级到一个有更多CPU的机器;
把硬盘改为 SSD 的或者更高级一点的。
但硬件提高终归是有一个容量限制的。并且不少作业务的小伙伴,写代码的时候都直接操做数据库,发生过不少次服务一上线数据库就被打爆的情形。数据库被打爆掉了以后,除非等待数据库恢复,没有任何其它机会能够恢复业务。
若是数据库里面数据是正常的,业务其实均可以补偿出来。因此咱们作DAL服务层的时候,第一件事情是限流,其它的东西能够放一放。而后作链接复用,咱们Python框架用的多进程单线程加协程的模型。
多进程之间实际上是不能够共享一个链接的。好比:一台机器上部署了10个 Python进程,每一个进程10个数据库链接。再扩展到10台机器上,就有1000个数据库链接。对数据库来讲,链接是一个很昂贵的东西,咱们DAL层要作一个链接复用。
这个链接复用讲的不是服务自己的链接复用,而是说DAL层上的链接复用,就是服务有1000个链接到DAL层,通过链接复用后对数据库可能只是保持着十几个链接。一旦发现某个数据库请求是一个事务的话,那么DAL就帮你保留这个链接的对应关系。当这个事务结束以后,就把数据库的链接,放回到共用池里面去,供其余人使用。
而后作冒烟和熔断。数据库也能够熔断的。当数据库发生冒烟时,咱们会杀掉一些数据库的请求,保证数据库不至于崩溃。
6、服务治理
服务框架以后,涉及服务治理的问题。服务治理实际上是一个很大的概念。首先是埋点,你要埋不少的监控点。
好比有一个请求,请求成功了或者失败了,请求的响应时间是多少,把全部的监控指标放到监控系统上面去。咱们有一个很大的监控屏幕,上面有不少的监控指标。有专门小组72小时去盯着这个屏幕,若是有任何曲线波动了,就找人去解决。另外是报警系统,一个监控屏幕展现的东西老是有限的,只能放那些很重要的关键指标。这个时候就须要有报警系统。
罗马不是一天建成的,基础架构更是一个演进的过程。咱们的资源和时间老是有限的,做为架构师和 CTO 来讲,如何在这种有限的资源下,产出更重要的东西?
咱们作了不少系统,以为本身作得很不错了,但实则不是,我感受咱们又回到了石器时代,由于问题愈来愈多,需求也愈来愈多,总感受你的系统里还缺点什么东西,想作的功能也一大堆。
这些问题涉及咱们作事的一个原则:东西够用就好,可是要可以未雨绸缪,作必定的超前规划。



本文分享自微信公众号 - JAVA高级架构(gaojijiagou)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。