本文为个人SpringCloud学习笔记,主要记录Nacos的注册中心实操、SpringBoot多模块编程实操等
注册中心是微服务的一个重要组件,用于实现服务的注册与发现,主要作用包括以下:
注册中心通常有两个角色
使用多模块编程的方式实现生产者
1.构建父模块
2.父模块添加依赖
3.删除无用文件
4.父依赖修正
4.构建子模块生产者(prodiver)
5.子类依赖
6.删除重复依赖
因为父模块中已经有配置,那么子模块下面图示代码删除即可
7.添加所属父类说明
8.父类添加拥有子类说明
9. 子类配置application.yml
spring:
application:
# 服务注册站点
name: nacos-provider #命名不能使用‘_’,早期SpringCloud不支持
cloud:
nacos:
# Nacos认证信息
discovery:
username: nacos
password: nacos
# Nacos 服务发现与注册配置,其中子属性server-addr指定Nacos服务器主机和端口
server-addr: localhost:8848
namespace: public # 注册到nacos的指定namespace,默认public
server:
port: 0 #动态端口
补充:这里使用动态端口是因为微服务中,消费者在调用生产者服务的时候是通过Nacos作为中间人的,具体调用到哪个一个实际上并不关心,所以实际生产者端口号分配工作不妨丢给操作系统去分配,这样也不怕端口被占有的问题。同时,也是因为微服务的随机调用生产者服务,不需要写死服务调用端口号,所以机器处理可靠下,为什么不让机器来考虑这种问题呢?而且微服务体量大,如果人为去分配,也可以导致两个服务分配到相同的端口号,所以这种工作不妨让机器去苦恼。
在项目启动后,会自动注册到Nacos中作为一个服务站点中的一员
访问成功:
11.最终说明
到此多模块的创建便结束了,以下是父模块pom.xml与子模块provider的pom.xml
父模块pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.examplegroupId>
<artifactId>SpringCloudDiscoveryDemoartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>SpringCloudDiscoveryDemoname>
<description>SpringCloudDiscoveryDemodescription>
<packaging>pompackaging>
<properties>
<java.version>17java.version>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<spring-boot.version>3.0.2spring-boot.version>
<spring-cloud-alibaba.version>2022.0.0.0spring-cloud-alibaba.version>
<spring-cloud.version>2022.0.0spring-cloud.version>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
<modules>
<module>providermodule>
modules>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>${spring-boot.version}version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>${spring-cloud-alibaba.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.1version>
<configuration>
<source>17source>
<target>17target>
<encoding>UTF-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<version>${spring-boot.version}version>
<executions>
<execution>
<id>repackageid>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
project>
provider----->pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.examplegroupId>
<artifactId>providerartifactId>
<version>0.0.1-SNAPSHOTversion>
<name>providername>
<description>providerdescription>
<parent>
<groupId>com.examplegroupId>
<artifactId>SpringCloudDiscoveryDemoartifactId>
<version>0.0.1-SNAPSHOTversion>
parent>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.1version>
<configuration>
<source>17source>
<target>17target>
<encoding>UTF-8encoding>
configuration>
plugin>
<plugin>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-maven-pluginartifactId>
<configuration>
<mainClass>com.example.provider.ProviderApplicationmainClass>
<skip>trueskip>
configuration>
<executions>
<execution>
<id>repackageid>
<goals>
<goal>repackagegoal>
goals>
execution>
executions>
plugin>
plugins>
build>
project>
注册中心的消费者的实现比生产者更为复杂一些,首先因为消费者要通过调用生产者提供API来完成服务,这其中就需要HTTP接口作为中间人,那么就需要引入Spring Cloud OpenFeign
,其次为了实现负载均衡,我们还需要添加客户端负载均衡器Spring Cloud LoadBalancer
。
- Spring Cloud OpenFeign: Spring Cloud OpenFeign 是 SpringCloud 生态系统中的一个组件,它是基于 Netflix 的 Feign 库开发的,用于简化和优化微服务架构中的服务间通信。
- Spring Cloud LoadBalancer: Spring Cloud 团队提供的一种客户端负载均衡器
- 负载均衡(Load Balancer) :一种在多个服务实例之间分配负载和流量的技术,目的是提高服务的整体性能和可靠性。
消费者创建步骤如下:
1.子模块消费者(Consumer)
还是一样的配方
2.添加依赖
父模块添加OpenFegin与LoadBalance依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-loadbalancerartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
父模块添加子模块说明
<modules>
<module>providermodule>
<module>consumermodule>
modules>
子模块添加父模块说明
<parent>
<groupId>com.examplegroupId>
<artifactId>SpringCloudDiscoveryDemoartifactId>
<version>0.0.1-SNAPSHOTversion>
parent>
3.启动配置
spring:
application:
# 服务注册站点
name: nacos-consumer#命名不能使用‘_’,早期SpringCloud不支持
cloud:
nacos:
# Nacos认证信息
discovery:
username: nacos
password: nacos
# Nacos 服务发现与注册配置,其中子属性server-addr指定Nacos服务器主机和端口
server-addr: localhost:8848
namespace: public # 注册到nacos的指定namespace,默认public
register-enabled: false
server:
port: 8080
这里需要注意的是:对于消费者而已,我们需要把它的注册功能关闭,因为消费者本身是调用服务而不提供服务,所以没必要注册服务,所以这里使用
“register-enabled: false”
将其关闭,而且消费者生产者的服务注册站点名字配置上也不同,方便管理
除此之外还有一点,对于客户端来说,他不再想服务端那样端口动态化,因为客户端主要还是面向人的,如果人要使用,端口动态,那么我要如何才能准确访问到呢?所以
客户端端口需要明确指定
4.开启OpenFegin
在消费者的启动类上加上注解@EnableFeignClients
@SpringBootApplication
@EnableFeignClients
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
@Service
@FeignClient(name = "nacos-provider")
public interface UserService {
@RequestMapping("/user/getInfo")
public String getInfo(@RequestParam("name") String name);
}
这里我们需要注意到的是@FeignClient(name = “nacos-provider”),就是告诉这个接口:服务站点在这个位置
@RequestMapping(“/user/getInfo”)而这一句注解则是告诉这个服务接口具体路由,所以消费者的接口就可以通过路由访问调用到生产者的API了
6.调用服务API
import com.example.consumer.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
@Autowired
private UserService userService;
@RequestMapping("/order")
public String getInfo(){
return userService.getInfo(" Spring Cloud");
}
}
7.实际效果
当集群中的健康实例占比小于设置的保护闻值时,就会触发闻值保护功能
。触发保护闻值后,Nacos会将全部实例(健康实例+非健康实例)返回给调用者,虽然可能会损失一部分流量,但能保证集群中剩余的健康实例能正常工作。label 标签实现就近访问,官方实现: https://nacos.io/zh-cn/blog/cmdb.html
民间实现:
https://blog.csdn.net/lr309283175/article/details/116030428
Nacos中的健康检测机制是用来检查服务健康状态的,只有健康的节点才会被服务消费端调用,这样才能保证程序稳定、正常的运行。Nacos中提供了两种健康检测的机制:
举个简单的例子:
面对灾害,对于被困人,ta需要主动求助:“救救我,救救我”,而对于搜救员,是“你在哪,你在哪”的反向询问确认
所以就是说,客户端每隔一段时间,跟服务端上报状态,而服务端则通过反向探测来确定客户端是否健康
所以这两种机制时间上是对应两个服务实例
临时实例:对应客户端主动上报状态
永久实例:反向探测客户端状态