【深入明白SpringCloud微服务】浅析微服务注册中心Eureka与nacos,手写实现一个微服务注册中心
注册中心注册中心是微服务体系内里非常告急的一个核心组件,它最告急的作用就是实现服务注册与发现。
在已往还没有微服务和注册中心的时间,一个服务存在对另一个服务的调用关系时,须要在自己服务的设置文件内里设置对方的ip端口,当发生调用时,须要读取设置文件内里对方的ip端口,组装哀求url,发送哀求。这种方式非常的不机动,当被调用的服务集群用呆板上下线时,调用方不能动态感知,须要手动修改设置然后重启服务,而且服务一旦多起来,维护这些设置也是一项繁琐的工作,很容易堕落。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvY2JjMDg2YTI4MTBhZmVmNWRlOTA0MGZlOTc4OGRjZTMucG5n
为了办理这个题目,于是就有了微服务注册中心。
注册中心是摆设在分布式大概微服务情况下的一个中心件服务,提供服务的注册与发现功能。当使用了注册中心之后,调用方被称为服务斲丧者,被调用方被称为服务提供者。服务提供者启动时往注册中心注册,注册信息包罗自己的服务名称、服务实例id、ip地点和端口等,注册中心把这些信息维护到内存注册表。服务斲丧者启动时(饿汉式加载)大概在发生调用时(懒加载)想注册中心发起服务发现哀求,从注册中心拉取服务提供者注册上来的注册信息,缓存到当地的服务列表中。如许,服务斲丧者通过查询服务列表就能得知要调用的服务提供者的ip端口,无需在设置文件中举行设置,而且当服务提供者对应的服务集群有服务实例上下线时,服务斲丧者可以通过定时轮询注册中心大概注册中心主动关照的方式动态感知。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvYTFmNWYzYjIwZWYxZjllOTBlNmQzM2UwY2NiMTlkNTAucG5n
注册中心会在内存中维护一个服务注册表,用于存储服务提供者注册上来的信息。比如用一个双层Map,外层key是服务名,内层key是服务实例id(同一服务的差别实例构成集群,因此须要一个雷同于id的唯一标识),value是ip端口。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvYmY0NzQ5NjgzMmYzOGMxNDc0NjRlNDkyMmQ0MjQyYjYucG5n
内存中的注册信息有大概还会长期化大概存到外部的存储服务中,比如Mysql、redis、MongoDB、文件都可以。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvYWE5M2JhOTNjZDZlYjYzNmVkMTRjOTM3YWZiZDczYTAucG5n
注册中心为了制止单点故障,通常也是集群摆设。因此,注册中心实例之间会有服务注册信息的同步。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvZGQ3ZTQ1NzA2NzY3MDc3OTE1ZWY1NGYxZjk4OTRmOWUucG5n
当注册中心是集群式摆设时,服务提供者启动时就通过某种方式选取到一台注册中心实例注册即可,注册中心会通过集群内同步把注册信息同步到其他注册中心实例。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvMGI5ZjllNGZmYzhiMjRiMDlmZWEyNzc4NjI4MWM4MmYucG5n
由于服务有大概由于某些缘故起因而出题目大概下线,服务注册中心须要通过某种方式对服务提供者举行康健查抄,把不康健的服务实例从注册表中剔除。但是有的注册中心不会对服务提供者举行康健查抄,而是给服务提供者注册上来的信息设置一个逾期时间,服务提供者须要定期的举行服务续约,假如高出指定时间不续约,服务提供者的注册信息将会被注册中心从注册表中剔除。注册中心的注册表发生表动,会关照服务斲丧者,大概由服务斲丧者自己轮询感知注册表的厘革。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvNzllNTBjOTY4OGEwYzk4MjczM2U3Y2E1ZmVjZmEwZDMucG5n
手写实现一个注册中心
我们对注册中心已经有了一个熟悉,总结下来就是有一个服务注册服务端,维护了一个内存注册表,客户端哀求服务端举行服务注册与发现,现实上就是读写内存注册表。然后注册中心折务端还要实现注册信息在集群内的同步、服务变更关照客户端、服务康健查抄等功能。
那么,我们也可以实现一个自己的注册中心了。
服务端筹划
我们照旧参考Eureka和1.x版本的nacos,接纳http服务端的实现方式。我们界说一个自己的Controller,名字就叫RegistryCenterController,是一个SpringMVC的Controller,吸取客户端发来的http哀求。
然后我们界说一个Service,名字叫RegistryCenterService,由它来处理处罚内存注册表的读写,内存注册表就直接放在RegistryCenterService中。RegistryCenterController吸取到哀求之后,会调用registryCenterService举行哀求处理处罚。
在界说内存注册表的结构前,我们要界说一个用于存放注册信息的对象,我们界说一个MicroService对象用于封装服务提供者的注册信息,比如ip地点端标语等。
然后内存注册表的结构照旧使用双层ConcurrentHashMap,外层key就是服务名serviceName(我们这里不思量什么namespace和cluster之类的东西),内存key就是服务实例id,value就是MicroService,如许就是一个非常简单的双层ConcurrentHashMap结构的内存注册表,我们给它定名为registryTable。
客户端通过发送http哀求来举行服务发现和服务注册,服务端通过RegistryCenterController吸取http哀求并调用RegistryCenterService读写内存注册表registryTable。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvM2YyNGE4ZjA3M2ZkZDg0MjdhOGUzZTI1NTk1ZDQzN2YucG5n
RegistryCenterController:
/**
* @author huangjunyi
* @date 2023/11/30 10:23
* @desc
*/
@RestController
@RequestMapping("/registry/center")
public class RegistryCenterController {
@Autowired
private RegistryCenterService registryCenterService;
...
}
RegistryCenterService :
/**
* @author huangjunyi
* @date 2023/11/30 10:40
* @desc
*/
@Service
public class RegistryCenterService {
// 内存注册表,双层ConcurrentHashMap:]
private Map<String, Map<String, MicroService>> registryTable = new ConcurrentHashMap<>();
...
}
MicroService :
/**
* @author huangjunyi
* @date 2023/11/30 10:41
* @desc
*/
public class MicroService implements Serializable {
private String serviceName;
private String id;
private String ip;
private int port;
private long lastTime;
...
}
至于服务同步,我们也是做异步处理处罚。在RegistryCenterService 内部界说一个LinkedBlockingQueue范例的变量作为队列,把注册上来的信息放到这个队列内里,就把MicroService对象放进去。然后使用一个配景线程去轮询这个队列,把MicroService同步到集群中的其他注册中心实例。
https://dis.qidao123.com/imgproxy/aHR0cHM6Ly9pLWJsb2cuY3NkbmltZy5jbi9ibG9nX21pZ3JhdGUvMmU3MjJmNTE2NDRiNjQ5MDM2ZTRjZjZmMzM5Mjk1YTQucG5n
RegistryCenterService :
@Service
public class RegistryCenterService {
// 内存注册表,双层ConcurrentHashMap:]
private Map<String, Map<String, MicroService>> registryTable = new ConcurrentHashMap<>();
// 集群同步队列
private LinkedBlockingQueue<MicroService> syncQueue = new LinkedBlockingQueue<>(
页:
[1]