
上个章节的例子中可以看到,远程调用时,我们的 URL 是写死的:
String url = "http://127.0.0.1:9090/product/"+ orderInfo.getProductId();当更换机器,或者新增机器时,这个 URL 就需要跟着变更,就需要去通知所有的相关服务去修改。随之而来的就是各个项目的配置文件反复更新,各个项目的频繁部署。这种没有具体意义,但又不得不做的工作,会让人非常痛苦。
注册中心(Service Registry / Service Discovery Center)是微服务架构中一个核心组件,用来管理和维护服务实例的“地址簿”。它的核心作用是让服务能够动态发现其他服务的位置,而不依赖固定的 IP 或端口。
注册中心主要有三种角色:
注册中心主要负责两件事:
A:IP:PORT。
CAP 理论是分布式系统设计中最基础,也是最为关键的理论。

一个分布式系统不可能同时满足数据一致性,服务可用性和分区容错性这三个基本需求,最多只能同时满足其中的两个。
在分布式系统中,系统间的网络不能 100% 保证健康,服务又必须对外保证服务,因此 Partition Tolerance 不可避免,那就只能在 Consistency 和 Availability 中选择一个,也就是 CP 或者 AP 架构。
更多参考:https://cloud.tencent.com/developer/article/1860632
Zookeeper 的官方并没有说它是一个注册中心,但是国内 Java 体系大部分的集群环境都是依赖 Zookeeper 来完成注册中心的功能。
Eureka 是 Netflix 开发的基于 REST 的服务发现框架,主要用于服务注册、管理、负载均衡和服务故障转移。
官方声明在 Eureka2.0 版本停止维护,不建议使用。但是 Eureka 是 SpringCloud 服务注册/发现的默认实现,所以目前还是有很多公司在使用。
Nacos 是 SpringCloudAlibaba 架构中重要的组件,除了服务注册,服务发现功能之外,Nacos 还支持配置管理、流量管理、DNS、动态DNS等多种特性。
Zookeeper | Eureka | Nacos | |
|---|---|---|---|
CAP理论 | CP | AP | CP或AP (默认AP) |
在分布式环境中,即使拿到一个错误的数据,也胜过无法提供实例信息而造成请求失败要好,比如淘宝双十一、京东618都是谨遵AP原则。
Eureka 是 NetflixOSS 套件中关于服务注册和发现的解决方案。SpringCloud 对 Eureka 进行了集成,并作为优先推荐方案进行宣传,虽然目前 Eureka2.0 已经停止维护,新的微服务架构设计中,也不再建议使用,但是目前依然有大量公司的微服务系统使用 Eureka 作为注册中心。
官方文档:https://github.com/Netflix/eureka/wiki
Eureka主要分为两个部分:
EurekaServer:作为注册中心 Server 端,向微服务应用程序提供服务注册、服务发现、健康检查等功能。EurekaClient:服务提供者,服务启动时,会向 EurekaServer 注册自己的信息(IP、端口、服务信息等信息),然后 EurekaServer 会存储这些信息。通常 Eureka-server 作为一个独立的微服务!

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency><build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>给该项目编写一个启动类,并在启动类上添加 @EnableEurekaServer 注解,开启 eureka 注册中心服务。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}server:
port: 10010
spring:
application:
name: eureka-server
eureka:
instance:
hostname: localhost
client:
fetch-registry: false # 表示是否从Eureka Server获取注册信息,默认为true.因为这是一个单点的Eureka Server,不需要同步其他的Eureka Server节点的数据,这里设置为false
register-with-eureka: false # 表示是否将自己注册到Eureka Server,默认为true.由于当前应用就是Eureka Server,故而设置为false.
service-url:
# 设置与Eureka Server的地址,查询服务和注册服务都需要依赖这个地址.
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/启动服务,访问注册中心:http://127.0.0.1:10010/,可以看到 eureka-server 已经启动成功了。

接下来将之前的 product-service 注册到 eureka-server 中。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>添加服务名称和 eureka 的地址:
spring:
application:
name: product-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10010/eureka刷新注册中心:http://127.0.0.1:10010/,可以看到 product-service 已经注册到 eureka 上了:

接下来修改 order-service,在远程调用时,从 eureka-server 拉取 product-service 的服务信息,实现服务发现。
服务注册和服务发现都封装在 eureka-client 依赖中,所以服务发现时,也是引入 eureka-client 依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>服务发现也需要知道 eureka 地址,因此配置内容依然与服务注册一致,都是配置 eureka 信息。
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10010/eureka远程调用时,我们需要从 eureka-server 中获取 product-service 的列表(可能存在多个服务),并选择其中一个进行调用。
所有微服务要从注册中心(如 Eureka、Consul、Nacos)拉取服务实例信息,靠的就是 DiscoveryClient。
@Slf4j
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Resource
private DiscoveryClient discoveryClient;
@Autowired
private RestTemplate restTemplate;
public OrderInfo selectOrderById(Integer orderId) {
OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
//String url = "http://127.0.0.1:9090/product/"+ orderInfo.getProductId();
// 根据应用名称获取服务列表
List<ServiceInstance> instances = discoveryClient.getInstances("product-service");
// 服务可能有多个, 获取第一个
EurekaServiceInstance instance = (EurekaServiceInstance) instances.get(0);
log.info(instance.getInstanceId());
// 拼接url
String url = instance.getUri() + "/product/" + orderInfo.getProductId();
ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
orderInfo.setProductInfo(productInfo);
return orderInfo;
}
}刷新注册中心:http://127.0.0.1:10010/,可以看到 order-service 已经注册到 eureka 上了。

访问接口:http://127.0.0.1:8080/order/1,可以看到,远程调用也成功了。
Eureka 和 Zookeeper 都是用于服务注册和发现的工具,区别如下:
AP 原则,保证高可用,而 Zookeeper 基于 CP 原则,保证数据一致性。原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。