前言以淘宝为例,简单了解一下大型电商的服务器架构是什么样的。如图:上面是安全系统,中间是业务操作系统,包括各种业务服务,下面是一些共享服务,然后是一些中间件,其中ECS是云服务器,MQS是队列服务,OCS是缓存等,右边是一些配套的系统服务。除了图中显示的,还有一些我们看不到的,比如高可用的体现。淘宝现已实现多机房容灾和异地机房单元化部署,为淘宝业务提供了稳定、高效、易维护的基础设施支撑。这是一座含金量非常高的建筑,也是一座非常复杂庞大的建筑。当然,这个架构不是一天两天演变成这个样子的,也不是一开始就设计开发出来的。对于初创公司来说,很难在前期预估未来几千、几万倍的访问量,网站结构会是什么样子。同时,如果前期设计千万级并发流量的流量结构,很难支撑这个成本。所以,一个大的服务体系是从一个小的一步一步来的。在每个阶段,它都发现该阶段网站架构所面临的问题,然后不断解决这些问题。在这个过程中,整个架构会不断演进。代码也会进化,从架构到代码,都在不断进化和优化。因此,高层次的项目技术架构和开发设计的实现,不可能一蹴而就。这就是所谓的平地而建的高楼。独立架构从一个小网站开始。一般来说,一台初始服务器就够了,文件服务器、数据库、应用都部署在一台机器上。也称为allinone架构。多机部署随着网站用户逐渐增多,访问量越来越大,硬盘、cpu、内存等开始吃紧,单台服务器难以支撑。从演进过程来看,我们把数据服务和应用服务分开,为应用服务器配置更好的cpu、内存等,为数据服务器配置更好更快的大硬盘,如图。在一台服务器上部署可以提高某些性能和可用性。随着访问并发度越来越高,分布式缓存不断演进架构,以减少接口的访问时间,提高服务性能。我们发现有很多业务数据不需要每次都从数据库中获取,所以我们使用缓存,因为80%的业务访问集中在20%的数据上(28原则),如果这部分ofdata可以缓存,性能可以提升很多,缓存有两种,一种是Application中的本地缓存,一种是远程缓存,远程缓存又分为远程单机缓存和分布式缓存缓存(图中为分布式缓存集群)。我们需要思考几点,业务特征使用缓存的数据,业务特征使用本地缓存的数据,业务特征使用远程缓存的数据。分布式缓存在扩容时会遇到哪些问题,如何解决,分布式缓存算法有哪些,各自的优缺点是什么。这些问题都是我们在使用这个架构的时候需要思考和解决的问题。这时候随着服务器集群的访问qps不断增加,假设我们使用的ApplicationServer是tomcat,那么tomcat服务器的处理能力就会成为瓶颈。虽然我们也可以购买更强大的硬件,但总会有一个上限,而且这个成本在后期会成倍增长。这时候我们可以做一个服务器集群,然后添加一个负载均衡调度器(LoadBalancer)。服务器集群后,我们可以横向扩展我们的服务器,解决了服务器处理能力的瓶颈。这个时候我们需要多思考几个问题,负载均衡有哪些调度策略,它们的优缺点是什么,各自适合什么场景,比如轮询、权重、地址散列、地址散列分为原始IP地址哈希列、目标IP地址哈希列、最少连接数、加权最少连接数等。服务器集群后,假设我们登录到服务器A,会话信息存储在服务器A上,如果我们的负载均衡策略是roundrobin或者最小连接数等,那么下次访问服务器B是有可能的,并且此时会存储在服务器A中。我们无法读取到B服务器上的session信息,所以需要解决session管理的问题。session共享解决方案sessionsticky我们使用sessionsticky来解决这个问题。它的处理规则是,对于同一连接中的数据包,负载均衡器会进行NAT转换,转发给后端固定服务器进行处理。Processing,这个方案解决了session共享的问题。如图所示,client1会通过负载均衡固定转发到server1。缺点是首先,假设一个服务器重启,服务器的所有session都会消失。第二,我们的负载均衡服务器变成了有状态服务器,实现容灾会很麻烦。sessionreplication会话复制,即browser1通过负载均衡服务器将session保存到application1时,同时也会将session复制到application2,所以多个服务器都保存了相同的session信息。缺点是应用服务器的带宽问题。会话信息必须在服务器之间同步。当大量用户在线时,服务器会占用过多的内存。基于cookie基于cookie,也就是说我们每次访问应用服务器都是使用cookie携带session信息。缺点是cookie的长度有限,在浏览器上保存cookie的安全性也是个问题。sessionserver把session做成sessionserver,比如可以使用redis来实现。这样,每个用户访问应用服务器,其会话信息最终存储在会话服务器中,应用服务器也从会话服务器获取会话。应考虑以下问题。在当前架构中,会话服务器是一个单点。如何解决单点并保证其可用性。当然,sessionserver也可以做成集群。这种方式适用于session数量和web服务器数量较多的情况,改成这种架构后,写应用的时候存储session的业务逻辑也要调整。数据库读写分离解决了服务器水平扩展后,继续看数据库。数据库的读写操作需要经过数据库。当用户数量达到一定数量时,数据库的性能再次成为瓶颈,我们不断进化。我们可以利用数据库的读写分离,应用需要访问多个数据源。通过统一的数据访问模型进行访问。数据库的读写分离是将写操作全部引入主库(master),将读操作引入从库(slave)。这时,应用程序也必须做出相应的改变。我们实现了一个数据访问模块(dataaccessmodule),让上层写代码的人意识不到读写分离的存在,让多个数据源的读写不侵扰业务代码。这就是代码层面的演变。如何支持多数据源,如何在不侵入业务的情况下进行封装,如何利用业务目前使用的ORM框架完成主从读写分离,是否替换ORM,优缺点是什么各有千秋,如何取舍是当前架构需要考虑的问题。当访问量过大,也就是数据库的IO非常大,我们的数据库读写分离会遇到以下问题?比如主库和从库的复制有没有延迟?如果我们将主库和从库分别部署在不同的机房,那么跨机房的同步数据传输就更成问题了。另外,应用到数据源的路由问题也是需要考虑和解决的一点。CDN加速和反向代理我们不断增加CDN和反向代理服务器(Reverseproxyserver)。使用CDN可以很好的解决不同地域的访问速度问题,反向代理可以在服务器机房缓存用户资源。分布式文件服务器这时候我们的文件服务器又出现了瓶颈。我们将文件服务器更改为分布式文件服务器集群。在使用分布式文件系统的时候,我们需要考虑几个问题,如何不影响线上应用Access的部署,是否需要业务部门帮忙清理数据,是否需要备份服务器,是否需要需要重新做域名解析等等。数据库分库分表这时候我们的数据库又出现了瓶颈。我们选择专门的数据库进行数据的垂直拆分,相关业务独家使用我们自己的数据库。我们解决大并发数据写入的问题。当我们将这些表分到不同的库中时,会带来一些新的问题。比如跨业务、跨库的事务,可以使用分布式事务,或者去掉事务,或者不追求强事务。随着访问量和数据量的增加,某项业务的数据库数据量和更新量已经达到了单个数据库的瓶颈。这时候就需要对数据库进行横向拆分,比如将user拆分为user1,而user2就是将同一张表的数据拆分到两个数据库中。这个时候我们就解决了单一数据库的瓶颈。横向拆分要注意哪些点,横向拆分的方法有哪几种。水平拆分之后,我们会遇到几个问题。第一个问题是sql路由。假设有一个用户,我们如何知道用户信息是否存在于user1或user2数据库中呢?因为分库,我们的主键策略也会不同,同时也会面临分页的问题。假设我们要查询某月下单的用户详情,这些用户分布在user1和user2库中。我们后台运行管理系统显示的时候也是有分页的。这些都是我们在使用这个架构时需要解决的问题。搜索引擎和NoSQL在网站发布并进行大规模推广后,我们应用服务器的搜索量再次飙升。我们把应用服务器的搜索功能单独提取出来,做了一个搜索引擎。同时,一些场景可以通过使用NoSQL得到改善。表现。同时开发统一的数据访问模块,同时连接数据库集群、搜索引擎和NoSQL,解决上层应用开发的数据源问题。这里的前言只是一个简单的例子,并不基于任何实际的业务场景。事实上,每个服务的架构都需要根据实际业务特点进行优化演进,所以流程并不完全相同。当然,这个架构并不是最终的形式,还有很多地方需要改进。比如负载均衡服务器目前是单点的。如果负载均衡服务器无法访问,那么后续服务器包括服务器集群也将无法访问。所以可以把负载均衡服务器做成一个集群,然后做一些主从双机热备,同时做一个自动切换的方案。在整个架构的演进过程中,其实需要关注的东西更多,比如安全、数据分析、监控、反作弊……针对一些具体的场景比如交易、充值、流计算、等等,使用消息队列,任务调度……整个架构不断发展,做SOA架构,服务(微服务),多机房……最后想说一下项目的高层技术架构而开发设计的实现绝非一蹴而就。
