一文秒懂SpringCloud Alibaba中的服务组件——Nacos
共 9990字,需浏览 20分钟
·
2021-05-14 20:31
汪伟俊 | 作者
Java技术迷 | 出品
我们都知道,SpringCloud是微服务的一站式解决方案,是众多组件的集合,而因为SpringCloud中几乎所有的组件使用的都是Netflix公司的产品,其中大部分已经进入了停止更新或者维护阶段。我们需要一些别的组件来代替它们,基于此,SpringCloud Alibaba诞生了,本篇文章我们就来了解一下SpringCloud Alibaba中的服务组件——Nacos。
服务注册与配置中心-Nacos
nacos是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台,在SpringCloud Alibaba中,我们使用nacos进行服务的注册发现、服务的配置管理。
首先下载nacos,官网地址 https://nacos.io/zh-cn/ :
点击下方的版本说明:
拖动到网页底部,点击下载压缩包,解压完成后得到如下的目录结构:
其中启动程序放在bin目录下,直接执行bin目录中的 startup.cmd
即可启动nacos:
这样就表示启动成功了,此时访问 http://localhost:8848/nacos :
默认的用户名和密码均为 nacos
,登录后即可来到nacos的后台管理系统:
服务注册
接下来我们试着编写一个服务并将其注册到nacos中。
首先创建父项目 springcloud-alibaba,将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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.wwj</groupId>
<artifactId>springcloud-alibaba</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud-alibaba</name>
<description>Demo project for Spring Boot</description>
<packaging>pom</packaging>
<modules>
<module>cloud-provider-payment8001</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
</project>
然后创建支付服务提供者 cloud-provider-payment8001,修改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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-provider-payment8001</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>cloud-provider-payment8001</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.wwj</groupId>
<artifactId>springcloud-alibaba</artifactId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
......
</project>
重点是引入nacos的依赖,引入依赖后编写配置文件:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # nacos的服务中心地址
service: cloud-provier-payment # 服务名
server:
port: 8001 # 端口号
需要注意的是服务名是必须进行配置的,配置完成后在启动类上添加@EnableDiscoveryClient注解:
@EnableDiscoveryClient
@SpringBootApplication
public class CloudProviderPayment8001Application {
public static void main(String[] args) {
SpringApplication.run(CloudProviderPayment8001Application.class, args);
}
}
此时启动该服务,然后查看nacos的后台系统:
点击左侧的服务列表,即可看到我们注册到nacos中的服务。然后编写一个控制器用于模拟业务:
@RestController
public class PaymentController {
@Value("${server.port}")
private String port;
@GetMapping("/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id) {
return "nacos服务注册,端口号:" + port + "\t" + "id:" + id;
}
}
测试一下,访问 http://localhost:8001/payment/nacos/1:
业务正常。接下来创建第二个支付服务 cloud-provider-payment8002
,代码直接拷贝刚才的服务即可,只需修改端口号为8002,其它都一样。
启动payment8002,查看nacos后台:
这样服务就注册成功了。
服务消费
有了服务提供者之后,我们理应创建服务消费者来消费这些服务,当然,消费者也是要注册到nacos中的,创建服务 cloud-comsumer-order9000,pom文件依然是引入nacos依赖,然后编写配置文件:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # nacos的服务中心地址
service: cloud-consumer-order # 服务名
server:
port: 9001 # 端口号
既然是服务消费,那就少不了服务调用,但是nacos已经为我们集成了ribbon,当我们引入nacos依赖的时候,ribbon依赖也随之引入进来了,所以我们可以直接使用ribbon实现负载均衡,那么首先就需要将ribbon注册到容器中:
@Configuration
public class MyApplicationConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
最后编写控制器并在主启动类上标注@EnableDiscoveryClient注解:
@RestController
public class OrderController {
/**
* 需要调用的服务
*/
public static final String SERVER_URL = "http://cloud-provier-payment";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Integer id) {
// 拼接请求地址
String reqUrl = SERVER_URL + "/payment/nacos/" + id;
return restTemplate.getForObject(reqUrl, String.class);
}
}
启动服务消费者,首先查看nacos后台:
服务注册成功, 测试一下业务代码,访问 http://localhost:9001/consumer/payment/nacos/1 :
而且支持负载均衡,默认采用轮询策略。
OpenFeign
ribbon虽然能够实现客户端的负载均衡和服务调用,但是稍显麻烦,缺点也很明显,需要在Controller层调用方法请求另外一个服务的Controller方法。为此,我们可以使用OpenFeign来改进这一过程,OpenFeign集成了ribbon,它更侧重服务之间的调用,当然也默认支持负载均衡。以 cloud-comsumer-order9001 服务为例,要想使用OpenFeign,我们首先需要引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
引入依赖后我们无需注册RestTemplate,而是来编写一个接口:
@FeignClient("cloud-provier-payment")
public interface PaymentService {
@GetMapping("/payment/nacos/{id}")
public String getPayment(@PathVariable("id") Integer id);
}
首先在该接口上标注 @FeignClient("cloud-provier-payment")
注解,其中值为需要远程调用的服务名,在接口中定义方法,一般来说,方法的声明与需要调用的方法声明一致。
然后在启动类上标注@EnableFeignClients注解:
@EnableDiscoveryClient
@EnableFeignClients("com.wwj.cloudcomsumer.order.service")
@SpringBootApplication
public class CloudComsumerOrder9001Application {
public static void main(String[] args) {
SpringApplication.run(CloudComsumerOrder9001Application.class, args);
}
}
若是接口在启动类当前包及其子包下,则无需配置注解的值;接下来就可以编写业务方法了:
@RestController
public class OrderController {
@Autowired
private PaymentService paymentService;
@GetMapping("/consumer/payment/nacos/{id}")
public String paymentInfo(@PathVariable("id") Integer id) {
return paymentService.getPayment(id);
}
}
将接口直接注入进来,然后调用接口中的方法即可。启动项目,测试业务:
服务配置
在前面我们就说过,nacos既是服务的注册中心,也是服务的配置中心,接下来看看nacos如何对服务进行配置。
首先创建一个新的服务 cloud-config2001,然后引入依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-nacos-config</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
我们同样需要将服务注册到nacos中,并且还需要额外配置nacos的配置中心:
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848 # nacos的服务中心地址
service: cloud-config2001 # 服务名
config:
server-addr: 127.0.0.1:8848 # nacos的配置中心地址
file-extension: yaml # 指定配置文件格式为yaml
prefix: cloud-config2001 # DataId前缀
server:
port: 2001 # 端口号
这个配置文件有讲究,我们需要创建一个名为 bootstrap.yml
的配置文件,这是因为我们需要优先去配置中心获取所需的配置,当配置中心没有配置时,才使用本地的配置,而bootstrap.yml配置文件的优先级高于其它命名的配置文件,故需将配置写在bootstrap.yml中。
不要忘了在启动类上标注@EnableDiscoveryClient 注解。最后编写一个方法进行测试:
@RestController
@RefreshScope // 支持nacos的动态刷新功能
public class ConfigController {
@Value("${config.msg}")
private String msg;
@GetMapping("/get/msg")
public String getMsg() {
return msg;
}
}
在本地我们并没有编写关于config.msg的配置信息,只需在nacos中编写配置即可,步骤如下。首先点击左侧导航栏的配置列表,然后点击右侧的+号:
特别需要注意接下来这一步:
最底下的是配置的内容,最上面的是Data ID,这个Data ID非常有讲究,它遵循这样的一个命名规范:
${spring.application.name}-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
在项目中我们并没有配置 ${spring.application.name}
,但我们配置了Data ID的前缀: prefix: cloud-config2001
,这两个必须选其中一个进行配置;我们也没有配置 ${spring.profiles.active}
,然后配置了文件格式为yaml,所以Data ID为 cloud-config2001.yaml
。若是我们配置了:
spring:
profiles:
active: dev # 开发环境
则Data ID为:cloud-config2001-dev.yaml
,最后千万记得点击发布配置才能生效。启动项目,测试一下:
加上我们在控制器上标注了@RefreshScope注解,所以在nacos配置中心里修改配置后,就能够立马在项目中生效,无需重新启动项目。
配置管理
nacos作为配置中心,除了能够提供配置外,它还具有非常强大的功能,比如命名空间、配置分组等等,首先说说命名空间。命名空间是用来区分部署环境的,一个项目往往需要经历开发、测试、维护三个阶段,每个阶段的配置内容可能不尽相同,为此,可以创建三个命名空间来分别接管这三个阶段的配置;默认情况下会有一个 public
命名空间。然后是Data ID,前面我们已经了解过Data ID的组成结构,所以我们可以直接通过Data ID的不同来区分不同环境的配置,比如:
•cloud-config2001-dev.yaml•cloud-config2001-test.yaml•cloud-config2001-prod.yaml
此时我们就能通过修改:
spring:
profiles:
active: dev
# active: test
# active: prod
来分别获取三个配置文件的配置。
接下来我们再来看看分组,默认情况下我们会有一个 DEFAULT_GROUP
分组,新建的配置文件都会被存放在该分组下,通过分组我们也能够区分部署环境的配置信息:
这三个配置文件名相同,但是分组分别属于开发、测试和生产环境,然后通过 group
属性指定即可:
spring:
cloud:
nacos:
config:
group: DEV_GROUP # 指定分组
# group: TEST_GROUP
# group: PROD_GROUP
最后是命名空间,通过命名空间,我们仍然能够实现同样的效果:
点击导航栏的命名空间,然后点击右侧的新建命名空间:
创建好命名空间后,nacos会为每个命名空间分配id:
然后配置一下命名空间:
spring:
cloud:
nacos:
config:
group: DEV_GROUP # 指定分组
namespace: d7e672f8-441e-449b-a143-1eca69122daa # 命名空间ID
此时服务会去寻找该命名空间下的指定分组的配置文件,若有环境指定,也需要加上,然后在nacos中新建配置文件:
在指定命名空间下创建配置文件即可。
本文作者:汪伟俊 为Java技术迷专栏作者 投稿,未经允许请勿转载。
往 期 推 荐 1、最牛逼的 Java 日志框架,性能无敌,横扫所有对手! 2、把Redis当作队列来用,真的合适吗? 3、惊呆了,Spring Boot居然这么耗内存!你知道吗? 4、牛逼哄哄的 BitMap,到底牛逼在哪? 5、全网最全 Java 日志框架适配方案!还有谁不会? 6、30个IDEA插件总有一款适合你 7、Spring中毒太深,离开Spring我居然连最基本的接口都不会写了
点分享
点收藏
点点赞
点在看