Spring Cloud Alibaba:Nacos服务注册与发现
动态服务发现对以服务为中心的(例如微服务和云原生)应用架构方式非常关键。Nacos
支持DNS-Based
和RPC-Based
(Dubbo
、gRPC
)模式的服务发现。Nacos
也提供实时健康检查,以防止将请求发往不健康的服务实例。
服务(Service
)是Nacos
世界的一等公民。Nacos
支持几乎所有主流类型的服务的发现、配置和管理:
-
Kubernetes Service
-
gRPC & Dubbo RPC Service
-
Spring Cloud RESTful Service
Nacos
的配置特性将在下一篇博客中进行介绍,并且先以Spring Cloud RESTful Service
为例子,Kubernetes Service
和gRPC & Dubbo RPC Service
在以后介绍Kubernetes
和Dubbo
时再进行补充。
Eureka
也有服务注册与发现的功能,博主在下面这几篇博客中进行了介绍:
- Spring Cloud 之Eureka初使用
- Spring Cloud 之Eureka高可用
- Spring Cloud 之使用RestTemplate实现微服务之间相互请求的三种方式
- Spring Cloud 之Feign实现微服务之间相互请求
但由于Eureka2.0
闭源,以及Nacos
本身的优势(服务在线管理、配置动态刷新等),并且Nacos
久经双十一的考验。
功能
| Nacos
| Eureka
| 说明
|
注册中心
| 是
| 是
| 服务治理基本功能,负责服务中心化注册
|
配置中心
| 是
| 否
| Eureka 需要Config 的配合来实现配置中心,且不提供管理界面 |
配置动态刷新
| 是
| 否
| Eureka 需要Config 、MQ 以及Webhook 的配合来实现配置动态刷新,而Nacos 采用Netty 保持TCP 长连接实时推送 |
可用区AZ
| 是
| 是
| 对服务集群划分不同区域,实现区域隔离,并提供容灾自动切换
|
分组
| 是
| 否
| Nacos 可以根据业务和环境进行分组管理 |
元数据
| 是
| 是
| 提供服务标签数据,例如环境或服务标识
|
权重
| 是
| 否
| Nacos 默认提供权重设置功能,调整承载流量压力 |
健康检查
| 是
| 是
| Nacos 支持由客户端或服务端发起的健康检查,Eureka 是由客户端发起心跳 |
负载均衡
| 是
| 是
| 均提供负责均衡策略,Eureka 采用Ribbon |
管理界面
| 是
| 否
| Nacos 支持对服务在线管理,Eureka 只是预览服务状态 |
Spring Cloud Alibaba
版本关系:
下载与运行Nacos
Windows下载
直接下载zip
后缀的nacos-server
压缩包。
解压后的目录如下图所示:
运行Nacos
:
startup.cmd -m standalone
可以访问管理界面(要加/nacos
路径,因为有默认配置server.servlet.cnotallow=/nacos
)。
Linux下载
复制链接地址,用于使用wget
命令进行下载。
wget https://github.com/alibaba/nacos/releases/download/1.4.2/nacos-server-1.4.2.tar.gz
解压:
tar -zxvf nacos-server-1.4.2.tar.gz
解压后的目录如下图所示:
运行Nacos
:
./startup.sh -m standalone
用户名和密码都是nacos
。
创建服务
创建AlibabaBlog maven
工程作为父module
,再创建nacos
和consumer
两个子module
。
AlibabaBlog module
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.kaven</groupId>
<artifactId>AlibabaBlog</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<description>Spring Cloud Alibaba</description>
<modules>
<module>nacos</module>
<module>consumer</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.2.RELEASE</version>
</parent>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<spring-cloud-alibaba-version>2.2.6.RELEASE</spring-cloud-alibaba-version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<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>
</project>
nacos module
结构如下图所示:
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>AlibabaBlog</artifactId>
<groupId>com.kaven</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>nacos</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
application.yml
:
server:
port: 8080
spring:
application:
name: nacos
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
NacosController
接口类:
package com.kaven.alibaba.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @Author: ITKaven
* @Date: 2021/11/08 17:00
* @Blog: https://kaven.blog.csdn.net
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@RestController
public class NacosController {
@GetMapping("/nacos")
public String getMessage() {
System.out.println("被请求了!");
return "spring cloud alibaba nacos";
}
}
NacosApplication
启动类:
package com.kaven.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
* @Author: ITKaven
* @Date: 2021/11/08 16:39
* @Blog: https://kaven.blog.csdn.net
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@SpringBootApplication
@EnableDiscoveryClient
public class NacosApplication {
public static void main(String[] args) {
SpringApplication.run(NacosApplication.class);
}
}
@EnableDiscoveryClient
注解要加上。
consumer module
结构如下图所示:
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>AlibabaBlog</artifactId>
<groupId>com.kaven</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>consumer</artifactId>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
application.yml
:
server:
port: 8090
spring:
application:
name: consumer
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
ConsumerController
接口类:
package com.kaven.alibaba.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
/**
* @Author: ITKaven
* @Date: 2021/11/08 17:10
* @Blog: https://kaven.blog.csdn.net
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@RestController
public class ConsumerController {
@Resource
private RestTemplate restTemplate;
@GetMapping("/nacos")
public String getNacos() {
return restTemplate.getForObject("http://nacos/nacos", String.class);
}
}
ConsumerApplication
启动类:
package com.kaven.alibaba;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @Author: ITKaven
* @Date: 2021/11/08 17:07
* @Blog: https://kaven.blog.csdn.net
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
@EnableDiscoveryClient
注解要加上。
启动两个子module
。
服务注册成功了。
consumer
使用RestTemplate
成功调用注册在Nacos
上的服务。
多服务负载均衡
启动3
个nacos
服务,首先要修改NacosApplication
的运行配置,操作如下所示:
依次修改端口启动服务(修改一次端口,启动一次服务)。
3
个nacos
服务启动成功。
多次请求http://localhost:8090/nacos/
:
这里很显然是轮询的负载均衡策略,而Nacos
的负载均衡策略默认是轮询。但这里并没有使用到Nacos
的负载均衡策略,而是使用了Spring Cloud
中的负载均衡策略,因为在控制台上修改服务的权重是无效的,仍然是轮询;要想使用自定义的负载均衡策略,就需要实现自定义的IRule
实现类,这在下面这篇博客中有介绍:
- Spring Cloud 之Ribbon负载均衡
而Nacos
已经实现了自定义的IRule
实现类NacosRule
,有兴趣可以去探索一下NacosRule
类的源码。因此需要将NacosRule
实例变成bean
,便于Spring
容器管理,修改ConsumerApplication
类如下:
package com.kaven.alibaba;
import com.alibaba.cloud.nacos.ribbon.NacosRule;
import com.netflix.loadbalancer.IRule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Scope;
import org.springframework.web.client.RestTemplate;
/**
* @Author: ITKaven
* @Date: 2021/11/08 17:07
* @Blog: https://kaven.blog.csdn.net
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
@Bean
@Scope(value = "prototype")
public IRule loadBalanceRule() {
return new NacosRule();
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
重复上面的请求操作,结果是一样的,大家可以去测试一下,因为Nacos
的负载均衡策略默认也是轮询。
服务在线管理
修改第一个nacos
服务的权重为100
(默认为1
)。
修改服务权重成功。
使用Postman
来批量调用consumer
服务的接口。
第一个nacos
服务被调用了98
次。
另外两个nacos
服务都是被调用了1
次。
Nacos
的源码分析博主以后再进行介绍,博主目前还在看Spring
的源码,等有时间再分享其他框架的源码分析。Nacos
服务注册与发现就介绍到这里,之后会介绍Nacos
的其他特性以及高可用。
如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。