一、Nacos简介
Nacos 是阿里巴巴的开源项目,是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
Nacos 和Eureka一样,但是更强大。
常见的注册中心:
-
Eureka(原生,2.0遇到性能瓶颈,停止维护)
-
Zookeeper(支持,专业的独立产品。例如:dubbo)
-
Consul(原生,GO语言开发)
-
Nacos
二、配置中心
配置中心作用:可以将application.yml 中的内容配置到nacos,如果需要修改配置文件,不需要打开jar包,在jar包中修改,直接在nacos管理界面修改即可。
2.1新建配置文件
在nacos管理界面-配置中心-配置列表,点击右侧加号(如图)
Data ID 的完整规则格式如下:prefix-spring.profiles.active.file-extension
-
prefix
是所在模块的模块名,即配置文件中 spring.application.name 的值 -
spring.profiles.active 可以不填
-
file-exetension
为配置内容的数据格式,可以填yml或 properties
在下面的"配置内容"中,粘贴配置,我把代码里的application.yaml 删除,所有配置都放到nacos中,如果项目可以正常启动,且端口、数据库链接都是"配置内容"中的,说明成功读取了nacos配置中心的配置。
2.2 引入依赖
<!-- 读取nacos配置依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
2.3在和application.yml平级的位置 新建 bootstrap.properties
这个文件的作用是指向配置文件,告诉程序读取哪里的配置文件、读取哪个配置文件
#配置中心地址
spring.cloud.nacos.config.server-addr=localhost:8848
# 开启动态刷新配置,否则配置文件修改,工程无法感知
spring.cloud.nacos.config.ext-config[0].refresh=true
# 上一步设置的DataId
spring.cloud.nacos.config.ext-config[0].data-id=service-sta.properties
2.4验证
启动程序,不报错,且端口号是"配置内容"中的配置信息,证明使用了nacos中的配置。
2.5 动态配置
就是在"配置内容"中进行了修改,可以立刻通知到程序,如果不这么设置,需要将程序重启,才能读到新的配置。
2.5.0 具体做法
在bootstrap.properties 中,添加一行
# 开启动态刷新配置,否则配置文件修改,工程无法感知
spring.cloud.nacos.config.ext-config[0].refresh=true
2.5.1 验证
在nacos管理界面点击 "编辑"(如图),随便修改一个配置项后点击"发布"
程序中有如下输出,代表动态修改完成。
部分修改,比如数据库端口号、程序端口号等,无法立即生效,需要重启程序。
2.6 不同环境下的配置文件
在程序中,会有开发、测试和生产三个不同的环境,通常要写三个配置文件
application-dev.properties application-test.properties application-prod.properties
使用nacos配置时,"命名空间" 提供了这样的功能,一个"命名空间"看作是一个环境,有一套配置文件。
新建"命名空间",分别起名 dev test prod
克隆配置(每个"命名空间" 都有一套 yml 或propertis ,粘贴内容比较麻烦,可以写好一个后,将内容 直接克隆到其他"命名空间",再在其他"命名空间"中做修改):
在boostrap.properties配置文件中,需要加一个配置项,设置使用的namespace编号
# 配置使用哪个环境的配置文件(namespace代表对应的环境及配置文件)
spring.cloud.nacos.config.namespace=ff2af6b8-2b3e-4d16-bc7d-f16947593c07
三、注册中心
服务实例启动时,将自身信息(如服务名称、地址、端口等)注册到Nacos注册中心。
通过注册中心可以1.对微服务的各个模块进行管理、2.配合feign 实现模块间互相调用。
3.1 将单个项目注册到注册中心
3.1.1 pom文件中引入依赖 并指定版本
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>project_test</artifactId>
<version>0.0.1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<packaging>jar</packaging>
<dependencies>
<!--hystrix依赖,主要是用 @HystrixCommand -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<!--服务注册-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
<!--服务调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<!--打包规则,打包时将resource文件夹打包进去-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.1.RELEASE</version>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
</project>
3.1.2 启动类添加服务发现注解@EnableDiscoveryClient
@EnableFeignClients
@EnableDiscoveryClient
@ComponentScan("com.example")
@SpringBootApplication
public class SpringCloudTest2Application {
public static void main(String[] args) {
SpringApplication.run(SpringCloudTest2Application.class, args);
}
}
3.1.3 application.properties中指明 nacos地址
spring.cloud.nacos.discovery.server-addr=localhost:8848
3.2 将子模块注册到nacos
可以在父模块的<dependencyManagement> 中声明 spring-cloud-dependencies 的版本,子模块的spring-cloud-starter-openfeign等依赖就可以不用写版本了,做到版本的统一管理。(<dependencyManagement> 专门用于管理子模块的版本,比如里面放了个依赖a,子模块不会自动引入依赖a,而是当子模块引入依赖b,且b是a的子包时,可以不用写b的版本号)
spring-cloud-dependencies的子包是spring-cloud-starter-openfeign,父模块的<dependencyManagement>中声明 spring-cloud-dependencies 的版本了,子模块中引用spring-cloud-starter-openfeign,就可以不用写版本编号。
其他的比如主类注解、application.properties的配置,和单模块一致。
父模块:
<dependencyManagement>
<dependencies>
<!--Spring Cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
子模块:
<?xml version="1.0" encoding="UTF-8"?>
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>SpringCloudTest</artifactId>
<groupId>com.example</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>model_test</artifactId>
<version>0.0.1</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<packaging>jar</packaging>
<dependencies>
<!--hystrix依赖,主要是用 @HystrixCommand -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<!--服务注册-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>0.2.2.RELEASE</version>
</dependency>
<!--服务调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<!--打包规则,打包时将resource文件夹打包进去-->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.yml</include>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.2.1.RELEASE</version>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
</build>
</project>
四、结合Feign实现 远程调用
即一个注册到naocs的模块,调用另一个注册到nacos模块中的接口
4.1添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--服务调用-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
4.2 具体代码
4.2.1 调用方
4.2.1.1 主类需要添加@EnableFeignClients 注解
这个注解会告诉 Spring Cloud 扫描代码,查找 @FeignClient
注解的接口
@EnableFeignClients
@EnableDiscoveryClient
@ComponentScan("com.example")
@SpringBootApplication
public class SpringCloudTest2Application {
public static void main(String[] args) {
SpringApplication.run(SpringCloudTest2Application.class, args);
}
}
4.2.1.2 编写Client类,通过调用这个类中的方法,可以访问到project-test模块的接口
@Component
// 被调用模块的名称
@FeignClient("project-test")
public interface UserClient {
// 被调用模块的接口地址
@GetMapping("/project/interface")
Integer callProjectModle();
}
4.2.1.3 具体调用
@RestController
public class OriginCallController {
@Autowired
UserClient userClient;
@GetMapping("/orgincall")
public Integer registerCount(){
return userClient.callProjectModle();
}
}
4.2.2 被调用方
被调用方正常写接口就行,不需要额外配置
@RestController
public class EduClient {
@GetMapping("/project/interface")
public R recordMsmLog(){
return R.ok();
}
}
4.3 feign的熔断器
当被调用方出错时,比如被调用方服务停止了、被调用方接口因并发访问次数过多,响应时间太长时,可以直接调用异常处理方法,至少给客户响应一个基本信息,而不是一个500报错或一直等待。
4.3.1.yml中开启熔断器
#nacos 注册中心地址
spring.cloud.nacos.discovery.server-addr=123.249.80.154:8848
# 开启feign熔断器
feign.hystrix.enabled=true
4.3.2.添加异常处理类,集成 Client接口
注意:这个类中的方法不能再抛异常,否则会报错:"[Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: EduClient#recordMsmLog(MsmLogVO) timed-out and fallback failed.] with root cause"
/**
* <p>
* 熔断器,当远程调用失败时被调用,至少给用户错误的提示信息,而不是简单的 500错误
* </p>
* @author hs1235-zhangyuankun
* @date 2024/1/28 20:03
*/
@Component
public class EduClientFallCallback implements EduClient {
@Override
public R recordMsmLog(@RequestBody MsmLogVO msmLogVO) {
return R.error(ErrorEnum.MSM_RECORD_ERROR);
}
}
4.3.3Client接口中增加fallBack
@FeignClient(name = "service-edu",fallback = EduClientFallCallback.class)
@Component
public interface EduClient {
/**
* 远程调用,登记短信的发送情况
* @return
*/
@GetMapping("/eduservice/base/base-msm-log/save")
R recordMsmLog(@RequestBody MsmLogVO msmLogVO);
}