高并发与高可用
大型网站系统应有的特点
高并发,大流量:需要面对高并发用户,大流量访问。举个例子,去往迪拜的飞机有200张票,但是有100w人都挤进系统买票,如何让这100w人能够看到票务的实时更新,以及顺利的买到一张票,都是一个网站架构师应该考虑的问题。这也许对于淘宝的“双十一”1000w的一分钟独立访问用户量来说,是个微不足道的数字,但是对于用户的体验以及网站的口碑来说,都是一项不小的挑战。
高可用:相对于高并发来说,高可用并不是一个比较有规律的参数,7*24 是每个网站的梦想,但是你并不知道,在某一刻,他就没理由的宕机了。
海量数据:存储,管理海量的数据,需要使用大量的服务器。FaceBook每周上传的照片接近10亿,没有一个大型的存储服务器的支撑,相信用户量不会一直飙升。
许多大型的互联网都是为全球用户提供服务的,用户分布范围广,各地网络情况千差万别。各个运行商之间的互通,各个国家的数据连接等等。
由于互联网的开放性,使得互联网更容易受到攻击,包括各种省份证信息被窃取等事件屡见不鲜。
几乎所有的大型互联网网站都是从一个小网站开始,渐进发展起来的,好的互联网产品都是慢慢运营出来的。
网站架构演变过程
传统项目分为三层架构,将业务逻辑层、数据库访问层、控制层放入在一个项目中 使用SSH或者SSM技术。
优点:适合于个人或者小团队开发,不适合大团队开发。
根据业务需求进行拆分成N个子系统,多个子系统相互协作才能完成业务流程子系统之间通讯使用RPC远程通讯技术。
优点:
1.把模块拆分,使用接口通信,降低模块之间的耦合度。
2.把项目拆分成若干个子项目,不同的团队负责不同的子项目。
3.增加功能时只需要再增加一个子项目,调用其它系统的接口就可以。
4.可以灵活的进行分布式部署。
有优点就有缺点,缺点如下:
1.系统之间交互需要使用远程通信,接口开发增加工作量。
2.各个模块有一些通用的业务逻辑无法共用。
为了解决上面分布式架构的缺点,我们引入了soa架构,SOA:Service Oriented Architecture面向服务的架构。也就是把工程拆分成服务层、表现层两个工程。服务层中包含业务逻辑,只需要对外提供服务即可。表现层只需要处理和页面的交互,业务逻辑都是调用服务层的服务来实现。
SOA是一种软件架构模式,将共同的业务逻辑抽取出来,封装成单独的服务
业务系统分解为多个组件,让每个组件都独立提供离散,自治,可复用的服务能力
通过服务的组合和编排来实现上层的业务流程
作用:简化维护,降低整体风险,伸缩灵活
微服务是指开发一个单个、小型的但有业务的服务,每个服务都有自己的处理和轻通讯机制,可以部署在单个服务器上,让专业的人做专业的事情。
微服务与SOA相比,更加轻量级。
OA架构主要针对企业级、采用ESB服务(ESB企业服务总线),非常重,需要序列化和反序列化,采用XML格式传输。
微服务架构主要互联网公司,轻量级、小巧,独立运行,基于Http+Rest+JSON格式传输。
ESB也可以说是传统中间件技术与XML、Web服务等技术相互结合的产物。
1.在微服务中,与SOA不同,服务可以独立于其他服务进行操作和部署,因此更容易经常部署新版本的服务和独立扩张服务,让专业的人做专业的事情,快速迭代新的产品。
2.在SOA中服务可能共享数据存储,而微服务中每个服务都具有独立的数据存储。
3.SOA与微服务主要区别在于规模和范围,SOA是一种思想,是面向服务架构体系,微服务继承 了SOA的优点,去除传统的ESB消息总线,采用Http+json格式通讯方式,更加轻量级。
高并发设计原则
系统设计不仅需要考虑实现业务功能,还要保证系统高并发、高可用、高可靠等。同时还应考虑系统容量规划(流量、容量等)、SLA指定(吞吐量、响应时间、可用性、降级方案等)、监控报警(机器负载、响应时间、可用率等)、应急预案(容灾、降级、限流、隔离、切流量、可回滚等)。
缓存
异步并发
连接池
线程池
扩容
消息队列
分布式任务
在我们从零开始做一个新系统的时候,会首先进行系统功能模块架构设计,那么是直接做一个大而全的垂直的MVC系统,使用一个war包进行发布管理,还是需要按一些规则进行模块拆分,设计成SOA或者微服务系统比较好呢?这个笔者认为需要依据项目具有什么样的人力物力条件以及项目需要支撑多少用户量和交易量为基础。一个好的系统设计应该能够满足解决当前的需求和问题,把控实现和进度风险,预测和规划未来,避免过度设计,在上线一个基础核心版本之后,再进行不断迭代和完善。
今天我们来谈一谈进行SOA、微服务系统架构设计时模块拆分的一些维度和原则。
系统维度:按照系统功能、业务拆分,如、优惠券、购物车,结算,订单等系统。
功能维度:对系统功能在做细粒度拆分,优惠券系统分为 优惠券后台系统、领券系统、发券系统。
读写维度:比如商品系统中,如果查询量比较大,可以单独分为两个服务,分别为查询服务和写服务,
读写比例特征拆分;读多,可考虑多级缓存;写多,可考虑分库分表.
AOP 维度: 根据访问特征,按照 AOP 进行拆分,比如商品详情页可分为 CDN、页面渲染系统,CDN 就是一个 AOP 系统
模块维度:对整体代码结构划分 Web、Service、DAO
在分布式系统中,将业务逻辑层封装成接口形式,暴露给其他系统调用,那么这个接口我们可以理解为叫做服务。
当服务越来越多的时候,就会需要用到服务治理,那么会用到Dubbo、SpringCloud服务治理框架
后续在深入Dubbo和SpringCloud中会详细讲到。
服务化演进: 进程内服务-单机远程服务-集群手动注册服务-自动注册和发现服务-服务的分组、隔离、路由-服务治理
考虑服务分组、隔离、限流、黑白名单、超时、重试机制、路由、故障补偿等
实践:利用 Nginx、HaProxy、LVS 等实现负载均衡,ZooKeeper、Consul 等实现自动注册和发现服务
消息中间件是一个客户端与服务器异步通讯框架,消息中间件中分为点对点与发布订阅通讯方式,生产者发送消息后,消费者可以无需等待, 异步接受生产者发送消息。
在电商系统中,会使用消息队列异步推送消息,注意消息失败重试幂等性问题。
幂等性问题解决方案,使用持久化日志+全局id记录。
浏览器端缓存
APP客户端缓存
CDN(Content Delivery Network)缓存
接入层缓存
应用层缓存
分布式缓存
对于兜底数据或者异常数据,不应该让其缓存,否则用户会在很长一段时间里看到这些数据。
改串行为并行。
高可用设计原则
通过负载均衡和反向代理实现分流。
通过限流保护服务免受雪崩之灾。
通过降级实现部分可用、有损服务。
通过隔离实现故障隔离。
通过合理设置的超时与重试机制避免请求堆积造成雪崩。
通过回滚机制快速修复错误版本。
对于高可用服务,很重要的一个设计就是降级开关,在设计降级开关时,主要依据如下思路:
1.开关集中化管理:通过推送机制把开关推送到各个应用。
2.可降级的多级读服务:比如服务调用降级为只读本地缓存、只读分布式缓存、只读默认降级数据(如库存状态默认有货)。
3.开关前置化:如架构是Nginx–>tomcat,可以将开关前置到Nginx接入层,在Nginx层做开关,请求流量回源后端应用或者只是一小部分流量回源。
4.业务降级:当高并发流量来袭,在电商系统大促设计时保障用户能下单、能支付是核心要求,并保障数据最终一致性即可。这样就可以把一些同步调用改成异步调用,优先处理高优先级数据或特殊特征的数据,合理分配进入系统的流量,以保障系统可用。
目的: 防止恶意请求攻击或超出系统峰值
实践:
恶意请求流量只访问到 Cache
穿透后端应用的流量使用 Nginx 的 limit 处理
恶意 IP 使用 Nginx Deny 策略或者 iptables 拒绝
目的:屏蔽故障机器
实践:
DNS: 更改域名解析入口,如 DNSPOD 可以添加备用 IP,正常 IP 故障时,会自主切换到备用地址; 生效实践较慢
HttpDNS: 为了绕过运营商 LocalDNS 实现的精准流量调度
LVS/HaProxy/Nginx: 摘除故障节点
发布版本失败时可随时快速回退到上一个稳定版本
业务设计原则
页面请求防止重复提交,可以采用防重key、放重表、Token等
采用图形验证,防止机器攻击。
消息中间件:消息中间件中应该注意因网络延迟的原因,导致消息重复消费
第三方支付接口:在回调接口中,应该注意网络延迟,没有及时返回给第三方支付平台,注意回调幂等性问题。
分布式系统中,保证生成的订单号唯一性,定时Job执行的幂等性问题等。
复用流程系统,提供个性化的流程服务。
复用流程系统,提供个性化的流程服务。
设计后台系统时,考虑效果的可预览、可反馈。
对于有些重要的后台功能需要设计审批流,比如调整价格,并对操作进行日志记录,从而保证操作可追溯、可审计。
系统发展的最初阶段就应该有文档库(设计架构、设计思想、数据字典/业务流程、现有问题),业务代码合特殊需求都要有注释。
包括代码和人员的备份。代码主要提交到代码仓库进行管理和备份,代码仓库至少应该具备多版本的功能。人员备份指的是一个系统至少应该有两名开发人员是了解的。