【架构师从入门到进阶】第一章:架构设计基础------第五节:架构演进(缓存到微服务)
上一篇文章我们讲到了架构演进中的数据库读写分离阶段,本篇文章我们继续讲架构演进的进阶阶段。
cdn和反向代理
随着我们用户量的不断扩大,访问量的继续增长,我们的用户会分布在全国各地,比如说北京、上海、广州。不同地区的用户访问网站的时候,速度差别也很大。有研究表明,网站访问延迟和用户的流失率成正比,也就是说,延迟越大,用户流失率越高。
我们自己用网站也是一样的,一个网站响应特别慢,我们就不想用它了。网站访问越慢,用户越会因为没有耐心而离开。为了提供更好的用户体验,留住用户,需要加速网站的访问速度。我们在这个阶段,加速网站速度的手段,可以用cdn和反向代理。
这里所说的反向代理,很多人可能会和前面所说的集群混淆。因为有nginx,它既是反向代理,又是负载均衡的一个组件,好多人可能以为反向代理就是负载均衡。其实并不是,比如说微服务中的ribbon是,它只做负载均衡,并没有反向代理。
在我们的系统进化中,怎么去用反向代理呢?其实就是在我们的整个系统的前端,加一些东西。比如说我们有cdn服务器,我们先把cdn加上,然后,再有反向代理。
其实这里面cdn和反向代理本质上都是缓存,为什么说缓存呢?
cdn是,content deliver network,也就是内容分发网络 ,比如说你是一个北京的用户,请求我们的系统,那么我们就从离北京最近的服务器给你提供服务;如果你是广州的用户访问系统,我们就从离广州最近的服务器向你提供服务。这个时候就是用户访问的时候,其实并不是去中心的应用服务器拿取数据,而是从离用户最近的一些节点缓存上的那些数据提前给到了用户,这是cdn的缓存。
那么反向代理服务器呢?也是一样的。在反向代理服务器中,它保存着可以被反向代理服务器代理的后面的服务的地址。当用户请求到达后,它根据负载均衡算法选择一个服务器去访问,或者在反向代理服务器上做一些缓存。就是说,当我要请求一个服务的时候,我先去请求反向代理服务器,有反向代理服务器给我指配一个具体的服务来响应我的要求。这时候第一个缓存是反向代理服务器,缓存了后面的每个服务器的地址。还有就是反向代理服务器它自己也可以做一个缓,缓存给用户提供服务。
那么,用cdn和反向代理的目的就是尽早的把数据返回给用户,一方面是加快用户的访问速度,另一方面也能减少后面服务器的访问压力。
分布式系统(分库分表,分布式缓存,分布式文件系统)
但是我们现在虽然做了数据库的主从同步,但是这两个库其实是一模一样的,也就是说,随着用户量的增大,这样长久的下去,一个库也会成为瓶颈,因为所有的数据都在一个库里,只不过是他把这个库向另外一个库做了备份。这个时候,就需要将这些数据进行拆分,这其实就是我们所说的分布式数据库,然后我们平时也叫它叫做分库分表。
同样的道理,文件存储也是一样的,关于存储的系统都是这么处理的,都需要分布式的存储,并且我们可以将数据库、缓存、还有文件的访问做一个统一处理。
缓存服务器现在变成了多台,比如说把用户的缓存放在一台机器上,把订单的缓存放在另外一台缓存服务器上。
然后文件服务器也是这个样子的,比如说用户的文件放在一台机器上,然后订单的文件放在另外一台机器上。
我们把对所有存储的数据的读取,通过一个数据的公共访问模块来做。
分布式数据库,就是我们所说的分库分表,就包括横向的拆分和纵向的拆分。文件存储呢,也可以按照业务或者文件类型分类进行存储。
其实这个本质相当于给数据库和文件、还有缓存做了负载均衡,原来由一个服务器扛的压力,现在把它拆分到了多台服务器上。
搜索引擎和NoSQL数据库
随着业务越来越复杂,我们前面讲的其实只是说解决了存储的问题。其实数据不仅仅需要存,还需要查询,还需要检索。一般能满足高效率检索的是用非关系型数据库,并且这类型的数据库大部分都是基于内存的数据库。
前面做的是优化了存储,这块做的是优化查询。
服务拆分
随着我们系统的发展,系统上线的时间很久了,然后业务场景也变得越来越复杂,团队也在不停的扩大。一个电商网站,有了很多业务线,比如用户、订单、商品、买家、卖家等,也都有不同的团队在负责。具体到技术上,原来把订单、用户、商品、买家、卖家都放在一个项目里,现在也不合适了,因为团队多,功能也太复杂了,一个项目中集成了特别多的代码,给开发、测试和部署都带来了不便。这个时候就需要将业务进行拆分,就像我们前面讲过的分库分表一样。
比如一个电商大应用,我们就会把它拆分成订单、用户、商品等多个小应用,直接通过rpc调用,或者通过消息队列进行通信。
微服务
如果服务很多,有成千上万个小服务的话,服务之间彼此的调用也会很复杂。比如说有一个服务要调用十个服务来完成功能,那么他需要知道这十个服务的IP地址和端口,如果十个服务的IP地址和端口在以后部署的时候有了变化,那么它的调用方也需要知道它这个IP地址的变更。我们刚才只说了十个服务,如果有100个服务,它得维护100个。
还有就是如果一个服务被100个服务调,它只要IP地址一变,调用它的那100个调用方都需要做相应的更新。这样的话,整个系统的整体复杂度就会越来越高,部署维护也会越来越困难,于是后面就有了微服务,通过注册中心去管理,有了熔断降级,有了配置中心等等。
总结
到这里,我们就会有一个结论:大家做架构设计要有一个信心,就是不要怕架构无法满足业务。当真的遇到架构变得越来越复杂,复杂度成指数级提升的时候,创新的解决办法就会有了,天无绝人之路。
从我们前面的演进过程来看,我们发现每次技术架构的变革,都是由于技术无法满足业务,要么是业务量增大了,要么是用户增多了,数据量增大了等等。为了应对这些业务的变化,我们来调整我们的架构。所以说,技术和业务呢,是相辅相成,相互促进的。
这就是技术演进的大概的路径。
- 初始阶段:一台服务器。
- 服务器拆分:对服务器进行了拆分,文件、数据库、应用进行了独立。
- 缓存:为了提高访问速度,加了缓存。
- 集群:加了集群,提高应用服务器的服务能力。
- 读写分离:由于数据库的压力太大,我们把读写进行了分离,并且加了数据访模块,查都走从写都走主,通过一个组件去进行路由。
- cdn和反向代理:在更前面做的缓存,就是cdn和反向代理。
- 分布式系统:将存储相关的组件做了分布式,用公共的访问模块去访问。
- 搜索引擎和NoSQL数据库:用搜索引擎或者一些NoSQL数据库满足复杂的查询业务场景。
- 服务拆分:把大服务拆分了无数个小服务,之间通过rpc或者消息队列进行通信。
- 微服务:微服务的组织架构,出现了配置中心,注册中心,熔断降级限流隔离等等。
这就是我们技术架构的一个演进过程。这里再强调一句,不是所有的网站都会像上面所说的内容一样一步一步进化的,有的网站可能是跳跃着去进化。比如说,第一步就遇到数据库的压力了,直接数据库就做了分库分表,这都是有可能的。