微服务架构下的⾼可⽤和⾼性能设计今天再谈下微服务架构下的⾼可⽤性设计。
对于⾼可⽤性实际应该包括了⾼可靠性,⾼性能和⾼扩展性。因此谈微服务架构的⾼可⽤性,⾸先需要梳理三者之间的关系。
⾼可⽤性三个维度和相互关系
对于业务系统的⾼可⽤性,实际上包括了⾼可靠,⾼性能和⾼扩展三个⽅⾯的内容。⽽且三⽅⾯相互之间还存在相互的依赖和影响关系。
对于三者的关系,我们可以⽤下图进⾏描述。
上图可以看到⾼可靠,⾼性能和⾼扩展性三者之间的关系。
对于⾼可靠性来来说,传统的HA架构,冗余设计都可以满⾜⾼可靠性要求,但是并不代表系统具备了⾼性能和可扩展性能⼒。反过来说,当系统具备了⾼扩展性的时候,⼀般我们在设计扩展性的时候都会考虑到同时兼顾冗余和⾼可靠,⽐如我们常说的集技术。
对于⾼性能和⾼扩展性两点来说,⾼扩展性是⾼性能的必要条件,但是并不是充分条件。⼀个业务系统的⾼性能不是简单的具备扩展能⼒就可以,⽽是需要业务系统本⾝软件架构设计,代码编写各⽅⾯都满⾜⾼性能设计要求。
对于⾼可靠和⾼性能,两者反⽽表现出来⼀种相互制约的关系,即在⾼性能⽀撑的状态下,往往是对系统的⾼可靠性形成严峻挑战,也正是这个原因我们会看到类似限流熔断,SLA服务降级等各种措施来控制异常状态下的⼤并发访问和调⽤。
数据库的⾼可⽤性
在我前⾯谈微服务架构的时候就谈到,在微服务架构下传统的单体应⽤要进⾏拆分,这个拆分不仅仅是应⽤层组件的拆分,还包括了数据库本⾝的拆分。
如果⼀个传统的单体应⽤规划为10个微服务,则可能会垂直拆分为10个独⽴的数据库。这实际上减⼩
了每⼀个数据库本⾝⾯对的性能负荷,同时提升了数据库整体的处理能⼒。
分布式和微服务的关系同时在拆分后虽然引⼊了各种跨库查询,分布式事务等问题,但是实际很多跨库操作,复制的数据处理计算都不在数据库⾥⾯完成,数据库更多的是提供单纯的CRUD类操作接⼝,这本⾝也是提升数据库性能的⼀个关键。
如果采⽤Mysql数据库。
要满⾜⾼可靠性,你可以采⽤Dual-Master双主架构,即两个主节点双活,但是仅⼀个节点提供数据库接⼝能⼒,另外⼀个节点实时同步数据库⽇志,作为备节点。当主节点出现故障的时候,备节点⾃动转变为主节点服务。
简单的双主架构两节点间安装代理,通过Binlog⽇志复制,上层通过类似Haproxy+Keepalive实
现通过的VIP浮动IP提供和⼼跳监测。
可以看到双主架构更多的是为⾼可靠服务。
如果要满⾜⾼性能,常采⽤的是读写分离集。即1个主节点承担读写操作,多个从节点承担读操作。从节点仍然是通过Binlog⽇志进⾏主节点信息同步。当有数据访问请求进⼊的时候,前端Proxy可以⾃动分析是CUD类请求,还是R读请求,以进⾏请求的路由转发。
当我们进⾏订单新增操作的时候,当新增成功的时候需要快速的刷新当前订单列表
界⾯,第⼆次的刷新本⾝是读操作,但是和前⾯的写绑定很紧,实际上不太适合从
Slave节点读取数据的。这个时候可以在进⾏Sql调⽤的时候明确指定是否仍然从主
节点获取数据。
当然,⼤部分时候可能需要两者结合,既提供⾜够的⾼可靠性,⼜提供⾜够的⾼性能。因此Mysql集在搭建的时候既需要进⾏双主设置,⼜需要进⾏多个从节点设置。
在上图这种逻辑部署架构下,基本就可以同时满⾜⾼可靠和⾼性能两个⽅⾯的需求。但是从上⾯架构部署可以看到,备节点的主和从都处于⼀种热备⽆法实际提供能⼒状态。
是否可以将所有Slave挂到⼀个Master上?
如果这样设计,那么当主Master出现故障的时候,就需要对多个Slave节点进⾏⾃动化漂移。这⼀⽅⾯是整体实现⽐较复杂,另外就是可靠性也不如上⾯这种架构。
对数据库性能扩展的思考
⾸先来看前⾯架构本⾝的⼀些潜在问题点:
第⼀就是CUD操作仍然是单节点提供能⼒。对于读操作占⼤部分场景的,基本可以通过双主+读写分离集实现很好的性能扩展。但是如果CUD操作频繁仍然可能出现性能问题。
其次,数据库性能问题⼀般分为两个层⾯,其⼀就是⼤并发请求下的性能,这个可以通过集负载均衡去解决,其⼆是单个请求访问⼤数据库表模糊查询性能,这个是服务通过负载去解决的。
也就是说上⾯的设计,在⼤并发的CUD操作,对⼤数据表的关联查询或模糊查询操
作仍然可能出现明显的性能问题。
如何来解决这个问题?
简单来说就是写⼊通过消息中间件来将同步转异步,进⾏前端削峰。⽽对于查询则进⾏内容缓存或创建⼆级索引,提升查询效率。
对于查询本⾝⼜包括了偏结构化数据查询和处理,类似采⽤Redis库或Memcached进⾏缓存;⽽对于⾮结构化数据,类似消息报⽂,⽇志等采⽤Solr或ElasticSearch构建⼆级索引并实现全⽂检索能⼒。
当⾯临⼤量的数据写⼊操作类操作的时候,单个Master节点往往性能很难⽀撑住,这个时候采⽤类似RabbitMQ,RocketMQ,Kafka等消息中间件来进⾏异步销峰处理就是必要的。这个异步实际上涉及到两个层⾯的异步。
其⼀是对于发短信,记录⽇志,启流程等接⼝服务异步。其⼆是对长耗时写⼊操作异步,先反馈⽤户请求收到,处理完再通知⽤户拿结果。
⽽对于查询操作,前⾯谈到的并发查询可以进⾏集负载。
但是对于⼤数据量表,⽐如上亿记录的⼤表模糊查询,这块就必须进⾏⼆级索引。对这种⼤的数据表的查询即使没有并发查询,如果不进⾏⼆级索引,查询效率和响应速度仍然很慢。
对半结构化信息启⽤分布式存储
对于类似⽇志,接⼝服务调⽤⽇志等半结构化信息,本⾝数据量很⼤,如果全部存储在结构化数据库中,那么对存储空间需求很⼤,⽽且很难扩展。特别是前⾯的Mysql集⽅案本⾝还是采⽤本地磁盘进⾏存储的情况下。
因此需要对历史⽇志进⾏清除,同时将历史⽇志迁移到分布式存储库,⽐如Hdfs或Hbase库,然后基于分布式存储再构建⼆级缓存能⼒。
构建DaaS数据层进⾏⽔平扩展
前⾯谈到在拆分了微服务后已经进⾏了垂直扩展,⽐如⼀个资产管理系统可以拆分为资产新增,资产调拨,资产折旧,资产盘点等10个微服务模块。
但是在拆分后仍然发现资产数据量极⼤,⽐如在集团集中化这种⼤型项⽬可以看到,⼀个省的资产数据表就接近上亿条记录。这种时候将所有省数据全部集中化在⼀个数据库管理不现实。因此需要进⼀步按省份或组织域进⾏⽔平拆分。
在⽔平拆分后,在上层构建DaaS层提供统⼀对外访问能⼒。
应⽤集扩展
对于应⽤集扩展实际⽐数据库层要简单,应⽤中间件层可以很⽅便的结合集管理节点或者独⽴的负载均衡硬件或软件进⾏集能⼒扩展。对于应⽤集扩展,本⾝就是提升整个性能的关键⽅式。在集的扩展过程中还是有些问题需要进⼀步讨论。
集做到完全的⽆状态化
如果集做到完全的⽆状态化,那么集就可以做到和负载均衡设备或软件结合来实现负载均衡扩展能⼒。⽐如硬件常⽤的F5或radware等,软件如HAProxy,Nginx等。
Session会话信息如何处理?对于Session本⾝是有状态的,因此对于Session信息可以考虑存储到数据库或Redis缓存库中。
集节点在启动的时候往往需要读取⼀些全局变量或配置⽂件信息,这些信息如果简单的存在在本地磁盘往往难以集中化管理。因此当前主流思路是启⽤全局的配置中⼼来统⼀管理配置。
如果应⽤功能实现中存在⽂件的上传和存储,那么这些⽂件存储在磁盘本地本⾝也是有状态的,因此对于这些⽂件本⾝也需要通过⽂件服务能⼒或分布式对象存储服务能⼒来实现。
微服务架构下各个微服务间本⾝存在接⼝交互和协同,对于接⼝调⽤的具体地址信息也需要通过服务注册中⼼获取,获取后可以缓存在本地,但是必须有变更后实时更新机制。
四层负载和七层负载
⾸先看下最简单的四层负载和七层负载的⼀个说明:
四层负载:即在OSI第4层⼯作,就是TCP层,可以根据IP+端⼝进⾏负载均衡。此种Load Balance不理解应⽤协议(如HTTP/FTP/MySQL等等)。
七层负载:⼯作在OSI的最⾼层,应⽤层,可以基于Http协议和URL内容进⾏负载均衡。此时负载均衡能理解应⽤协议。
当前可以看到对于F5,Array等硬件负载均衡设备本⾝也是⽀持7层负载均衡的,同时在四层负载均衡的时候我们还可以设置是否进⾏会话保持等⾼级特性。要明⽩四层负载均衡本质是转发,⽽七层负载本质是内容交换和代理。
也就是说在不需要进⾏状态保留和基于内容的路由的时候,我们完全可以启⽤四层
负载均衡来获取更好的性能。
在微服务架构前后端分离开发后。
后端微服务组件可以完全提供Rest API接⼝服务能⼒,那么本⾝就⽆状态。⽽对于前端微服务组件直接⾯对最终⽤户访问,需要保持Session状态。在这种情况下就可以进⾏两层负载均衡设计,即前端采⽤七层负载,⽽后端采⽤四层负载均衡。
前端缓存
前端缓存主要是分为HTTP缓存和浏览器缓存。其中HTTP缓存是在HTTP请求传输时⽤到的缓存,主要在服务器代码上设置;⽽浏览器缓存则主要由前端开发在前端js上进⾏设置。缓存可以说是性能优化中简单⾼效的⼀种优化⽅式了。⼀个优秀的缓存策略可以缩短⽹页请求资源的距离,减少延迟,并且由于缓存⽂件可以重复利⽤,还可以减少带宽,降低⽹络负荷。
具体可以参考:
www.jianshu/p/256d0873c398
软件性能问题分析和诊断

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。