目录
- 一、服务注册引入
- [二、 服务注册中心](#二、 服务注册中心)
- [三、 CAP理论](#三、 CAP理论)
- [四、 常见注册中心](#四、 常见注册中心)
- [五、 Eureka](#五、 Eureka)
-
- [5.1 搭建注册中心](#5.1 搭建注册中心)
- [5.2 服务注册](#5.2 服务注册)
- [5.3 服务发现](#5.3 服务发现)

一、服务注册引入
在上一篇环境与工程搭建,我们远程调用时候写url写死了。
java
String url = "http://127.0.0.1:9090/product/"+ orderInfo.getProductId();
当更换服务器的时候,这个url是需要跟着变的。我们这里就需要使用注册中心来解决这个问题。
二、 服务注册中心
注册中心:维护⼀个服务列表,哪个机器上线了,哪个机器宕机了,这些信息都会⾃动更新到服务列表上,客⼾端拿到这个列表,直接进⾏服务调⽤即可。这个就是注册中⼼
注册中⼼主要有三种⻆⾊(以租房为例):
- 服务提供者(Server):⼀次业务中,被其它微服务调⽤的服务。也就是提供接⼝给其它微服务。(相当于房东)
- 服务消费者(Client):⼀次业务中,调⽤其它微服务的服务。也就是调⽤其它微服务提供的接⼝。(相当于租客)
- 服务注册中⼼(Registry):⽤于保存Server 的注册信息,当Server 节点发⽣变更时,Registry 会同步变更。服务与注册中⼼使⽤⼀定机制通信,如果注册中⼼与某服务⻓时间⽆法通信,就会注销该实例。(相当于中介)
关系与工作内容:
- 服务注册:服务提供者在启动时,向 Registry 注册⾃⾝服务,并向 Registry 定期发送⼼跳汇报存活状态。
- 服务发现:服务消费者从注册中⼼查询服务提供者的地址,并通过该地址调⽤服务提供者的接⼝。服务发现的⼀个重要作⽤就是提供给服务消费者⼀个可⽤的服务列表。

三、 CAP理论
- 一致性(Consistency): CAP理论中的⼀致性, 指的是强⼀致性,所有节点在同⼀时间对外具有相同的数据。(弱一致性就是,所有节点对外达到相同数据可以有时间间隔)
- 可⽤性(Availability):保证每个请求都有响应(响应结果可能不对)
- 分区容错性(Partition Tolerance):当出现⽹络分区后,系统仍然能够对外提供服务

分布式系统CAP三个属性是不可能同时满足的,系统间的⽹络又不能100%保证健康,服务⼜必须对外保证服务,因此Partition Tolerance(分区容错性)不可避免。那就只能在C和A中选择⼀个。也就是CP或者AP架构。
- CP架构:为了保证分布式系统对外的数据⼀致性,于是选择不返回任何数据
- AP架构:为了保证分布式系统的可⽤性,节点间可能返回不同版本的数据(即使这个数据不正确)
四、 常见注册中心
- Zookeeper
Zookeeper的官⽅并没有说它是⼀个注册中⼼,但是国内Java体系,⼤部分的集群环境都是依赖 Zookeeper来完成注册中⼼的功能。 - Eureka
Eureka是Netflix开发的基于REST的服务发现框架,主要⽤于服务注册,管理,负载均衡和服务故障转移。
官⽅声明在Eureka2.0版本停⽌维护,不建议使⽤。但是Eureka是SpringCloud服务注册/发现的默认实现,所以⽬前还是有很多公司在使⽤。 - Nacos
Nacos是Spring Cloud Alibaba架构中重要的组件,除了服务注册,服务发现功能之外,Nacos还⽀持配置管理,流量管理,DNS,动态DNS等多种特性。

五、 Eureka
Eureka主要分为两个部分:
- Eureka Server:作为注册中⼼Server端,向微服务应⽤程序提供服务注册,发现,健康检查等能⼒。
- Eureka Client:服务提供者,服务启动时,会向Eureka Server 注册⾃⼰的信息(IP,端⼝,服务信息等),Eureka Server 会存储这些信息。
5.1 搭建注册中心
我们就使用上一篇文章环境与工程搭建的案例代码来搭建。
-
创建Eureka-server ⼦模块

-
pom中引⼊eureka-server依赖与项目构建插件
xml
<!-- 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>
- 完善启动类
java
package com.cloud.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
- 配置文件
yml
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/
- 启动服务,访问注册中心

5.2 服务注册
把product-service 注册到eureka-server中。
- 在product-service的pom文件中加上eureka-client的依赖
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 完善product-service的配置⽂件
yml
spring:
application:
name: product-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10010/eureka
- 启动服务

5.3 服务发现
修改order-service,在远程调⽤时,从eureka-server拉取product-service的服务信息,实现服务发现
- 在order-service的pom文件中加上eureka-client的依赖
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
- 完善order-service的配置⽂件
yml
spring:
application:
name: order-service
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10010/eureka
- 远程调⽤,修改service
java
package com.cloud.order.service;
import com.cloud.order.mapper.OrderMapper;
import com.cloud.order.model.OrderInfo;
import com.cloud.order.model.ProductInfo;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.netflix.eureka.EurekaServiceInstance;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@Service
@Slf4j
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
@Resource
private DiscoveryClient discoveryClient;
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;
}
}
- 启动

