1. 分布式微服务架构设计原理
1.1 从传统的单体架构到到服务化架构
架构的演进答题分为三个阶段:
- JEE架构阶段
- SSH架构阶段
- 服务化架构阶段
- JEE架构阶段主要划分为 UI交互研发团队(前端研发工程师)、后台研发工程师和DBA研发团队。SSH架构 阶段划分上与JEE架构阶段停留在相同层次上,不同点在于使用springMVC的划分性质,使用了Struts、Spring、Hiberate几个框架使得开发变得简单。
- 服务化架构不同于以上两种单体层次的架构模式,它解决了单体程序的高耦合和高并发程序无法突破瓶颈的限制。而SOA则是服务化的典型代表,它通过将服务进行详细的设计规划,拆分成一个个小型的服务,这些服务都必须在其定义的接口和契约上完成,并且通过诸如HTTP、TCP或IP等网络通讯协议进行网络通讯。典型的两种SOA实现方式是:Web service(注册发现模式) 和 ESB(总线模式),现在大型互联网公司主流喜欢使用 Zookerper 和 Dubbo 的服务化架构模式。
1.2 从服务化到微服务
SOA服务化是为了让每个服务职责单一、更简单和易于扩展,但存在历史遗留问题。而微服务架构则致力于松耦合和高内聚的效果,其强调每个服务的独立开发、维护、部署。
- 与传统的结构相比,微服务更加的灵活,可以平滑的进行水平扩展。具有子服务独立打包部署的特点,让更专业的人做专业的事。
- 与SOA服务相比较,目的不同、部署方式不同以及服务粒度不同。
- 目的性 SOA强调有效集成、历史应用集成、应用流程编排。微服务强调有效的拆分应用,实现敏捷开发和部署。
- 部署方式 SOA通过将组件化模块打成一个WAR包部署在一台应用服务器上。微服务采用敏捷扩容和缩容的docker技术来进行自动化部署。
- 服务粒度 SOA强调契约化,内部实现通常是粗粒度的。微服务将就单一职责原则,一般会将整体应用按照业务流程拆分为更细的粒度。
1.3 微服务架构的核心要点和实现原理
微服务的实现原理核心划分一下六个方面:
- 微服务架构中的团队职能划分
- 去中心化的服务治理
- 微服务交互模式:读者容错模式、消费者驱动契约模式和去共享数据模式
- 微服务分解和组合模式:服务代理模式、服务聚合模式、服务串联模式、服务分支模式、服务异步消息模式和服务共享数据模式
- 微服务容错模式:舱壁模式(容器和线程池分组)、熔断模式、限流模式(计数器 令牌桶 信号量等)和失效转移模式
- 微服务划分粒度
- 微服务职能划分讲求专业人做专业事,理论上一个服务需要一个团队去进行开发维护,而现实中不可能按照康威定律去执行的。
- 去中心化 就是尽可能不要去设置中心化管理中心,我们常用的Dubbo和Zookerper则是中心化管理模式,我们如果使用这种模式也要做到服务宕机的降级化处理,比如点对点的hessian远程调用。
- 微服务的交互通常来讲,容错就是我们消费方在消费服务是尽可能获取需要的数据,不要抛出异常,除非完全不能使用;消费者驱动模式就是消费方可以对提供者方提出具体的要求,提供者在对接口进行修改时要遵循此种约束;去数据共享通俗的讲就是不要公用相同数据库和缓存,每个服务需要有自己独立的服务器和缓存。
- 微服务组合模式 中我们最常用也是最应该使用的是服务聚合模式,它将基础服务可以组合成我们需要的服务,并且相比于分支模式,我们的服务调用结构可以更加的清晰明了。
- 微服务的治理我们需要有明确的模式,四种我们常用的模式都是我们需要进行分析和实践进行总结的。限流模式也是在高并发应用中经常使用到的模式。而失效转移模式中使用比较多的是补偿机制。
- 微服务的划分则需要我们根据业务和公司团队配置来进行合理的划分就可以了。
1.4 Java平台微服务架构的项目组织形式
- 通常来讲,我们实际应用中,使用MVC的模式,表现层,服务层和实现层。那么 微服务项目的层级结构 也是类似,表现层打war包,包含服务层和实现层的jar包。
- 微服务工程需要实现自动化的自动部署和持续集成功能,包含:代码管理、自动编译、发布QA、自动化测试、性能测试、准生产环境部署和测试、生产环境部署等。
1.5 服务化管理和治理框架的技术选型
- 服务化管理和治理的 RPC框架使用比较多的是Hessian和Burlap,使用HTTP铜须协议,数据传输使用XML格式,可以跨语言。而相对的RMI框架和 Spring HTTPInvoker框架都不支持语言的跨越,因此使用率比较少。
- 服务化框架 我们最常用的Dubbo框架,提供了高性能的RPC远程服务调用,还提供了基本的服务监控、治理和调度的功能,最近已经开源给Apache。还有诸如淘宝的HSF、Facebook 的Thrift、Apache Web Service下的子项目 AXIS等。
- spring-cloud 目前非常强大的微服务框架系列。基于spring—boot,集成了NetFilx,包含了各大服务组件,如:Eureka、Hystrix、Ribbon、Zuul等。
总结
从传统的单体服务演进到SOA服务化架构,再到高层次的微服务架构,技术上面我们得到了提升和转变。我们总结微服务有如下特点:
- 将传统单体服务拆分成模块化组件的网络服务。
- 按照业务拆分服务,划分服务团队,提升团队作战效率,减少团队沟通成本。并且每一个团队可以独立进行开发运营和部署。
- 微服务讲求合理拆分、分层和构建,需要平台可以持续的进行发布,并进行敏捷开发和部署。
- 微服务常用的设计模式,包含了交互模式、组合模式、容错模式等。
- 微服务的架构选型,现使用spring-cloud系列。
2.彻底解决分布式系统一致性的问题
2.1 什么是一致性
传统的IT行业一致性是强一致性,而在互联网时代,由于请求并发量大,数据量也大的特点,这里的一致性是弱一致性,所谓的如弱一致性就是分布式应用系统之间的一致性和数据的一致性。
2.2 一致性问题
- 下订单和扣库存
保持两者的同时成功或同时失败。
- 同步调用超时
系统A调用系统B超时,得到超时反馈但不知道系统B是否完成了特定功能,无法给予使用方结果。 - 异步回调超时
系统A异步调用系统B,但发生故障导致系统A一直没能收到返回结果,使得两个系统之间的状态不一致。 - 掉单
两个系统处理业务的上下游,但存在一个系统存在处理任务的请求,另外一个系统不存在,出现掉单。 - 系统间状态不一致
与掉单类似,但不同点在于,请求存在与两个系统,但请求的状态不一致。 - 缓存与数据库不一致
讨论缓存与数据库是保持强一致性还是弱一致性。 - 本地缓存节点间不一致
本地缓存的数据如果存在频繁的变更或修改,则在某一时刻各节点间的数据不一致,请求过来后进入了不同的系统,可能出现请求被处理两次的情况。 - 缓存数据结构不一致
存入到缓存中的数据可能没有完全获取,导致缓存中数据接口缺失,在调用接口时可能出现数据接口不一致抛出异常,如NullPointerException等。
2.3 解决一致性问题的模式和思路
- 酸碱平衡理论
主要有三大理论:关系型数据库遵循的ACID理论、分布式事务的CAP理论和CAP解决方案的BASE理论。我们基于BASE理论的软状态原理,可以保持系统状态在一定时间内不需要一直,只需要保证系统状态的最终一致性。这里我们可以解决一致性的第一个问题。- 分布式事务一致性协议
主要有大三协议: 两阶段协议(准备阶段和提交阶段,可能出现阻塞、脑裂、单点故障)、三阶段协议(增加了一个问询阶段,降低了阻塞和不一致的风险)、阿里巴巴的TCC协议(简化的两阶段协议,分为try、confirm、Cancle三个步骤)。- 保证最终一致性的模式
查询模式、补偿模式、异步确保模式 三种模式可以解决一致性问题的2.3问题。
定期校对模式 是通过系统间的全局唯一ID来定期校对主流程系统的操作,进行补偿,可以解决问题4,5。
消息可靠模式 希望我们通过消息队列来进行数据的补偿等操作,要保证消息的可靠性和幂等性。
缓存一致性模式 提出缓存与数据库保持弱一致性,对于缺失数据进行回源而不放入数据库当中。
2.4 超时处理模式
系统的交互目前有三种方式:同步调用、异步调用、消息队列。
- 同步通讯中出现超时一般采用幂等的特性采用查询模式进行重试或者快速失败(一般有两状态和三状态的区别);
- 异步调用超时 通常有三种超时模式:异步调用接口超时和异步调用内部超时与同步三状态一直,采用查询补偿的模式。异步调用回调超时我们一般采用定时重试的机制。
- 消息队列超时 主要分为生产者超时和消费者超时,我们对数据精确度不高的消息采用拿走即消费的模式。而对于需要较高精确度的消息我们采用手动的方式,进行数据库存储和消息消费状态的信息返回。
- 超时补偿原则 分为调用者超时和被调用者超时,调用者超时则是调用者不停的轮询被调用者知道请求成功,后者则是被调用者努力完成任务,知道返回给调用者结果。一般我们处理微信业务的支付回调则是类似的机制。
2.5 迁移开关的设计
常用的迁移设计主要有三种方式:
1.应用层面,直接进行curl调用;
2.配置层面,在系统配置中心直接配置;
3.标记层面,即在服务器接收到请求后将关联实体进行标记,确保数据的一致性。(推荐使用)
总结
介绍了什么是一致性,分为强一致性和弱一致性,又提出了一致性八个问题:下单和减库存、同步调用超时、异步调用超时、掉单、系统状态不一致、缓存与数据库不一致、本地缓存节点不一致和缓存结构不一致的问题。后续提出了解决方案,分为六大模式:查询模式、补偿模式、异步确保模式、定期校验模式、消息可靠模式、缓存一致性模式。又讲解了具体的超时处理模式,从系统间的交互方式做了具体的分析。
3. 服务化系统容量评估与性能保障
3.1 架构设计和非功能质量
我们一般架构设计有分为三个阶段:需求分析与整理 概要设计 详细设计
非功能质量一般包含:高性能、高可用、可伸缩性、可扩展性、安全性、稳定性、健壮性、可测试性、可监控性等。
我们一般对系统架构进行评价使用 互联网架构权衡分析方法(ATAM)。
3.2 全面的非功能质量需求
概要的来讲可以分为 核心需求和非核心需求:
核心需求:高可用、高性能、可伸缩、可扩展、安全性。
非核心需求:可监控性、可测试性、鲁棒性、可重用性、易用性、可维护性。
具体指标一般分为:
系统服务器、缓存、数据库、消息队列。其对应的相关指标可以从部署结构指标、容量和性能指标、其他指标三个方面来进行综合评测。
3.3 典型的技术评审提纲
我们从方案设计时做出的一系列方案和方案对比评估,主要从以下六个方面来进行:
- 现状(业务背景和技术背景)
- 需求(业务需求和性能需求)
- 方案描述(概要、详细说明、性能评估、方案优缺点)
- 方案对比,介绍不同方案的突出点,并做出倾向选择和选择理由
- 风险评估
- 工作量评估
3.4 性能和容量评估经典案例
通过介绍下单时需要的收货地址和物流信息的需求,计算每次请求的量和数据存储以及读取速度等,给出了系统应用层服务器、数据库、缓存、消息队列的最大化方案和最小化方案,也说明了初期可以采用从最小化方案的好处以及可以配置的开关等。
3.5 性能评估参考标准
主要介绍了系统层性能指标和应用层的性能指标,当需要时可以参考指标进行合理的输出。
3.6 性能测试的方案设计与最佳实践
压力测试执行步骤:
1. 确定压测目标。
2. 压测场景设计和压测方案制定
3. 准备测压环境
4. 压测的执行
5. 问题修复和系统优化
3.7 有用的压测工具
- ab
- jmeter
- mysqlslap
- sysbench
- dd
- LoadRunner
- hprof
总结
互联网时代对系统的非功能质量有很高的要求,本章主要就非功能质量的需求做出了相对详细的说明和实践。也列举了我们进行技术评审、性能方案评估、压测流程和相关压测工具的说明实例。
4. 大数据日志系统的构建
日志对于我们来说非常重要,日志根据来源、目标、级别又可以分为很多不同的类型。我们主要常用的有:业务系统应用日志、性能日志、服务远程调用日志等。在使用日志时,我们需要确定好怎么输出日志和怎么存储日志,最后才是怎么使用日志。
4.1 开源日志框架的原理分析和应用实践
讲解了日志框架的逐步升级。从JDK提供的Jdk Logger 到apache提供的Commons Logger,再到apache log4j,再此基础上又进一步改良用异步加载日志方式提升性能使用的Slf4j和Logback,最后到目前结合了Slf4j和Logback的优秀特性的Slf4j2。采用Disrupter的无锁特性,提升了日志的记录性能。
4.2 日志系统的优化与最佳实践
- 开发任务要养成日志记录的习惯;
- 日志级别的设置,线上环境和测试环境等需要有不同的日志级别;
- 日志数量和大小,我们需要在关键路径上设置日志,并且日志的大小要尽可能的小,但要全;
- 日志的分割,尽量使用日志框架原生的滚动追加方式;
- 日志的格式,注意的是使用‘ %L ’的情况,可能对系统性能有一定的影响。
4.3 大数据日志系统的架构与设计
大数据日志系统一般我们在每台服务器上添加日志采集器,通过采集器监控日志,如果产生日志则将日志文件存入到缓冲队列,通过日志解析器进行解析,一般我们将数据解析成JSON格式的数据后存储到有序的储存系统中并简历索引。
- 日志采集器目前最流行的是Logstash和fluentd。都广泛的被社区和开发者使用,两者在处理性能上没有很大的差别。
- 日志缓冲队列,我们通常采用的消息队列比如Kafka、redis、RabbitMq等。推荐使用性能最好的Kafka。
- 日志解析器,可以才用Logstash和Fluentd当做解析器,也可以使用更加专业storm和spark作为解析器。
- 日志储存和搜索引擎,一般采用比较常规和好用的Elasticsearch和Solr等。注意对日志要做定期的清理。
- 日志的展示系统,一般在自身的服务器或者手机APP上建立体统的展示。
- 监控和报警,日志存储到系统和搜索引擎中我们可以简历监控和报警系统,保证服务的稳定运行。
- 日志系统的容量和性能评估,可以根据第三节的知识点计算相应的峰值等参数信息进行储存设备和服务引擎等的配置。
4.4 ELK系统的构建与设计
Elk 系统主要由三大模块组成:Elasticsearch、Logstash、Kibana。这里只是简单的讲解了三个框架的使用,我们再具体使用时还需要自己不断深入。
总结
我们做微服务要注重日志的记录,有了日志不仅可以快速定位问题的所在,也可以根据日志进行服务监测和数据分析,我们一般系统常用的slf4j2等高性能框架可以简单的提供一系列日志,但是在分布式服务的情况下,搭建一个高性能高可用的大数据日志系统是非常有必要的,我们可以采用ELK的日志框架模式构建自身系统相符的日志系统。
5. 基于调用链的服务治理系统设计与实现
- 我们在做了常规的日志系统以后,往往还要面临线上突发紧急情况的处理,这个时候去一个个排场系统会显得特别麻烦,因此,我们通常会使用APM(应用性能服务)系统进行监控。目前比较流行的开源APM系统主要有:Pinpoint、Zipkin、CAT。商用版本的系统有:听云、博睿、oneAPM、云智慧。
- 对于调用链最早出现在谷歌的Dapper论文上,它提出在应用层增加标记来对服务化中的请求和响应建立联系。我们一般采用在HTTP请求头中设置标记信息:系统调用的全局流水ID(traceID)、服务节点的spanID与parentSpanID,通过他们构成一条业务链上的标记。
- 调用链的设计和实现与我们设置日志系统没有太大的区别,只是我们在消息进行采集和处理时需要添加标识信息。
6.java服务的线上应急和技术攻关
- 线上的急性问题我们需要有一下原则:
- 第一时间回复系统我不是彻底解决,达到快速止损;
- 有明显的资金损失时,第一时间升级系统,达到快速止损;
- 应急指挥围绕应急目标启动应急流程和快速止损方案;
- 不能短时间解决问题,进行升级处理;
- 在不影响用户体验的前提下,保留部分现场和数据。
- 分析问题从以下几个方面考虑:
- 问题系统最近是否进行了上线;
- 依赖的资源或基础平台最近是否进行了升级或上线;
- 依赖的系统是否进行了上线;
- 运营是否在系统里面做过运营变更;
- 网络是否有波动;
- 最近的业务是否上量;
- 服务的使用方是否有促销活动等。