Nacos
简介
最主要的功能是配置管理和服务发现。
配置管理:
- nacos将配置发布配置。服务从nacos获取配置。如果修改了已经存在nacos的配置,并且服务开启了动态获取,则服务可以获取更新后的配置。
**服务发现:**当两个服务之间需要有调用时,调用使用http协议,则以下图为例
- 服务A、B会将自己的地址上报给nacos
- 当serviceA要调用serviceB时,会找nacos获取serviceB的地址
- servcieA然后根据地址去调用serviceB服务。
环境
- 64 bit OS,支持 Linux/Unix/Mac/Windows,推荐选用 Linux/Unix/Mac。
- 64 bit JDK 1.8+;
- Maven 3.2.x+;
入门
-
下载原码或发行包(以下载发行包为例,nacos-server-1.1.4)
-
启动服务器:解压后,运行bin文件夹下的startup.cmd。
-
然后登入http://127.0.0.1:8848/nacos
或http://localhost:8848/nacos等。
默认用户:nacos 默认密码:nacos
-
服务注册和发布配置。
启动nacos服务之后,可以根据nacos提供的http api验证nacos服务是否正常。
需要使用curl的命令行工具。下载地址:https://curl.haxx.se/windows/发布服务:
curl -X POST "http://127.0.0.1:8848/nacos/v1/ns/instance?serviceName=nacos.naming.serviceName&ip=20.18.7.10&port=8080"
结果:
发布配置:
curl -X POST "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test&content=HelloWorld"
结果:
-
服务发现和配置获取
服务发现:
curl -X GET "http://127.0.0.1:8848/nacos/v1/ns/instance/list?serviceName=nacos.naming.serviceName"
结果:
配置获取:
curl -X GET "http://127.0.0.1:8848/nacos/v1/cs/configs?dataId=nacos.cfg.dataId&group=test"
结果:
外部mysql数据库的支持
nacos默认使用嵌入式数据库实现数据存储,例如存储配置信息等。可以改为使用mysql数据库存储。
环境:
-
mysql数据库版本5.6+
-
新建一个数据库nacos_config。然后执行nacos的config目下的nacos-mysql.sql文件。
-
修改config目录下的application.properties文件,添加
db.num=1 db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true db.user=root db.password=root
Nacos的管理模型
根据namespace、group、dataid可以确定唯一一个配置文件。
dataId:表示一个配置文件。一个项目下有多个工程,一个工程由一个主配置文件。
group:通常用于表示一个项目分组。例如一个学生管理系统的项目,可以分组为:STUDENT_GROUP。
namespace:表示不同环境。用于分割开发环境,生产环境,测试环境。
命名空间
创建命名空间:
切换不同的命名空间:
nacos的配置管理应用
服务从nacos获取配置
-
发布一个配置
-
建造一个父工程,用于管理版本依赖。子类微服务继承父工程。
父工程nacosconfig的pom.xml文件:用于管理依赖<?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.itheima.nacos</groupId> <artifactId>nacos-config</artifactId> <version>0.2.0-SNAPSHO</version> <modules> <module>service1</module> <module>service2</module> </modules> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-boot.version>2.0.3.RELEASE</spring-boot.version> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> </properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
**创建子工程微服务:**service1
pom.xml文件
<?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>nacos-config</artifactId>
<groupId>com.itheima.nacos</groupId>
<version>0.2.0-SNAPSHO</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>service1</artifactId>
<properties>
<nacos-config-spring-boot.version>0.2.1</nacos-config-spring-boot.version>
</properties>
<dependencies>
<!--导入web启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!--导入nacos启动器-->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>${nacos-config-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-actuator</artifactId>
<version>${nacos-config-spring-boot.version}</version>
</dependency>
</dependencies>
</project>
配置文件application.properties:用于配置nacos服务中线
nacos.config.server-addr=127.0.0.1:8848
#命名空间:开发环境
nacos.config.namespace=766053ac-4a74-41c8-a0ae-e981dad0b86d
主启动类:ApplicationNacos.class
@SpringBootApplication
@NacosPropertySource(dataId = "service1",groupId = "TEST_GROUP",autoRefreshed = true)
public class ApplicationNacos {
public static void main(String[] args) {
SpringApplication.run(ApplicationNacos.class,args);
}
}
@NacosPropertySource:用于配置要读取的配置的id,和组等信息。
controller测试:
@RestController
public class NacosController {
@NacosValue(value = "${common.name:null}", autoRefreshed = true)
private String name;
@RequestMapping(value = "/test", method = RequestMethod.GET)
public String test() {
return name;
}
}
@NacosValue:动态的从配置文件中获取属性。
- 测试:
获取多个配置
一个服务从nacos获取多个配置,或者多个服务获取同一个配置。
一个服务从nacos获取多个配置:
-
在nacos的dev的namespace下在创建一个配置。
-
再添加**@NacosPropertySource**注解,配置dataId和groupId,autoRefreshed开启动态读取
如果两个配置有相同的key,则优先读取上面的注解配置。@SpringBootApplication @NacosPropertySource(dataId = "service1",groupId = "TEST_GROUP",autoRefreshed = true) @NacosPropertySource(dataId = "service1Demo",groupId = "TEST_GROUP",autoRefreshed = true) public class ApplicationNacos {
@RestController public class NacosController { @NacosValue(value = "${common.name:null}", autoRefreshed = true) private String service1Name; @NacosValue(value = "${common01.name:null}",autoRefreshed = true) private String service2Name; @RequestMapping(value = "/test", method = RequestMethod.GET) public String test() { System.out.println("service1:"+service1Name); System.out.println("service1Demo:"+service2Name); return "OK"; } }
-
结果测试:
多个服务读取同一个配置
- 首先再创建一个与service1相同的子服务。
- service2也读取nacos中的service1配置。
- 结果测试:
Nacos的集群部署
-
将nacos的文件复制3份(以此为例)
-
改动每个nacos文件的配置。conf下的application.properties文件。改动每个nacos端口号让其不相同。
-
将每个nacos的conf下的cluster.conf.example改名为cluster.conf。并配置每个nacos的Ip:port
127.0.0.1:8848 127.0.0.1:8849 127.0.0.1:8850
-
在每个nacos的bin目录下,使用startup.cmd -m cluster命令行启动。
startup.cmd -m cluster
-
在登入任意nacos的页面,即可查看集群节点。
使用service从集群中获取配置测试:
服务发现
在一个大的项目中,会根据不同的功能来划分为不同的服务。例如在一个购物的项目中,就划分为订单服务,商品服务,用户服务。
而这些服务为了实现一些功能,可能会相互调用。例如一个用户完成下单的动作,则需要调用商品服务来获取商品信息,用户服务来获取用户信息等。而为了完成服务之间的相互是调用,调用方就需要获得被调用方的网络地址(IP地址+端口号)。
但是由于服务的网络地址不一定是固定的,因此我们可以将被调用方的地址交由nacos管理,调用方直接从nacos中获取。
以下是模拟serviceA调用serviceB的流程图。
Ribbon:用于负载均衡,属于客户端服务负载均衡。serviceB可能不止一个实例,当serviceA调用serviceB时使用何种方式调用,就取决于Ribbon组件。默认为负载均衡策略是轮询。
**Feign:**服务间的调用是通过http协议的,该组件简化了服务间调用的步骤。
入门案例
-
首先建一个父工程,一会服务生产方和服务消费方都会继承该工程。
父工程的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.itheima.nacos</groupId> <artifactId>nacosdiscover</artifactId> <version>1.0-SNAPSHOT</version> <modules> <module>nacosProduction</module> <module>nacosconsumer</module> </modules> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencyManagement> <dependencies> <!--spring-cloud-alibaba的依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--spring-cloud的依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--spring-boot的依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.3.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
-
创建服务生产方(被调用者)。
-
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"> <parent> <artifactId>nacosdiscover</artifactId> <groupId>com.itheima.nacos</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>nacosProduction</artifactId> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> </project>
-
配置文件
server: port: 8081 #配置端口号 spring: application: name: nacosConsumer #配置服务名称 cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #配置地址值 namespace: 766053ac-4a74-41c8-a0ae-e981dad0b86d #命名空间
-
配置启动类:服务发现要使用**@EnableDiscoveryClient**,@EnableFeignClients
//模拟服务端生产者 @SpringBootApplication @EnableDiscoveryClient @EnableFeignClients public class ApplicationPro { public static void main(String[] args) { SpringApplication.run(ApplicationPro.class,args); } }
-
编写controller
@RestController public class ProdController { private static final Logger logger= LoggerFactory.getLogger(ProdController.class); @GetMapping("test") public String test(){ logger.info("服务端生产者被调用"); return "nacosProduct"; } }
-
-
创建服务消费方
-
依赖:与生产方相同
-
配置文件:注意与生产方端口不冲突
server: port: 8081 #配置端口号 spring: application: name: nacosConsumer #配置服务名称 cloud: nacos: discovery: server-addr: 127.0.0.1:8848 #配置地址值 namespace: 766053ac-4a74-41c8-a0ae-e981dad0b86d #命名空间
-
启动类:相同
-
Feign的客户端:是一个接口,要使用**@FeignClient**修饰,属性value要指定生产方的服务名称。该接口内部方法表示要调用的生产方的方法,直接复制该方法除方法体意外的内容。
@FeignClient("nacosProduction") public interface ProductClient { @GetMapping("test") public String test(); }
-
书写controller:对Feign的客户端对象注入,调用其方法。
@RestController public class ConsumerController { @Autowired private ProductClient productClient; @GetMapping("test") public String test(){ return "consumer"+"|"+productClient.test(); } }
-
-
将生产方和消费方都启动。
在nacos,服务管理-服务列表,选择对应的生产空间,则可以看到服务都已经被注册了。
-
通过消费者的地址调用方法:http://localhost:8081/test
负载均衡演示
-
在运行一个服务生产方,端口号为8082。
-
此时可以看到生产方有2个实例
-
来回访问http://localhost:8081/test。
则可以发现生产方的两个实例被来回调用(默认轮询)。