微服务-Summary
注册中心
在Spring微服务架构中,服务注册中心用于管理和发现服务实例。
Eureka:最常用的注册中心,AP模型。
- 70%的市场占有率
- 虽然2.0的官方版本停止维护了,但是1.X的社区版本还在不停的维护。
ZooKeeper:通常配合Dubbo使用,CP模型。还可用于分布式锁和分布式配置。
- CP模型并不适合服务发现,后期阿里也意识到了错误,推出了Nacos。
Kubernetes (K8s) 内置的服务发现机制:通过Kubernetes Service管理微服务实例的注册与发现。与容器编排和管理紧密结合,天然适用于容器化环境。缺点是复杂性较高,需要搭建Kubernetes集群。
特性 | Eureka | ZooKeeper | Nacos |
---|---|---|---|
开发公司 | Netflix | Apache 基金会 | 阿里巴巴 |
CAP | AP(可用性和分区容忍性) | CP(一致性和分区容忍性) | 既支持 AP,也支持 CP |
功能 | 服务注册与发现 | 分布式协调、配置管理、分布式锁 | 服务注册与发现、配置管理、服务管理 |
定位 | 适用于构建基于 HTTP 的微服务架构 | 通用的分布式协调服务框架 | 适用于微服务和云原生应用 |
访问协议 | HTTP | TCP | HTTP/DNS |
自我保护 | 支持 | - | 支持 |
数据存储 | 内嵌数据库、多个实例形成集群 | ACID 特性的分布式文件系统 ZAB 协议 | 内嵌数据库、MySQL 等 |
健康检查 | Client Beat | Keep Alive | TCP/HTTP/MYSQL/Client Beat |
特点 | 简单易用、自我保护机制 | 高性能、强一致性 | 动态配置管理、流量管理、灰度发布等 |
CAP定理(CAP Theorem)
在分布式系统中有三个指标,它们不可能同时做到,这个结论就叫做 CAP 定理。
- 一致性(Consistency):要求所有服务之间的数据保持一致。例如在A服务修改数据,那么在B服务也能要能查询到。
- 可用性(Availability):要求对每一个请求做出响应,即使某些服务的数据不是最新。
- 分区容错性(Partition Tolerance):要求不同区间的服务因为网络故障无法通信时,它们各自也能继续提供服务。
为什么P总是成立?
例如华南1区和华南2区的服务器,当出现网络分区(网络延迟、丢包)时,它们之间可能无法相互通信。这在分布式系统中几乎是不可避免的。所以P总是成立。
而在服务之间无法互相通信的情况下,还要继续提供服务,那么A和C就只能二选一。
为什么CAP只能达到 CP 或者 AP?
在出现分区容错即服务之间无法互相通信的情况下:
CP:为了保证数据一致性,在服务会停止响应(即可用性不成立)
AP:为了保证及时响应,即使数据不是最新也会返回(即一致性不成立)
Eureka工作流程
自我注册:服务启动时会向 Eureka Server 注册自己的信息(如服务ID、IP地址、端口、状态等),Eureka Server 会维护一个服务注册表。
心跳机制:注册后的服务实例会定期发送心跳(Heartbeat)请求给 Eureka Server,表示自己还处于健康状态。如果心跳超时,Eureka Server 会将该实例标记为不可用,并从服务列表中移除,下线实例。
服务发现:客户端从 Eureka Server 拉取(pull)服务注册表,缓存本地。服务消费者可以通过服务ID从注册表中找到所需服务的实例列表,然后选择一个实例进行调用。
Zookeeper注册中心的实现
- 服务注册:通过在目录树中下创建临时节点实现。创建一个临时节点(例如
/services/app1
),通常以服务的 IP 和端口作为节点名称(例如/services/app1/192.168.1.100:8080
),当服务实例宕机或失去与 Zookeeper 的连接时,临时节点会自动被删除。 - 服务发现:客户端读取这些临时节点,获取对应实例的IP和端口,再进行调用。
- Zookeeper 提供了 Watcher 机制,客户端可以对某个节点设置 Watcher。当节点的子节点发生变化时(例如有新的服务实例注册或某个实例下线),Zookeeper 会通知客户端,客户端可以通过重新读取节点数据来获取最新的服务实例列表。
Kubernetes (K8s) 内置的服务发现
Kubernetes 的服务发现机制是内置的,不需要额外的服务注册中心。
服务对象(Service):在 Kubernetes 中,每个服务(Service)对象对应一组 Pod。Service 对象有一个固定的虚拟 IP 地址和端口,外部用户通过这个 IP 地址可以访问后端的 Pod,而 Pod 的 IP 是动态的,随时可能变化。
DNS 方式服务发现:Kubernetes 内部提供了一个 DNS 服务,所有 Service 都会被注册到 DNS 中,客户端可以通过服务名称直接解析出服务的 IP 地址和端口。例如,客户端可以通过 my-service.my-namespace.svc.cluster.local 访问服务,而不需要关心服务的 IP 地址变化。
环境变量方式服务发现:当某个 Pod 启动时,Kubernetes 会将集群中所有已存在的服务信息以环境变量的形式注入到 Pod 中。这样,Pod 内的应用程序可以通过读取环境变量获取服务的 IP 和端口。
Endpoints 对象:每个 Service 对象在 Kubernetes 中有一个 Endpoints 对象,记录了与该 Service 关联的所有 Pod 的 IP 地址。当有新的 Pod 启动或停止时,Endpoints 对象会自动更新,保持服务的最新状态。
分布式链路追踪
分布式链路追踪(Distributed Tracing)是一种用于追踪和监控分布式系统中跨服务请求的技术。它通过生成唯一的跟踪标识(Trace ID)来记录和关联从一个服务开始、经过多个服务到达结束点的整个请求流程。在每个服务中,进一步将请求处理的不同步骤标记为单独的跨度(Span),并记录其详细信息,如开始时间、结束时间、调用的服务等。通过这些信息,开发人员可以获取系统中请求的完整路径和执行详情。
在分布式系统架构中(如微服务架构),一个请求通常需要经过多个服务和组件处理,单独查看每个服务的日志难以了解整个请求的全貌,分布式链路追踪就解决了这一问题。
主要用来监控请求在分布式系统中的调用链。
一个完整请求链路的追踪ID(traceid)用于查出本次请求调用的所有服务,每一次服务调用的跨度ID(spanid)用来记录调用顺序
实际应用:
错误追踪: 当系统出现故障时,能够快速定位到哪个服务或接口出现了问题。
性能分析: 通过链路追踪,识别系统中的性能瓶颈,尤其是在请求链路中找出耗时较长的服务调用。
Spring Cloud Sleuth + Zipkin
- Spring Cloud Sleuth: 它是 Spring Cloud 生态中的链路追踪组件,负责在微服务中自动生成和传播
Trace ID
和Span ID
,并收集追踪数据。 - Zipkin: 分布式追踪系统,用于收集和存储来自各个微服务的追踪数据,并提供可视化界面查看请求链路。
- 代码入侵性强
SkyWalking
- SkyWalking: 一个集成了链路追踪、应用性能监控(APM)和日志分析的全栈监控平台。它可以追踪多种协议(HTTP、gRPC 等)下的微服务调用,同时还能监控 JVM 性能指标、分析日志并生成告警信息。
- 全栈监控: 除了链路追踪,SkyWalking 还能监控服务的性能指标(如 JVM、GC、内存使用等)和异常告警。
- 探针(Agent)集成: SkyWalking 通过字节码增强技术(Java Agent)在运行时动态修改应用程序的字节码,从而在不修改代码的情况下自动插入追踪逻辑。应用启动时,只需配置 SkyWalking Agent,不需要像 Sleuth 那样显式集成库依赖。
分布式配置中心的解决方案
传统系统中,每个服务都有独立的配置文件,随着微服务的数量和环境的复杂度增加,配置管理变得更加繁琐且容易出错。分布式配置中心通过将所有服务的配置信息集中存储和管理,提供动态更新、版本控制等功能,从而提升配置管理的效率和一致性。
配置中心的典型工作流程是:
- 服务启动时从配置中心拉取配置。
- 配置中心支持动态推送更新的配置到服务中,避免服务重启。
- 通过不同的环境隔离(如开发、测试、生产),对不同的环境进行专门的配置管理。
Spring Cloud Config
Spring Cloud Config 是一种集中化的配置管理工具,支持从Git、SVN等版本控制系统中拉取配置,并提供加密、解密功能。它可以结合Spring Cloud Bus使用,实现配置的动态刷新。
- 优点:与Spring Cloud体系无缝集成,支持多环境配置,并提供配置的版本管理。
- 缺点:依赖于外部的版本控制系统,且更新配置时需要显式调用刷新操作。
Apollo(携程开源)
Apollo是携程开源的分布式配置中心,支持实时推送配置变更,具有较好的权限管理和多环境隔离能力。Apollo采用客户端与服务端结合的模式,服务端负责管理配置,客户端通过远程接口获取配置并支持自动更新。
- 优点:支持多语言、多集群配置,提供良好的可视化管理界面和权限控制。
- 缺点:部署和维护相对复杂。
Kubernetes中的ConfigMap
在Kubernetes中,ConfigMap 是一种用于存储非机密配置数据的对象,它允许你将应用程序所需的配置数据从容器镜像中解耦。
其主要功能是将配置数据传递给Pod,以便应用程序能够根据环境的变化灵活调整。
环境变量:ConfigMap可以为Pod设置环境变量,将配置信息以环境变量的方式注入到容器中。
配置文件:可以将ConfigMap中的数据挂载到容器的文件系统中,作为配置文件供应用程序读取。
- 配合SpringBoot Actuator暴露/refresh接口 + @RefreshScope注解实现不停机更新配置
命令行参数:通过ConfigMap,将配置信息以命令行参数的形式传递给应用程序。
限流和熔断
Hystrix
Hystrix 是一个由 Netflix 开源的库,用于实现服务容错、延迟和故障处理,尤其是在微服务架构中。它主要用于防止级联故障,提高系统的弹性。
作用:
- 断路器:Hystrix 实现了断路器模式,当某个服务的调用失败超过预设的阈值时,Hystrix 会迅速切断对该服务的调用,返回默认值,从而避免系统受到影响。
- 隔离:通过将服务调用隔离在不同的线程池中,防止某个服务的性能问题影响到其他服务。
- 限流:可以设置请求的最大并发数和排队等待的请求数,限制系统负载。
- 监控与指标:Hystrix 提供监控功能,能够实时跟踪服务调用的性能、成功率、失败率等指标,帮助开发人员了解系统状态。
Sentinel
Sentinel 是阿里巴巴开源的流量控制和熔断降级组件,专为微服务架构设计,旨在提高分布式系统的稳定性和可用性。
作用:
- 流量控制:通过定义流量控制规则,可以限制进入服务的请求数量,防止服务被突发流量压垮。
- 熔断与降级:在服务出现异常或超时的情况下,自动切换到备用方案,以保证系统的可用性。
- 监控与报警:提供丰富的监控指标和仪表盘,实时监控服务的状态,能够通过报警机制提醒开发人员注意异常情况。
- 动态规则配置:支持动态配置流量控制、熔断和降级规则,无需重启应用,能够迅速响应系统的变化。
限流算法-时间窗口
固定时间窗口:计数器算法思想,在固定的时间窗口内,可以允许固定数量的请求进入,超过阈值就执行对应的限流策略。
滑动时间窗口:在固定时间窗口可能会出现请求堆积的情况,例如:限制1秒100个请求,第一秒的大部分请求都在后半秒,第二秒的大部分请求都在前半秒,那么这两个半秒的请求加起来就超过100了。要解决的话,我们就需要使用滑动时间窗算法,具体原理如下:
- 不划分固定的时间窗起点与终点,而是将每一次请求的到来时间点作为统计时间窗的终点,起点则是终点向前推时间窗长度的时间点。这种时间窗称为“滑动时间窗”