现在我们要实现基于Nacos的服务注册与发现,那么就需要导入SpringCloudAlibaba相关的依赖,我们在父工程将依赖进行管理:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- 这里引入最新的SpringCloud依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 这里引入最新的SpringCloudAlibaba依赖,2021.0.1.0版本支持SpringBoot2.6.X -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2021.0.1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
接着我们就可以在子项目中添加服务发现依赖了,比如我们以图书服务为例:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
和注册到Eureka一样,我们也需要在配置文件中配置Nacos注册中心的地址:
server:
# 之后所有的图书服务节点就81XX端口
port: 8101
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://cloudstudy.mysql.cn-chengdu.rds.aliyuncs.com:3306/cloudstudy
username: test
password: 123456
# 应用名称 bookservice
application:
name: bookservice
cloud:
nacos:
discovery:
# 配置Nacos注册中心地址
server-addr: localhost:8848
接着启动我们的图书服务,可以在Nacos的服务列表中找到:
按照同样的方法,我们接着将另外两个服务也注册到Nacos中:
接着我们使用OpenFeign,实现服务发现远程调用以及负载均衡,导入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- 这里需要单独导入LoadBalancer依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
编写接口:
@FeignClient("userservice")
public interface UserClient {
@RequestMapping("/user/{uid}")
User getUserById(@PathVariable("uid") int uid);
}
@FeignClient("bookservice")
public interface BookClient {
@RequestMapping("/book/{bid}")
Book getBookById(@PathVariable("bid") int bid);
}
@Service
public class BorrowServiceImpl implements BorrowService{
@Resource
BorrowMapper mapper;
@Resource
UserClient userClient;
@Resource
BookClient bookClient;
@Override
public UserBorrowDetail getUserBorrowDetailByUid(int uid) {
List<Borrow> borrow = mapper.getBorrowsByUid(uid);
User user = userClient.getUserById(uid);
List<Book> bookList = borrow
.stream()
.map(b -> bookClient.getBookById(b.getBid()))
.collect(Collectors.toList());
return new UserBorrowDetail(user, bookList);
}
}
@EnableFeignClients
@SpringBootApplication
public class BorrowApplication {
public static void main(String[] args) {
SpringApplication.run(BorrowApplication.class, args);
}
}
接着我们进行测试:
测试正常,可以自动发现服务,接着我们来多配置几个实例,去掉图书服务和用户服务的端口配置:
然后我们在图书服务和用户服务中添加一句打印方便之后查看:
@RequestMapping("/user/{uid}")
public User findUserById(@PathVariable("uid") int uid){
System.out.println("调用用户服务");
return service.getUserById(uid);
}
现在将全部服务启动:
可以看到Nacos中的实例数量已经显示为2
:
接着我们调用借阅服务,看看能否负载均衡远程调用:
OK,负载均衡远程调用没有问题,这样我们就实现了基于Nacos的服务的注册与发现,实际上大致流程与Eureka一致。
值得注意的是,Nacos区分了临时实例和非临时实例:
那么临时和非临时有什么区别呢?
- 临时实例:和Eureka一样,采用心跳机制向Nacos发送请求保持在线状态,一旦心跳停止,代表实例下线,不保留实例信息。
- 非临时实例:由Nacos主动进行联系,如果连接失败,那么不会移除实例信息,而是将健康状态设定为false,相当于会对某个实例状态持续地进行监控。
我们可以通过配置文件进行修改临时实例:
spring:
application:
name: borrowservice
cloud:
nacos:
discovery:
server-addr: localhost:8848
# 将ephemeral修改为false,表示非临时实例
ephemeral: false
接着我们在Nacos中查看,可以发现实例已经不是临时的了:
如果这时我们关闭此实例,那么会变成这样:
只是将健康状态变为false,而不会删除实例的信息。