在微服务场景下,多个服务之间的相互调用是不可避免的。而注册中心的职责就是负责通联这些分布在不同地方上的服务(即服务注册与发现)。
实际上服务注册与发现并不难,因为需求已经很明确了,除了上边提到的服务注册与发现,还应该有一个心跳机制,来确保注册过来的服务是可用的。
所以本身而言,让我们实现一个注册中心,要解决的问题,应该有:一个注册表,来记录这些期望被调用的服务。一个心跳机制,保证服务提供端注册的服务可用。以及客户端的一个拉取机制。
Eureka的工作原理如下图
实际上,在推送请求和拉取请求这件事上,推送注册表是一个写操作,而拉取注册表是一个读操作。写与读是有一个冲突的问题的,在eureka中为了避免读写的冲突,采用了多级缓存,延迟加载,通过最终一致性来解决读写冲突。
- 服务端把服务地址推送到注册表。
- 此时立马把注册表同步到读写缓存。
- 内部用一个线程来定时的吧读写缓存中的数据推送到只读缓存。
- 客户端定时的从只读缓存中读取配置。如果只读缓存没有数据,则去读写缓存拉取,如果有则拉取,如果没有则去注册表拉取。
- 注册中心还应该有一个心跳机制,定期的检查注册表中的服务是否可用。就是发送心跳包给服务提供端,如果正常则不操作。如果服务端服务不正常则将这个服务从注册表踢出,并质空读写缓存。
如何写一个能上生产的注册中心
先来梳理一下能上生产的必要条件。我们知道本身微服务进行了拆分,引入了更多的技术来解决拆分后问题。多数通过第三方技术来解耦。那么就面临了一个必然的问题:单点故障。试想一下,注册中心实际上是服务之间的枢纽。如果注册中心挂掉了,整个服务就瘫痪了。想要保证服务高可用,中间件的高可用也是必须的。注册中心能不能上生产,重要的一个问题就是高可用。在服务中高可用,通常是用集群来解决的。所以上生产的注册中心,应该支持集群模式。
所以从上边提到了自己实现一个注册中心的两个需求(服务注册与发现 心跳机制),变成了再加上 支持集群模式。
那么集群模式实现起来难吗?最主要的工作实际上是:客户端应该知道注册中心的全部地址,客户端加一个心跳机制,来检查注册中心是否存活,如果不存活尝试链接其他的注册中心;另外多个注册中心应该有一个互通获取服务注册表信息的功能。