微服务的主要功能是根据业务分为子服务,实现功能耦合,每个微服务提供单个业务功能服务,履行自己的职责,从技术角度是一个灵活独立的单元,可以单独启动和关闭,一般每个服务都有自己的数据库模块。
在传统的IT行业中,大多数软件都堆积在各种独立的系统中。综上所述,这些系统的问题是可扩展性差、可靠性低、维护成本高。后来引入了SOA服务,但是,因为 SOA 总线模式早期采用,与某种技术栈强绑定,如J2EE。这使得许多企业的遗留系统难以对接,切换时间过长,成本过高,新系统稳定性的收敛也需要一些时间。最终 SOA 在一些中小企业的场景中变得非常笨重是不合适的。
11.1 微服务和单体架构的区别单体架构的所有模块都耦合在一起,代码量大,维护困难。每个微服务模块相当于一个单独的项目,代码量显著减少,问题相对容易解决。 单体架构的所有模块都共享一个数据库,存储模式相对单一。每个模块都可以使用不同的存储模式(例如,有些使用redis,有些使用mysql等)。数据库也是一个对应于自己数据库的单个模块。 单体架构所有模块开发所使用的技术都是一样的,微服务每个模块都可以使用不同的开发技术,开发模式更灵活。
21.2 微服务和SOA的区别从本质意义上说,微服务仍然是 SOA 架构。但内涵不同,微服务不绑定特殊技术,在微服务系统中,可以有 Java 也可以提供编写服务 Python编写的服务由Restful架构风格统一为系统。因此,微服务本身与具体技术的实现无关,具有很强的可扩展性。
Part22.微服务的特点微服务的主要作用是实现一套基础设施系统,使各服务之间的松耦合,并在功能上表现为一个统一的整体。这种所谓的“统一整体”表现为界面、权限管理、安全策略、在线流程、日志和审计方法、调度方法和访问入口等。
32.1 微服务设计原则单一职责原则 每个微服务只需要实现自己的业务逻辑,比如教学模块,它只需要处理与教学相关的业务逻辑,其他内容可以拆分;
服务自治的原则 各微服务在开发、测试、发布、运维等方面都是独立的,其存储数据库也是分开的,减少了各自的依赖;
轻量级通信原则 首先,相互交流的语言非常轻,其次,交流方式需要跨语言和平台,使每个微服务都有足够的独立性,不受技术限制。通常的方法是通过REST 通信API或RPC;
界面明确原则 一般来说,微服务之间会有呼叫关系。为了避免微服务界面的变化,导致其他微服务移动全身,在设计开始时应考虑常用情况,使界面尽可能通用、灵活,尽量避免大规模变化。
42.2 客户端访问服务为了与服务沟通,客户端需要记住这些服务,包括离线/更新/升级服务,重新部署端,客户端也在维护和发布,这需要统一的管理。此外,每个服务的呼叫也需要一定的网络费用。一般来说,微服务通常在系统内无状态,用户登录信息和权限管理最好有统一的地方维护管理。
因此,后台服务和UI之间通常会有代理或API Gateway,其作用如下:
为前台提供统一的服务入口,使微服务透明 聚合后台服务,节省流量,提高性能 API管理功能,如安全、过滤、限流等
52.3 API网关API网关是将所有API调用到API网关层,具有网关层的统一访问和输出。网关的基本功能包括:统一访问、安全保护、协议适应、流量控制、长度链接支持、容错能力。通过网关后,每个API服务提供团队都可以专注于自己的业务逻辑处理,而API网关更关注安全、流量、路由等问题。
Chris Richardson 把它放在他的博客里 API 网关分为以下两种:单节点 API 网关、Backends for frontends 网关。
流行的开源API网关组件: Tyk:基于golang语言开发的开放源码API网关Tyk。Tyk提供API管理平台,包括API网关、API分析、开发人员门户和API管理面板。 Kong:Kong是一个可扩展的开放源码API Layer(又称API网关或API中间件)。Kong 可在任何RESTful中使用 通过插件扩展,API提供了超越核心平台的额外功能和服务。 zuul:提供边缘服务,具有动态路由、监控、弹性、安全等功能。基于JVM路由和服务端的负载均衡器,Zuul是Netflix生产的。
过滤器filter是整个Zuul的核心,分为前置过滤器(pre filter)、路由过滤器(routing filter)、后置过滤器(post filter)以及 错误过滤器(error filter)。当一个请求来临时,所有的请求都将首先执行 pre filter,然后通过 routing filter 将请求转发给后端服务。响应后端服务的结果,然后执行 post filter,最后,对客户端做出反应。不同的逻辑可以在不同的filter中执行,如安全检查、日志记录等。
Part33,服务调用同步调用和异步调用通信通常分为两种方式。
63.1 同步远程过程调用(Remote Procedure Invocation)通过远程调用直接访问其他service。示例 REST、gRPC、Apache、Thrift、RPCX等。
一般来说,同步调用相对简单,可以满足较强的一致性,但在调用层次较多时,性能容易出现问题,性能体验相对较差。RESTful和RPC各有优势。一般来说,基于HTTP的REST更容易跨客户端实现,服务端实现的技术更灵活,只要包装HTTP的SDK可以调用,使用范围更广;RPC的优点是传输协议更高效、安全可控,特别是公司有统一的开发规范和服务框架,具有更明显的开发效率优势。
73.2 异步使用异步信息进行通信,服务室通过信息管道交换信息,以完成通信。支持通知、请求/异步响应、发布/订阅、发布/异步响应等多种通信机制。Kafka很常见、RabbitMQ、RocketMQ等。
异步信息的呼叫在分布式系统中也起着重要的作用。它不仅可以减少服务之间的耦合,还可以缓冲信息,减少积压的影响。同时,它可以确保呼叫人的服务异步体验,专注于不受干扰的任务。然而,问题是数据的最终一致性;另一个是后台服务通常需要实现功率等级。考虑到消息发送的性能通常是重复的(通常只接收一次),需要制定相应的推送和消费策略。
Part44,服务发现Zookeeper作为服务注册中心,保证了CP,即高可用性和实时更新。在向注册中心查询服务列表时,一般可以容忍注册中心在几分钟前返回注册信息,但不能直接接受服务。也就是说,服务注册功能对可用性的要求高于一致性。但zk会出现这样的情况,当master节点因网络故障与其他节点失去联系时,剩余节点将重新选举leader。问题是选举leader的时间长达30~120s,选举期间整个zk集群不可用,导致选举期间注册服务瘫痪。在云部署的环境中,由于网络问题,zk集群失去master节点的可能性很大。虽然服务可以最终恢复,但由于选举时间长而导致的长期注册是不可容忍的。
通过ZK(zookeeper)对服务注册信息进行分布式管理。当 服务上线时,服务提供商将自己的服务信息注册到ZK,并通过心跳保持长链接,实时更新链接信息。根据定制算法,服务调用者可以通过ZK搜索地址,找到服务,并在本地缓存服务信息以提高性能。当服务离线时,ZK会向服务客户发送通知。 其他可以作为服务注册中心的有: etcd:可用性高,分布式高,一致性强,key-value,Kubernetes和Cloud Foundry都使用etcdry; consul:discovering和configuring的工具。它提供API,允许客户注册和发现服务。为了确定服务的可用性,Consul可以进行服务健康检查。
Part55,服务容错分布式服务的特点是网络不可靠。这种风险可以通过微服务的拆分来降低。如果没有特别的保证,可能会造成非常严重的后果。当系统由一系列服务呼叫链组成时,必须确保任何环节的问题都不会影响整个链路。挂断处理服务的方法有很多:
隔离 超时重试 限流 熔断机制 降级(本地缓存)
85.1 容错机制1 隔离它是指按照一定的规则将系统划分为几个服务模块,相对独立,没有强烈的依赖性。当出现故障时,问题和影响可以在不扩散风险、不涉及其他模块或整体系统服务的情况下与模块内部隔离。常见的隔离方法有:线程池隔离和信号量隔离。
2 超时重试加班和重试机制也是一种容错的方法,任何发生RPC调用的地方,如读取redis,db,mq等,由于网络故障或所依赖的服务故障,长时间无法返回结果,会导致线程增加,cpu负载增加,甚至雪崩。当上游服务呼叫下游服务时,设定最大响应时间。如果超过此时间,下游没有响应,请求断开并释放线程。
3 限流限流是指限制系统的输入输出流量已达到保护系统的目的。为了确保系统的稳定运行,一旦达到限制阈值,就需要限制流量,并采取少量措施来完成限制流量的目的。 限流方式有:计数器、令牌桶、信号量(漏桶)等。
4 熔断在互联网系统中,由于访问压力过大,当前的下游服务响应缓慢或失败。为了保护系统的整体可用性,上游服务可以暂时切断下游服务的呼叫。这种牺牲局部、保全的措施称为熔断。熔断器一般有三种状态: 熔断关闭状态:当服务无故障时,熔断器的状态对调用方的调用没有限制。 熔断开启状态:服务接口的后续调用不再通过网络,直接执行本地fallback方法。 半熔断状态:尝试恢复服务呼叫,允许有限的流量呼叫服务,并监控呼叫成功率。如果成功率达到预期,则表明服务已恢复并进入熔断器关闭状态。若成功率很低,则再次进入熔断关闭状态。
5 降级降级实际上是为服务提供一个支持方案,一旦服务不能正常调用,就是使用支持方案。
95.2 常见的容错组件Hystrix是Netflix开源的延迟和容错库,用于隔离访问远程系统、服务或第三方库,防止级联失败,从而提高系统的可用性和容错性。 Resilience4J是一种轻量级、简单、清晰、丰富的熔断工具,也是Hystrix官方推荐的替代品。不仅如此,Resilience4J还原支持Springboot,监控还支持与prometheus等多种主流产品的整合。 Sentinel是阿里巴巴开源的断路器,已经在阿里内部大规模采用,非常稳定。
Part66常见的负载平衡策略
106.1 随机来自网络的请求被随机分配给内部的多个服务器,理想情况下,每台机器的请求次数基本相同。
116.2 轮询每个来自网络的请求轮流分配给内部服务器,从1到N,然后重新开始。该负载平衡算法适用于服务器组内的服务器配置相同,平均服务请求相对平衡。
126.3 加权轮询根据服务器的不同处理能力,将不同的权值分配给每个服务器,使其能够接受相应的权值服务请求。例如,服务器A、B、C的权值分别设计为1、3、6.服务器A、B、C将分别接收10%、30%、60%服务请求。这种平衡算法可以保证高性能服务器的利用率更高,避免低性能服务器过载。
136.4 IP Hash通过生成要求源IP的哈希值,并通过哈希值找到正确的真实服务器。这意味着对应于同一主机的服务器总是相同的。不需要保存任何源IP,但请注意,这可能会导致服务器负载不平衡。
146.5 最少连接数客户端的每个请求在服务器上的停留时间可能会有很大的差异。随着工作时间的延长,如果采用循环或随机平衡算法,每个服务器上的连接过程可能会有很大的差异,没有达到真正的负载平衡。至少连接数平衡法记录了每个需要内部负载的服务器的数据,记录了服务器目前正在处理的连接数量。当有新的服务连接请求时,将当前请求分配给连接最少的服务器,使负载更加平衡。
Part77.监控微服务监控的一般做法是让每个组件提供报告其当前状态的接口(metrics接口),这个接口输出的数据格式应该是一致的。 然后部署指标采集器组件,定期从这些接口获取并保持组件状态,并提供查询服务。最后,需要一个UI,从指标采集器中查询各种指标,绘制监控界面或根据阈值发出报警。 网络上有许多开源组件。Redisexporter和MySQLexporter分别提供Redis缓存和MySQL数据库的指标接口,而微服务则根据每个服务的业务逻辑实现自定义的指标接口,然后使用Prometheus作为指标收集器,Grafana配备监控界面和电子邮件报警。建立了这样一套微服务监控系统。
157.1 常见的监控组件Prometheus Promethes是2012年开源的监控框架,其本质是由谷歌前员工开发的时间序列数据库。 它采用拉模式(Pull)从应用程序中提取数据并支持 Alert 该模块可以实现监控和预警。性能很强,单机可以消耗百万级时间序列。 一些定时任务模块是周期性运行的,不能通过拉来获取数据,Prometheus 它还提供了一种推数据的方式,但不是推送到Prometheus 在Server中,中间建一个 Pushgateway,定时任务模块将metrics信息推送到Pushgateway,然后Prometheuss Server仍然使用拉法从Pushgateway中获取数据。
openTSDB OpentSDB采用Hbase分布式存储,其获取数据的模式不同于Prometheus,采用推模式(Push)。 OpentSDB在显示层中有自己的WebUI视图,也可以很好地与Grafana集成,提供丰富的显示界面。 但OpentSDB没有自己的预警模块,需要自行开发或与第三方组件结合使用。
InfluxDB是2013年开源的时序数据库,主要用于监控系统方案。它还采用推模式收集数据(Push)。在显示层,InfluxDB也有自己的WebUI,也可以与Grafana集成。
Part88,链路跟踪在微服务架构中,服务之间有许多呼叫关系。为了更好地定位问题,有必要记录服务呼叫的内部接口以及产生了多少呼叫,即链路跟踪。 链路跟踪记录就像一棵树,每次服务调用都会在HTTPHEADERS中记录至少四个数据:
traceId:traceid识别用户要求的调用链路,具有相同traceid的调用属于相同的链路; spanId:识别服务调用的ID,即链路跟踪的节点ID; parentId:父节点spanid; requestTime 和 responseTime:请求时间和响应时间。 目前业内流行的链路跟踪系统,如Twitter的Zipkin、阿里的鹰眼、美团的Mtrace、大众点评的cat等。,大部分都是基于谷歌发表的Dapper。Dapper阐述了分布式系统的技术细节,特别是微服务架构中的链路跟踪概念、数据表示、埋点、传输、收集、存储和显示。