一、前言
服务发现是微服务架构体系中最关键的组件之一。如果尝试着用手动的方式来给每一个客户端来配置所有服务提供者的服务列表是一件非常困难的事,而且也不利于服务的动态扩缩容。
Spring Cloud Alibaba Nacos Discovery
通过自动配置以及其他Spring
编程模型的习惯用法为Spring Boot
应用程序在服务注册与发现方面提供和Nacos
的无缝集成。 通过一些简单的注解,可以快速来注册一个服务,并使用Nacos
组件来作为大规模分布式系统的服务注册中心。
Spring Cloud Alibaba Nacos Discovery
可以帮助您将服务自动注册到Nacos
服务端并且能够动态感知和刷新某个服务实例的服务列表。除此之外,它也将服务实例自身的一些元数据信息,例如:host
、port
、健康检查URL
、主页等注册到 Nacos
。
二、准备条件
-
已完成
Nacos
服务端部署,本章基于上章实现的Nacos
集群为基础,详情请见:nacos 单机集群搭建及常用生产环境配置 | Spring Cloud 3 -
已完成
SpringCloud
初始项目的手脚架搭建,详情请见:Spring Cloud入门篇 Hello World | Spring Cloud 1
三、项目搭建
3.1 项目最终结构
- 模块
nacos-discovery-http
,用于放置验证服务注册与发现所需对应的服务提供者和服务调用者应用。 - 模块
nacos-discovery-http/nacos-discovery-http-provider
为服务提供者应用 - 模块
nacos-discovery-http/nacos-discovery-http-consumer
为服务调用者应用
源码地址:https://gitee.com/gm19900510/springboot-cloud-example
根项目springboot-cloud-example/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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.gm</groupId>
<artifactId>springboot-cloud-example</artifactId>
<name>springboot-cloud-example</name>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<description>SpringBoot-Cloud进阶实战示例</description>
<properties>
<spring-boot.version>2.7.9</spring-boot.version>
<spring-cloud.version>2021.0.5</spring-cloud.version>
<spring-cloud-alibaba.version>2021.0.4.0</spring-cloud-alibaba.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<modules>
<module>hello-world</module>
<module>nacos-discovery-http</module>
</modules>
<dependencies>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- spring boot 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud 依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- spring cloud alibaba 依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<finalName>${project.name}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<finalName>${project.build.finalName}</finalName>
<layers>
<enabled>true</enabled>
</layers>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
<profiles>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
<nacos.username>nacos</nacos.username>
<nacos.password>nacos</nacos.password>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
</project>
3.2 新增模块nacos-discovery-http
- 在根项目下新建目录
nacos-discovery-http
- 在目录
nacos-discovery-http
下新增文件pom.xml
其中nacos-discovery-http/pom.xm
,完整配置如下:
<?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>springboot-cloud-example</artifactId>
<groupId>com.gm</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<artifactId>nacos-discovery-http</artifactId>
</project>
- 选择
nacos-discovery-http/pom.xm
文件,右键点击添加为Maven项目
3.2 新增模块nacos-discovery-http-provider
在模块nacos-discovery-http
下进行如下操作:
nacos-discovery-http/nacos-discovery-http-provider/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>
<groupId>com.gm</groupId>
<artifactId>nacos-discovery-http</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos-discovery-http-provider</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<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-test</artifactId>
<scope>test</scope>
</dependency>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.xlsx</exclude>
<exclude>**/*.xls</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.xlsx</include>
<include>**/*.xls</include>
</includes>
</resource>
</resources>
</build>
</project>
bootstrap.yml
存储一些关于 Nacos
基本的配置,完整配置如下:
server:
port: 4000
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:nacos1.kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos2kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos3.kc}:${NACOS_PORT:8848}
management:
endpoints:
web:
exposure:
include: '*'
编写com/gm/nacos_discovery_http_provider/controller/ProviderController.java
package com.gm.nacos_discovery_http_provider.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProviderController {
@Value("${server.port}")
private int port;
@RequestMapping(value = "sayHello", method = RequestMethod.GET)
public String sayHello(@RequestParam String world) {
return "当前服务端口为:" + port + ",请求参数:" + world;
}
}
编写com/gm/nacos_discovery_http_provider/NacosHttpProviderApplication.java
package com.gm.nacos_discovery_http_provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class NacosHttpProviderApplication {
public static void main(String[] args) {
SpringApplication.run(NacosHttpProviderApplication.class, args);
}
}
在服务启动类中新增注解:
@EnableDiscoveryClient
,表示启动服务发现。
spring-cloud-starter-alibaba-nacos-discovery
在实现的时候提供了一个EndPoint
EndPoint
的访问地址为 http://ip:port//actuator/nacosdiscovery。 EndPoint
的信息主要提供了两类:
subscribe
: 显示了当前有哪些服务订阅者NacosDiscoveryProperties
: 显示了当前服务实例关于Nacos
的基础配置
启动nacos-discovery-http-provider
实例访问EndPoint
的信息如下所示:
{
"subscribe": [
{
"name": "nacos-discovery-http-provider",
"groupName": "DEFAULT_GROUP",
"clusters": "DEFAULT",
"cacheMillis": 1000,
"hosts": [
{
"ip": "192.168.1.82",
"port": 4000,
"weight": 1.0,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "DEFAULT",
"serviceName": "DEFAULT_GROUP@@nacos-discovery-http-provider",
"metadata": {
"preserved.register.source": "SPRING_CLOUD"
},
"ipDeleteTimeout": 30000,
"instanceHeartBeatInterval": 5000,
"instanceHeartBeatTimeOut": 15000
},
{
"ip": "192.168.1.82",
"port": 4001,
"weight": 1.0,
"healthy": true,
"enabled": true,
"ephemeral": true,
"clusterName": "DEFAULT",
"serviceName": "DEFAULT_GROUP@@nacos-discovery-http-provider",
"metadata": {
"preserved.register.source": "SPRING_CLOUD"
},
"ipDeleteTimeout": 30000,
"instanceHeartBeatInterval": 5000,
"instanceHeartBeatTimeOut": 15000
}
],
"lastRefTime": 0,
"checksum": "",
"allIPs": false,
"reachProtectionThreshold": false,
"valid": true
}
],
"NacosDiscoveryProperties": {
"serverAddr": "nacos.kc:8848",
"username": "nacos",
"password": "nacos",
"endpoint": "",
"namespace": "",
"watchDelay": 30000,
"logName": "",
"service": "nacos-discovery-http-provider",
"weight": 1.0,
"clusterName": "DEFAULT",
"group": "DEFAULT_GROUP",
"namingLoadCacheAtStart": "false",
"metadata": {
"preserved.register.source": "SPRING_CLOUD"
},
"registerEnabled": true,
"ip": "192.168.1.82",
"networkInterface": "",
"ipType": "IPv4",
"port": 4000,
"secure": false,
"accessKey": "",
"secretKey": "",
"heartBeatInterval": null,
"heartBeatTimeout": null,
"ipDeleteTimeout": null,
"instanceEnabled": true,
"ephemeral": true,
"failureToleranceEnabled": false,
"failFast": true,
"nacosProperties": {
"password": "nacos",
"endpoint": "",
"secretKey": "",
"serverAddr": "nacos.kc:8848",
"accessKey": "",
"clusterName": "DEFAULT",
"namespace": "",
"com.alibaba.nacos.naming.log.filename": "",
"namingLoadCacheAtStart": "false",
"username": "nacos"
}
}
}
针对后续服务调用的负载均衡验证,变更服务端口号,再次启动nacos-discovery-http-provider
实例。
至此服务提供者配置完成,启动两个服务实例,端口分别为4000和4001。查看Nacos服务端服务列表
:
3.3 新增模块nacos-discovery-http-consumer
在模块nacos-discovery-http
下进行如下操作:
nacos-discovery-http/nacos-discovery-http-consumer/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>
<groupId>com.gm</groupId>
<artifactId>nacos-discovery-http</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<artifactId>nacos-discovery-http-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<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-test</artifactId>
<scope>test</scope>
</dependency>
<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>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.xlsx</exclude>
<exclude>**/*.xls</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.xlsx</include>
<include>**/*.xls</include>
</includes>
</resource>
</resources>
</build>
</project>
bootstrap.yml
存储一些关于 Nacos
基本的配置,完整配置如下:
server:
port: 3000
spring:
application:
name: @artifactId@
cloud:
nacos:
username: @nacos.username@
password: @nacos.password@
discovery:
server-addr: ${NACOS_HOST:nacos1.kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos2kc}:${NACOS_PORT:8848},${NACOS_HOST:nacos3.kc}:${NACOS_PORT:8848}
编写openfeign
接口类com/gm/nacos_discovery_http_consumer/service/ProviderServiceFeign.java
调用服务提供者
package com.gm.nacos_discovery_http_consumer.service;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "nacos-discovery-http-provider")
public interface ProviderServiceFeign {
@RequestMapping(value = "sayHello", method = RequestMethod.GET)
String sayHello(@RequestParam("world") String world);
}
编写com/gm/nacos_discovery_http_consumer/controller/ConsumerController.java
调用openfeign
接口
package com.gm.nacos_discovery_http_consumer.controller;
import com.gm.nacos_discovery_http_consumer.service.ProviderServiceFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ConsumerController {
@Autowired
ProviderServiceFeign providerServiceFeign;
@RequestMapping(value = "sayHello", method = RequestMethod.GET)
public String sayHello() {
return providerServiceFeign.sayHello("hello world");
}
}
编写com/gm/nacos_discovery_http_provider/NacosHttpProviderApplication.java
package com.gm.nacos_discovery_http_consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients("com.gm.nacos_discovery_http_consumer.service")
public class NacosHttpConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(NacosHttpConsumerApplication.class, args);
}
}
在服务启动类中新增注解:
@EnableFeignClients
,用于开启FeginClient功能,会扫描@FeignClient生成feginClient
代理对象,在生成代理对象的过程中会判断FeignClient
注解是否有url
属性如果没有url
属性则生成具有loadBalance
功能的代理对象。
至此服务调用者配置完成,启动服务实例。
四、测试
浏览器访问:http://127.0.0.1:3000/sayHello
重复请求
发现服务调用者调用服务提供者的负载均衡生效
五、Nacos Starter更多参数说明
更多关于 spring-cloud-starter-alibaba-nacos-discovery
的 starter
配置项如下所示:
配置项 | Key | 默认值 | 说明 |
---|---|---|---|
服务端地址 | spring.cloud.nacos.discovery.server-addr | 无 | Nacos Server 启动监听的ip地址和端口 |
服务名 | spring.cloud.nacos.discovery.service | ${spring.application.name} | 给当前的服务命名 |
服务分组 | spring.cloud.nacos.discovery.group | DEFAULT_GROUP | 设置服务所处的分组 |
权重 | spring.cloud.nacos.discovery.weight | 1 | 取值范围 1 到 100,数值越大,权重越大 |
网卡名 | spring.cloud.nacos.discovery.network-interface | 无 | 当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址 |
注册的IP地址 | spring.cloud.nacos.discovery.ip | 无 | 优先级最高 |
注册的端口 | spring.cloud.nacos.discovery.port | -1默认情况下不用配置,会自动探测 | |
命名空间 | spring.cloud.nacos.discovery.namespace | 无 | 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。 |
AccessKey | spring.cloud.nacos.discovery.access-key | 无 | 当要上阿里云时,阿里云上面的一个云账号名 |
SecretKey | spring.cloud.nacos.discovery.secret-key | 无 | 当要上阿里云时,阿里云上面的一个云账号密码 |
Metadata | spring.cloud.nacos.discovery.metadata | 无 | |
日志文件名 | spring.cloud.nacos.discovery.log-name | 无 | |
集群 | spring.cloud.nacos.discovery.cluster-name | DEFAULT | 配置成Nacos集群名称 |
接入点 | spring.cloud.nacos.discovery.enpoint | UTF-8 | |
是否集成Ribbon | ribbon.nacos.enabled | true | 一般都设置成true即可 |
是否开启Nacos Watch | spring.cloud.nacos.discovery.watch.enabled | true | 可以设置成false来关闭 watch |
注册的IP地址类型 | spring.cloud.nacos.discovery.ip-type | IPv4 | 可以配置IPv4和IPv6两种类型 |
六、下章预告
下章进行nacos
融合springcloud
,实现配置的动态变更。