分布式Web服务架构的快速演变之路

我相信很多文章写过这个主题,我们今天这篇文章之所以要再次写这个主题,一方面是想对现今Web服务架构的各个方面做一个演进的总结,另一方面也是想对自己在Web服务架构方面的经验加以落地,总结旧的经验才能演进更加优越的方案。个人工作以来从事的技术栈主要是PHP及Golang环境的,所以相关的栗子一般也都会以这两种语言为主。 

单机部署

Web服务一上线,服务的访问量有限,我们可能只需要一台单机即可支撑整个web服务的请求,一台单机同时部署web服务和数据库等,一个PHP-FPM、Nginx、Mysql的服务即可满足所有的需求。

Web服务与数据库分离

但是随着业务的房展,请求量上升,我们想想提高并发能力,增加一台服务器,将HTTP请求与SQL操作负载分散不同服务器。于是采用PHP、Nginx部署与Mysql部署分离的策略。

动静资源分离

我们知道Nginx最早主要用来做静态资源的访问、缓存。因此我们的Web服务可以针对静态资源,直接从nginx层面返回给浏览器。在nginx的配置中,可以根据访问资源的后缀、路径等通过正则匹配为相应的静态资源设置缓存时间。从而实现动静分析,静态资源由nginx层面直接返回,动态资源通过转发到后端的PHP或者其他程序进行解析、执行再返回给Nginx,最终返回给浏览器。

数据库主从分离

随着访问量的大增,数据库压力会急剧上升,这个时候我们可以考虑主从分析的方式,从库基于binlog进行主从复制,可以是一主多从或者其他架构。主从分离有以下好处:

  • 将读操作和写操作分离到不同的数据库上,避免主服务器出现性能瓶颈;

  • 主服务器进行写操作时,不影响查询应用服务器的查询性能,降低阻塞,提高并发;

  • 数据拥有多个容灾副本,提高数据安全性,同时当主服务器故障时,可立即切换到其他服务器,提高系统可用性;

缓存

针对读多写少的场景,我们可以考虑对读的数据增加缓存,缓存的方案又是一个大的话题,在此不做展开。一般采用读时穿透做缓存,需要加锁防止放生雪崩效应。或者采用缓存定时刷新预热的方式。在后续的文章中,会专针对缓存的架构设计做展开。目前主要采用的是Memcached和Redis两种方案。

七层负载均衡

访问量越来越大,单台服务器性能已无法支撑,于是增加负载均衡,水平扩展WEB节点,同时调整动静分离。

我们一般在Nginx层面做七曾负载均衡,后端再挂不同的机器集群,这样达到不同的请求映射到不同的服务集群,达到服务集群的水平扩展。

我们知道负载均衡有很多策略,从硬件层面例如H5服务器,到软件层面:Nginx、HA。但是方案一般就以下几种:轮询、指定权重、ip哈希(绑定)、Url哈希、Dns轮询等

Session共享

分布式部署服务以后,我们需要考虑session共享的问题,原有的服务是单机,session保存在单机的服务器上。现在是多个服务器的分布式部署,不同的session再存在自己的服务器上则会出现数据不一致的情况,因此我们要做session的共享,一般采用redis或者memcached等做数据共享,走长连接的方式。

数据库架构扩展

上文已经介绍,随着业务量上升,单台数据库读性能到达瓶颈,响应很慢;业务读多写少,需要提升读性能,考虑扩展数据库架构。

一主多从

基于binlog异步复制,多个从库同步主库。

读写分离

搜索独立:搜索功能采用全文搜索引擎,利用ElasticSearch或者solr等开源全文搜索引擎,做mysql数据到es的同步,由ES提供全文搜索引擎。

分库、分表、分区

  • 分库:根据业务类型分离相关表到不同数据库;例如WEB、BBS、Blog等。

  • 分表:单个表上千万条记录,操作耗时长,采用垂直拆分和水平拆分,将数据分散存储到不同小表上。

  • 分区:根据表字段分成多个区块,这些区块可以分布在不同磁盘上。

以上主要是分散磁盘I/O压力,提高处理性能。

从库四层负载均衡

当多个从库时,采用LVS实现负载均衡,对程序提供VIP,访问透明。

HA

主库和从库LB:Keepalived

服务拆分

随着服务的发展,业务变得庞大复杂,如果还是单体应用,那将会是非常恐怖,一个小功能的迭代极有可能产生致命的问题,因此需要考虑:

  • 服务化治理:RPC远程调用方案 。

  • 配置中心:使用Zookeeper存储服务连接信息。

  • 消息队列,Kakfa、RabitQ、ZeroQ、Nmp等

静态资源服务器

每次请求静态资源负载都会落在WEB节点和NFS存储上,而且这些资源都是很少变动的,我们把这些资源缓存到上层,请求到来时先判断本地是否有缓存,如果有就直接返回,从而减少后端HTTP请求,响应会快很多。

CDN

为了进一步提高用户对于静态资源的访问速度,我们可以将静态资源放到CDN上,我们知道一些大的CDN提供商在全国乃至全球都有很多服务节点,用户都可以就近享受服务速度上的提升。

进展到现在我们有更多的解决方案,例如:

  • 弹性伸缩:自动扩容,节点降级。

  • 微服务:更细粒度拆分应用,实现服务化、轻量级、自动化部署等。

  • 内存化:磁盘数据尽可能在内存中处理。

  • 异地容灾:如果不可容忍网站不可用,应考虑到异地备份或异地双活。

关于微服务,本公众号也有详细的文章介绍,可以翻阅查看。以上介绍的都是一些细节的点,除了这些积累的经验,我们还需要从整体上考虑:

系统分级:按照业务系统重要性划分,比如订单服务挂了,将影响用户无法下单,因此需要投入更多的资源保障;比如管理后台挂了,不会影响到用户;根据业务划分不同级别,实施不同的质量保障和成本投入。

全链路分析:梳理从网站入口到数据存储的各个环节,找出依赖服务,假设性去分析问题,如果某环节故障,影响范围怎样。

全方位监控:对相关链路实施全面监控,包括基础资源监控、服务状态监控、接口监控、日志监控等,确保出现问题有依据可追溯。

制定应急预案:多思考方案可行性,不定期进行预案演习,验证预案正确性和可控性及掌握恢复时间。

网络接入层:机房故障:从DNS轮训摘除该机房或者切换到其他机房;VIP网络异常:切换备用VIP

代理层:IP限流:某些IP访问太大导致后端负载压力过高;实施IP限流;后端应用异常:如软硬件故障,摘除异常节点;如果某机房问题切换到其他机房

应用层和服务层:服务异常:某服务访问超时,响应慢;摘除服务或切换到正常服务;程序线程池不够用:线程池设置太小,导致请求堆积;提供参数开关,比如动态调整线程池大小;请求量太大:请求量太大,超过实际处理能力;请求限流或者设置请求阈值自动扩展节点

缓存层和数据层:Redis挂掉:主从切换;MySQL挂掉:主从切换,切换后验证;机房故障:切换缓存库/数据库到其他机房。

以上大致涉及到了Web服务架构的绝大部分,包括细节、也包括一些大的层面的考虑:总体上要考虑服务的:高性能、高可能、可扩展(自动伸缩)、方便部署等方面。

欢迎扫码,关注我的微信公众号

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值