【ServiceComb学习记录】微服务扫盲
项目架构
一站式微服务开源解决方案,包含多个产品,如:
Service Center
Java Chassis
Mesher
Service Center
一个服务注册中心。 服务提供者可以将自身的实例信息注册到 ServiceCenter,以供服务消费者发现并使用它。
注册发现流程
1.服务提供者向Service Center注册服务信息
2.服务提供者发送心跳,维持在Service-Center中的“UP”状态
3.服务消费者向Service-Center注册服务信息
4.服务消费者从Service-Center发现服务提供者信息
5.服务消费者向服务提供者发送请求,并获取通讯结果
servicecomb 的核心设计理念————以契约为中心
契约是微服务系统运行和治理的基础,java chassis 提供了两种方式定义契约:code first 和 contract first 。
微服务架构的优点
1.微服务独立开发、独立运行、独立部署,可以使用任意一种语言开发,解决了技术栈受限的问题;
2.微服务之间不会互相影响,避免出现某个模块设计不合理造成CPU使用率飙升而影响其他模块的情况
3.不同的团队维护不同的服务,职责单一;
4.可以针对不同的服务做不同的扩、缩容策略,避免资源浪费
Eureka微服务架构中节点信息的维护
使用服务注册/服务发现机制实现
Service Center为避免同时读写内存数据结构造成的并发冲突问题,还采用多级缓存机制进一步提升服务请求的响应速度
在拉取注册表的时候:首先从ReadOnlyCacheMap里查缓存的注册表。若没有,就找ReadWriteCacheMap里缓存的注册表。如果还没有,就从内存中获取实际的注册表数据。
第一层缓存:readOnlyCacheMap,本质上是 ConcurrentHashMap,依赖定时从 readWriteCacheMap 同步数据,默认时间为 30 秒。
第二层缓存:readWriteCacheMap,本质上是 Guava 缓存。readWriteCacheMap 的数据主要同步于存储层。当获取缓存时判断缓存中是否没有数据,如果不存在此数据,则通过 CacheLoader 的 load 方法去加载,加载成功之后将数据放入缓存,同时返回数据。
readWriteCacheMap 缓存过期时间,默认为 180 秒,当服务下线、过期、注册、状态变更,都会来清除此缓存中的数据。
Eureka拉取注册表的过程:
Eureka Client 获取全量或者增量的数据时,会先从一级缓存中获取;如果一级缓存中不存在,再从二级缓存中获取;如果二级缓存也不存在,这时候先将存储层的数据同步到缓存中,再从缓存中获取。
Eureka拉取实例信息的过程
客户端第一次全量拉取+后续增量拉取
增量拉取注册表的实现借助了一个ConcurrentLinkedQueue类型的变量recentlyChangedQueue,默认情况下recentlyChangedQueue里面存放的是180秒内修改的服务实例信息,后台会有一个定时任务来维护recentlyChangedQueue,只有最近180秒内有变更的服务实例才会在里面。
在增量拉取注册表时,会将本地的注册表和recentlyChangedQueue中的服务实例进行一个合并,将有变化的服务实例信息进行一个修改,保证本地的服务注册表信息和eureka server的服务注册表一致。
在获取增量注册表信息的时候,同时获取了一个eureka server全量注册表的hash值,这个又是干什么用的呢?在eureka client增量同步注册表完成之后,也会计算一个hash值,然后将自己计算出来的这个hash值和eureka server全量注册表的hash值进行比对,如果是一致的,说明增量数据同步没问题,反之则说了增量数据同步出现了不一致,那么就会重新从eureka server全量拉取一份最新的服务注册表。
多级缓存的意义
当存在大规模的服务注册和更新时,如果只是修改 ConcurrentHashMap 里的数据,那么势必因为锁的存在导致竞争,影响性能。两层缓存机制可以提高并发读写效率,增量数据通过linkQueue维护,再加一个线程保证只保存最近3分钟的变更数据,这个架构设计很值得学习,还有一个就是通过hash对比来判断数据是否一致,在分布式系统中比较数据一致中比较实用。但是由于缓存机制的存在,服务实例注册、下线、故障,client感知到需要很长时间(30s readOnlyCacheMap更新,30s client增量拉取注册表),在实际生产项目中,都会调整参数进行优化。
CAP理论是分布式架构中重要理论,它说的是:
一致性(Consistency) (所有节点在同一时间具有相同的数据)
可用性(Availability) (保证每个请求不管成功或者失败都有响应)
分区容错性(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
Zookeeper保证CP
当向注册中心查询服务列表时,我们可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举。问题在于,选举leader的时间太长,30 ~ 120s, 且选举期间整个zk集群都是不可用的,这就导致在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得zk集群失去master节点是较大概率会发生的事,虽然服务能够最终恢复,但是漫长的选举时间导致的注册长期不可用是不能容忍的。
Eureka保证AP
Eureka看明白了这一点,因此在设计时就优先保证可用性。Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:
1.Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
2.Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
3.当网络稳定时,当前实例新的注册信息会被同步到其它节点中
因此, Eureka可以很好的应对因网络故障导致部分节点失去联系的情况,而不会像zookeeper那样使整个注册服务瘫痪。
总的来说,数据存在的节点越多,分区容忍性越高,但要复制更新的数据就越多,一致性就越难保证。为了保证一致性,更新所有节点数据所需要的时间就越长,可用性就会降低。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南