服务拆分
微服务架构最核心的是 服务之间的松耦合性
服务根据业务功能进行拆分
拆分的难点:
网络延迟
同步进程间通信导致可用性降低
在服务之间维持数据一致性
获取一致的数据视图
上帝类阻碍了拆分
服务之间的相互调度
消息队列
应用场景
- 异步处理,例如用户注册时,需要的发送短信和邮件验证处理;
- 应用解耦,例如订单系统与库存系统的解耦;
- 流量消峰,例如在用户流量太大时,排队。
高级用法:
1 高级用法-工作队列
如果多个consumer连接相同queue,那么从队列到消费者的消息分发是负载均衡的,也就是说第一个是程序1收到,第二个是程序2收到,以此类推。
通过增加consumer的数量,即可实现工作队列机制,实现任务的并行处理。
2 高级用法-微服务架构
整个应用采用一个broker消息中介,每个微服务对应一个队列,并在同一个微服务的不同实例间负载均衡,从而实现不同服务之间的解耦。
3 高级用法-事件总线
通过消息队列实现事件总线,并基于事件和状态构建微服务和工作队列的调度与执行机制,实现通用的工作流系统。
数据库设计
根据具体的微服务要求 设计 不同的数据库方案
读写分离,集群。
降低服务故障发生的可能性手段?
监控系统按照原理分为三大类:
日志类Log
调用链路类Tracing
度量类Metrics
日志类比较常见,我们的框架代码、系统环境、以及业务逻辑中一般都会产出一些日志,这些日志我们通常把它记录后统一收集起来,方便在需要的时候进行查询。
日志类记录的信息一般是一些事件、非结构化的一些文本内容。日志的输出和处理的解决方案比较多,大家熟知的有 ELK Stack 方案(Elasticseach + Logstash + Kibana)
上述方案,还可升级,在beats日志客户端收集器后面插入 redis数据库,或者消息队列Kafka。
调用链类监控主要是指记录一个请求的全部流程。一个请求从开始进入,在微服务中调用不同的服务节点后,再返回给客户端,在这个过程中通过调用链参数来追寻全链路行为。通过这个方式可以很方便的知道请求在哪个环节出了故障,系统的瓶颈在哪儿。
这一类的监控一般采用 CAT 工具 来完成,一般在大中型项目较多用到。
度量类主要采用 时序数据库 的解决方案。它是以事件发生时间以及当前数值的角度来记录的监控信息,是可以聚合运算的,用于查看一些指标数据和指标趋势,比如数据库的硬盘资源使用率。所以这类监控主要不是用来查问题的,主要是用来看趋势的。
Metrics一般有5种基本的度量类型:Gauges(度量)、Counters(计数器)、 Histograms(直方图)、 Meters(TPS计算器)、Timers(计时器)。
基于时间序列数据库的监控系统是非常适合做监控告警使用的,所以现在也比较流行这个方案。
一般我们做「监控系统」都是需要做分层式监控的,也就是说将我们要监控的对象进行分层,一般主要分为:
-
系统层:系统层主要是指CPU、磁盘、内存、网络等服务器层面的监控,这些一般也是运维同学比较关注的对象。
-
应用层:应用层指的是服务角度的监控,比如接口、框架、某个服务的健康状态等,一般是服务开发或框架开发人员关注的对象。
-
用户层:这一层主要是与用户、与业务相关的一些监控,属于功能层面的,大多数是项目经理或产品经理会比较关注的对象。
监控的指标一般有哪些:
-
延迟时间:主要是响应一个请求所消耗的延迟,比如某接口的HTTP请求平均响应时间为100ms。
-
请求量:是指系统的容量吞吐能力,例如每秒处理多少次请求(QPS)作为指标。
-
错误率:主要是用来监控错误发生的比例,比如将某接口一段时间内调用时失败的比例作为指标。
网关
保护内部服务而设计的一道屏障,可以提供高性能、高可用的 API托管服务
统一管理服务单元向外提供服务的接口
功能: 路由转发,负载均衡,安全认证,日志记录,数据转换
常用的开源方案:Zuul, Tyk , Kong
粒度问题:
粗粒度,外部访问服务层要 通过 网关 ; 细粒度,外部访问服务层 和 服务层 之间 不同服务单元的访问 都 需要通过 网关;混合使用,不同的服务按区域 划分,同一个区域的服务单元直接调用,不同区域的服务单元要通过 网关。
降低故障的影响
服务发现
服务实例的网络地址是动态分配的。而且,由于自动扩展,失败和更新,服务实例的配置也经常变化。这样一来,客户端代码需要一套更精细的服务发现机制。
有两种主要的服务发现模式:客户端服务发现(client-side discovery)和 服务器端服务发现(server-side discovery)。
客户端服务发现
当使用客户端服务发现的时候,客户端负责决定可用的服务实例的网络地址,以及围绕他们的负载均衡。客户端向服务注册表(service registry)发送一个请求,服务注册表是一个可用服务实例的数据库。客户端使用一个负载均衡算法,去选择一个可用的服务实例,来响应这个请求。
一个服务实例被启动时,它的网络地址会被写到注册表上;当服务实例终止时,再从注册表中删除。这个服务实例的注册表通过心跳机制动态刷新。
客户端的服务发现模式有优势也有缺点。这种模式相对直接,但是除了服务注册表,没有其它动态的部分了。而且,由于客户端知道可用的服务实例,可以做到智能的,应用明确的负载均衡决策,比如一直用hash算法。这种模式的一个重大缺陷在于,客户端和服务注册表是逻辑耦合,必须为服务客户端用到的每一种编程语言和框架实现客户端服务发现逻辑。
服务端发现
客户端通过负载均衡器向一个服务发送请求,这个负载均衡器会查询服务注册表,并将请求路由到可用的服务实例上。通过负载均衡服务器的服务发现,服务实例在服务注册表上被注册和注销。
服务器端服务发现模式也是优势和缺陷并存。最大的好处在于服务发现的细节被从客户端中抽象出来,客户端只需要向负载均衡器发送请求,不需要为服务客户端使用的每一种语言和框架,实现服务发现逻辑;另外,这种模式也有一些问题,除非这个负载均衡器是由部署环境提供的,又是另一个需要启动和管理的高可用的系统组件。
服务注册
服务注册表是服务发现的关键部分,是一个包含了服务实例的网络地址的数据库,必须是高可用和最新的。客户端可以缓存从服务注册表处获得的网络地址。但是,这些信息最终会失效,客户端会找不到服务实例。所以,服务注册表由一个服务器集群组成,通过应用协议来保持一致性。
自注册模式
在self-registration模式中,服务实例负责从服务注册表中注册和注销。如果需要的话,一个服务实例发送心跳请求防止注册过期。下图展示了这种模式的架构:
第三方注册
在third-party registration模式中,服务实例不会自己在服务注册表中注册,由另一个系统组件service registrar负责。service registrar通过轮询部署环境或订阅事件去跟踪运行中的实例的变化。当它注意到一个新的可用的服务实例时,就会到注册表中去注册。service registrar也会将停止的服务实例注销。
服务熔断,服务降级,限流
服务熔断和服务降级的区别:
- 触发原因不太一样,服务熔断一般是某个服务(下游服务)故障引起,而服务降级一般是从整体负荷考虑;
- 管理目标的层次不太一样,熔断其实是一个框架级的处理,每个微服务都需要(无层级之分),而降级一般需要对业务有层级之分(比如降级一般是从最外围服务开始)
- 实现的手段也不一样
熔断机制
熔断机制是应对雪崩效应的一种微服务链路保护机制。
在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整体的可用性,可以暂时切断对下游服务的调用。
这种牺牲局部,保全整体的措施就叫做熔断
1. 开启熔断
在固定时间窗口内,接口调用超时比率达到一个阈值,会开启熔断。
进入熔断状态后,后续对该服务接口的调用不再经过网络,直接执行本地的默认方法,达到服务降级的效果。
2. 熔断恢复
熔断不可能是永久的。
当经过了规定时间之后,服务将从熔断状态回复过来,再次接受调用方的远程调用。
服务间调用的实现方式:
远程接口RPC
事件驱动,即发消息形式,分为两种实现,一种是 事件通知,一种是 事件溯源。
事件通知就是微服务之间不直接调用,而是通过发消息来进行合作。
事件溯源有点像记账,它把所有的事件都记录下来,作为永久存储层,再在它的基础之上构建应用程序。
服务降级
当整个微服务架构整体的负载超出了预设的上限阈值或即将到来的流量预计将会超过预设的阈值时,为了保证重要或基本的服务能正常运行,我们可以将一些 不重要 或 不紧急 的服务或任务进行服务的 延迟使用 或 暂停使用。
服务降级实现手段:服务关闭,服务拒绝
核心设计:
设置一个分布式开关,用于实现服务的降级,然后集中式管理开关配置信息即可。手段是一个配置中心
自动降级:超时降级,失败次数降级,故障降级,限流降级等
测试
端到端测试
服务测试
单元测试
落地技术 | |
---|---|
服务网光,API路由 | Zuul等 |
服务注册发现 | Eurka,Consul,Zookeeper等 |
服务配置与管理 | Netflix公司的Archaius,阿里的DIamond等 |
全链路追踪 | Zipkin,Brave,Dapper等 |
服务调用 | Rest(微服务通信),RPC(Dubbo),gRPC |
服务配置中心管理 | SpringCloudConfig,Chef,淘宝的diamond、百度的disconf等 |
服务监控 | Zabbix,Nagios,Metrics,Spectator等 |
服务熔断器 | Hystrix,Envoy等 |
负载均衡 | Nginx,Ribbon等 |
服务接口调用 | Feign等 |
服务部署 | Docker,OpenStack,Kubernetes等 |
数据流操作开发包 | SpringCloud Stream(封装与Redis,Rabbit,kafka等发送接收消息) |
消息队列 | kafka,RabbitMQ,ActiveMQ等 |
时间消息总线 |
另一种微服务架构
Service Mesh
服务间通信的基础设施层。
目前社区Service Mesh的开源解决方案有:Buoyant 公司推出的 Linkerd 和 Google、IBM 等厂商牵头的 Istio。