当前位置: 首页 > 科技观察

我加入了一家新公司,结果无法使用SpringCloud,人生第一次被炒鱿鱼

时间:2023-03-17 13:53:11 科技观察

一、问题的由来在SpringCloud架构体系中,Eureka是一个至关重要的组件,它扮演着微服务注册中心的角色,所有的服务注册和服务发现都依赖于在尤里卡。很多刚接触SpringCloud的朋友在落地公司生产环境部署的时候经常会问:EurekaServer需要部署多少台机器?我们系统中有这么多的服务,对EurekaServer会有多大的访问压力呢?EurekaServer能否承受大型系统的访问压力?如果你也有这些疑问,别担心!一起来看看吧。Eureka作为微服务注册中心的核心原则是以下几个问题。我们先来看看,有个大概的印象。带着这些疑问,再看下面的内容会事半功倍。Eureka注册中心是用什么方法存储每个服务注册时发送的机器地址和端口号的?每个服务请求EurekaServer拉取注册中心的频率是多少?每个服务如何拉取注册表?一个拥有数百个服务、上千台机器的大型分布式系统部署在EurekaServer上会有多大的访问压力?EurekaServer如何从技术角度抗住数千万级的日访问量?先说一个基础知识点。默认情况下,每个服务中的EurekaClient组件会每隔30秒向EurekaServer发送一次请求,拉取最近发生变化的服务信息。例如:库存服务原来部署在1台机器上,现在扩容,部署到3台机器上,全部注册到EurekaServer。然后订单服务的EurekaClient会每隔30秒去EurekaServer拉取最新的注册表变化,看看其他服务的地址有没有变化。另外,Eureka还有心跳机制。每个EurekaClient都会每隔30秒向EurekaServer发送一次心跳,通知其他人,哥们,我的服务实例还活着!如果某个EurekaClient长时间没有向EurekaServer发送心跳,则说明该服务实例已经挂了。光看上面的文字,你可能没有太多印象。老规矩!来一张图,一起来直观感受一下这个过程吧。2.EurekaServer设计精巧的注册中心存储结构现在假设我们手头有一个大型的分布式系统,一共有100个服务,每个服务部署在20台标准配置为4核8G的机器上。也就是说,你总共部署了100*20=2000个服务实例和2000台机器。每台机器上的服务实例内部都有一个EurekaClient组件,它会每隔30秒请求EurekaServer拉取变化的registry。此外,每个服务实例上的EurekaClient会每隔30秒向EurekaServer发送一次心跳请求。那么我们算一算,作为微服务注册中心的EurekaServer每秒会被请求多少次呢?你一天要被要求多少次?按照标准算法,每个服务实例每分钟请求拉取注册中心两次,每分钟请求发送两次心跳。这样一个服务实例每分钟会请求4次,2000个服务实例每分钟会请求8000次。换算成每秒,大概是8000/60=133次,我们粗略估计EurekaServer每秒会被请求150次。那一天就是8000*60*24=1152万,也就是说每天有几千万的访问量。好的!经过这么一算,你发现这里的奥秘了吗?首先,对于微服务注册中心这样的组件,在设计它的拉取频率和心跳发送频率时,已经考虑了一个大系统每次服务请求的压力,每秒会承载多少请求。所以每个服务实例每30秒发起一次拉取变化的registry的请求,每30秒向EurekaServer发送一次心跳。其实这个时机是有目的的。根据我们的计算,一个有数百个服务、上千台机器的系统以这样的频率请求EurekaServer,每天的请求量在千万级别,每秒??的访问量在150次左右。即使算上其他一些额外的操作,我们也只是每秒询问EurekaServer200到300次。因此,通过设置合适的拉取注册中心和发送心跳的频率,可以保证在大型系统中EurekaServer的请求压力不会太大。关键问题是,EurekaServer如何保证能够轻松抵御每秒数百次请求和每天数千万次请求?要想搞清楚这个问题,我们首先要了解EurekaServer是用什么来存储注册表的?三个字,看源码。接下来我们进入Eureka源码一探究竟:如上图所示,图中名为registry的CocurrentHashMap是registry的核心结构。看完后,不禁先赞叹一下,精美的设计!从代码中可以看出,EurekaServer的注册中心是直接基于纯内存的,即在内存中维护了一个数据结构。每个服务的注册、服务下线、服务失败都会在内存中维护和更新这个注册表。当每个服务每30秒拉取注册表时,EurekaServer只是向它们提供存储在内存中的更改后的注册表数据。同样,当每30秒发起一次心跳时,心跳时间也会在这个纯内存的Map数据结构中更新。一句话总结:维护注册表,拉取注册表,更新心跳时间,都发生在内存中!这是EurekaServer非常核心的一点。搞清楚了这个,我们再分析一下registry的数据结构。不要被它复杂的外表所迷惑,静下心来一层层分析吧!首先这个ConcurrentHashMap的key就是服务名,比如“inventory-service”,就是一个服务名。值表示一个服务的多个服务实例。例子:比如“inventory-service”可以有3个服务实例,每个服务实例部署在一台机器上。我们看一下Mapasvalue:Map>这个Map的key是服务实例的idvalue,是一个叫Lease的类,它的泛型是一个叫InstanceInfo的东西,你可能请问,这两个是什么鬼?首先,让我们谈谈InstanceInfo。事实上,我们知道这个名字。这个InstanceInfo表示服务实例的具体信息,比如机器的ip地址、主机名、端口号等。并且在这个Lease中,每个服务的最后一次心跳时间都会维护在里面。3、EurekaServer端优秀的多级缓存机制。假设EurekaServer部署在4核8G的普通机上,根据内存来承载各个服务的请求,每秒可以处理多少个请求?根据之前的测试,单台4核8G机器可以处理纯内存操作,即使有一些网络开销,每秒处理数百个请求也轻松愉快。而且,为了避免同时读写内存数据结构带来的并发冲突,EurekaServer还采用了多级缓存机制,进一步提高了服务请求的响应速度。拉取registry时:首先从ReadOnlyCacheMap中查看缓存的registry。如果没有,请查找缓存在ReadWriteCacheMap中的注册表。如果还没有,则从内存中获取实际的注册表数据。注册表改变时:改变后的注册表数据会在内存中更新,同时ReadWriteCacheMap会过期。这个过程不会影响别人提供的ReadOnlyCacheMap查询注册表。在一段时间内(默认30秒),每个拉取注册中心的服务都会直接读取ReadOnlyCacheMap。30秒后,EurekaServer后台线程发现ReadWriteCacheMap已经被清空,也会清空ReadOnlyCacheMap中的缓存。下次有服务拉取registry时,会从内存中取出最新的数据,同时填充各个cache。多级缓存机制有什么优点?尽量保证内存注册表数据不会频繁的读写冲突。并进一步保证对EurekaServer的大量请求从纯内存快速迁移,性能极高。为了方便大家更好的理解,这里也放一张图,大家跟着图回顾一下整个过程:4.总结从上面的分析我们可以看出,Eureka设置了合适的请求频率(在某个时间拉取注册表单)intervalof30seconds),每隔30秒发送心跳),可以保证大型系统每秒请求EurekaServer数百次。同时通过纯内存注册表,保证所有请求都在内存中处理,保证了极高的性能。此外,多级缓存机制保证内存数据结构不会出现频繁的读写并发冲突操作,进一步提升性能。以上就是在SpringCloud架构中,Eureka作为微服务注册中心,可以承载大型系统每天千万级访问量的原理。