nacos使用-服务注册中心和配置中心

本例子基于 spring boot + spring cloud alibaba + spring cloud, nacos作为服务注册中心和配置中心。

简介

Nacos 是Spring Cloud Alibaba 的一个组件。致力于发现、配置和管理微服务。

Nacos名字:前四个字母分别为 Naming 和 Configuration 的前两个字母,最后的 s 为 Service。

下载启动

版本选择

如果是使用spring boot + spring cloud alibaba + spring cloud全家桶。那么版本选择一定要按照官网匹配,否则会因jar包冲突导致项目启动失败。

我们可以去spring cloud alibaba的版本说明查看

版本说明

在此文中,我选择的版本为spring boot - 2.2.5.RELEASE, spring cloud alibaba - 2.2.1.RELEASE, spring cloud - Hoxton.SR3

下载

nacos下载地址 https://github.com/alibaba/nacos/releases

根据上面的版本说明,我这里选择1.2.1

启动

下载解压后,进入bin目录

nacos的bin目录

可以看到启动命令。其中cmd是window系统使用,sh是linux系统使用。

我们本地测试使用windows环境,直接双击startup.cmd即可。linux环境请执行./startup.sh -m standalone (standalone代表单机启动,实际使用应做集群,集群数量三台起步)

查看控制台

nacos默认端口是8848,可不是某手机,8848代表珠穆朗玛峰的高度(但是现在高度好像是8844了)。

启动nacos后,访问localhost:8848/nacos/index.html,可以看到nacos后台。在这里可以对服务和配置做可视化管理(当然现在是空的,一会儿项目启动就有东西了)。

nacos服务为空

注册中心

先看看如何作为服务注册中心

服务注册

1 项目pom添加依赖

<!-- spring boot 项目 -->
<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.2.5.RELEASE</version>
	<relativePath/>
</parent>

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>

	<!-- 服务注册/发现 -->
	<dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
	<dependencies>
		<!-- spring cloud alibaba 依赖管理 -->
		<dependency>
			<groupId>com.alibaba.cloud</groupId>
			<artifactId>spring-cloud-alibaba-dependencies</artifactId>
			<version>2.2.1.RELEASE</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

2 application.properties添加配置

# 服务端口
server.port=8081
# 服务名
spring.application.name=service-provider
# 服务注册中心地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

3 启动类上添加服务发现注解

@EnableDiscoveryClient
@SpringBootApplication
public class ProviderApplication {

	public static void main(String[] args) {
		SpringApplication.run(ProviderApplication.class, args);
	}

}

PS:这里不加@EnableDiscoveryClient也行,Spring Cloud Dalston.SR4版本之后会自动向注册中心注册

4 启动查看

启动服务,刷新nacos后台就能看到这个服务了

nacos服务一个

服务调用

为了说明服务调用,我们先以同样的方式配置好另外一个服务

1 pom添加依赖

同上,略

2 application.properties添加配置

# 服务端口
server.port=9091
# 服务名
spring.application.name=service-consumer
# 服务注册中心地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

3 启动类

@SpringBootApplication
public class ConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}

}

4 启动查看

可以看到,我们有两个微服务了

nacos服务两个

5 引入openfeign

openfeign是spring cloud的组件,为微服务之间的调用提供了解决方案。

openfeign的使用也非常简单,我们在service-consumer项目的基础上继续完善

1) pom添加依赖

<dependencies>
	... //省略之前已添加

	<!-- 服务调用 -->
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-openfeign</artifactId>
	</dependency>
</dependencies>

<dependencyManagement>
	<dependencies>
		... //省略之前已添加
		
		<!-- spring cloud 依赖管理 -->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>Hoxton.SR3</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

2) 编写远程调用类

package com.test.consumer.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient("service-provider")
public interface ProviderFeignService {
	
	@RequestMapping("provider/test")
	public Result providerTest(@RequestBody TestEntity testEntity, @RequestParam String name);
	
}

映射说明: @FeignClient括号里是要调用的微服务名称,@RequestMapping括号里是被调用微服务的具体api路径。

传参说明: 实体类添加@RequestBody,字符串和普通类型添加@RequestParam。

这个service就和我们平时普通的service一样,在controller使用@Autowired依赖注入即可。

3) 启动类添加@EnableFeignClients

@EnableFeignClients(basePackages = "com.test.consumer.feign")
@SpringBootApplication
public class ConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}

}

说明: @EnableFeignClients括号里是要实行远程调用服务所在的包路径,即上面远程调用类所在的包路径。

现在回到service-provider添加一个测试controller就可以调用成功了

@RestController
@RequestMapping("provider")
public class TestController {

	@PostMapping("test")
	public Result test(TestEntity testEntity, String name) {
		Result result = new Result();
		// do something, balabala
		return result;
	}
}

Result是自定义返回类,略。

原理简述

服务注册中心的实现,大概依赖三个重要的定时任务

  1. 客户端定时任务:定时发送心跳,告诉nacos我还活着
  2. 客户端定时任务:定时拉取可用服务,放在本地缓存。openfeign调用时自行选用缓存中服务
  3. 服务端定时任务,定时刷新可用列表,踢掉太久没发心跳的客户端【默认15秒未发心跳的会被踢出】

小结

以上,我们实现了服务注册与发现,服务间远程调用。

配置中心

问题说明

随着业务越来越复杂,我们会面临一些问题:

  1. 微服务项目越来越多,配置文件也越来越多,管理起更麻烦
  2. 改动一个配置参数时,需要重新打包微服务重新发布
  3. 有时候希望改动某个参数可以立即生效

接下来,我们使用nacos解决这些问题。

1 添加pom依赖

<dependencies>
	... //省略之前已添加
	
	<!-- 配置中心 -->
	<dependency>
		<groupId>com.alibaba.cloud</groupId>
		<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
	</dependency>
</dependencies>

2 在application.properties设置运行环境

spring.profiles.active=dev

3 新建bootstrap.properties文件

# 服务名
spring.application.name=service-consumer
# 配置中心地址
spring.cloud.nacos.config.server-addr=127.0.0.1:8848

4 添加注解 @Value + @RefreshScope

@RefreshScope // 自动感知配置文件变化
@RequestMapping("test")
@RestController
public class TestController {
	// 从配置文件获取属性值
	@Value("{message}")
	private String message;
	
	@RequestMapping("message")
	public String message() {
		return message;
	}

}

5 去nacos配置中心添加配置文件

nacos配置中心之添加按钮

nacos配置中心之配置文件

这里Data Id就是配置文件名

6 启动服务,验证结果

服务启动时会去配置中心找文件 ${prefix}-${spring.profile.active}.${file-extension}

  1. prefix默认为spring.application.name,本例中即 service-consumer ;也可以通过配置spring.cloud.nacos.config.prefix来指定
  2. spring.profile.active就是当前环境对应的 profile,本例中即 dev ;如果spring.profile.active不存在,这之前的连接符-也将不存在,文件拼接格式变为${prefix}.${file-extension}
  3. file-extension就是文件后缀,默认为properties;可以通过配置spring.cloud.nacos.config.file-extension来指定,但其值目前只支持propertiesyaml

根据上述说明,服务会去配置中心找的文件就是service-consumer-dev.properties,也即是第5步新增的配置文件。

浏览器访问localhost:9091/test/message就可以看到返回结果为panda,即我们配置文件中的值。

然后去配置中心修改配置文件内容:

nacos配置中心之编辑按钮

nacos配置中心之配置文件修改

再次访问localhost:9091/test/message,可以看到返回结果变为panda2

如此,就解决了之前提到的三个问题:

  1. 配置文件和项目包分开,配置文件可统一管理
  2. 配置参数修改后,不需要重新打包项目,直接重启项目就能读到修改的值
  3. 对于一些需要立即生效的参数,使用@Value + @RefreshScope组合

7 小结

我们项目的启动脚本里一般会加上profile,如测试环境java -jar order.jar --spring.profile.active=test,生产环境java -jar order.jar --spring.profile.active=prod。那么,同一个jar包,我们完全不需要任何改动,发布到不同环境,它自己就能读取到不同环境的配置文件。

一"一个jar包,到处发布"。非常的方便。

namespace & group

我们已经把配置文件从项目中抽离出来了,然而这里仍有麻烦:如果我们有很多微服务,那么就对应有很多配置文件;这些文件还有各自不同环境的版本,也许还有不同业务场景下的版本。如果只是把这么多配置文件都单纯放在一起,那么维护起来也会很困难。

1 说明

为了解决配置文件太多不好管理的问题,我们可以使用nacos提供的命名空间(namesapce)和组(group)的概念。

namespace可以看成是一个独立的一级目录,namespace之间相互隔离;组可以看成namespace下面的二级目录,group之间同样隔离。

之前说,服务启动后会去配置中心找${prefix}-${spring.profile.active}.${file-extension},其实前面还得加上命名空间和组;即到底是去哪个命名空间下面的哪个组找配置文件。我们没有配置这两项,默认是去public下DEFAULT_GROUP找该文件。

而我们创建配置文件时并没有指定命名空间和组,默认就放在了public下的DEFAULT_GROUP组。

所以才能正常读取到配置文件。

2 解决方案

根据以上说明,我们可以使用微服务名来作为namespace。如一个商城项目,有订单微服务(order),商品微服务(product),库存微服务(stock)等,那我们就分别建立namespace为order, product, stock等。

然后,对于不同的业务场景,我们可以使用group来区分。比如双11对应的组,我们就叫1111;618对应的组,我们就叫618

我们去命名空间菜单,点击新建命名空间

nacos配置中心之命名空间菜单

nacos配置中心之新建命名空间

依次添加三个命名空间后,回到配置列表,可以看到新建的命名空间

nacos配置中心之命名空间三个

单击命名空间,可选中之。我们在其中新建配置文件,组也是在建立配置文件时指定的。

nacos配置中心之命名空间新建配置文件

连续建立不同组不同环境的配置文件,最后应该看起来类似这样

nacos配置中心之命名空间配置文件一览

然后其他微服务也如此,建立自己的不同组的不同环境的配置文件。

这里我们可以使用克隆功能,批量复制。

nacos配置中心之命名空间配置文件克隆

结果如下

nacos配置中心之命名空间配置文件克隆结果

如果微服务的配置差别不大的话,可以用这个方式批量复制,再去修改部分参数。

配置文件完成后,再去bootstrap.properties文件指定namespace和group

spring.cloud.nacos.config.group=1111
spring.cloud.nacos.config.namespace=12078634-abb1-4604-8678-45c11db8fe74

这里面的12078634-abb1-4604-8678-45c11db8fe74就是order命名空间后面那一串id

3 小结

以上,我们分离了配置文件和项目。并且能根据微服务和业务分开管理。使得配置维护,项目发布都更加容易。

tip:这里其实有个问题,这个group切换,还是需要修改group后重新发布项目。所以,这里失去了之前说好的"一个jar包,到处发布"的特点。所以,实际使用中,如果没有特别的业务场景,就使用一个默认group。只指定namespace,那么依旧可以做到不重新打包项目。

ps: 如果有同学知道项目启动如何指定group,请指正,多谢。

自定义数据库

默认情况下,nacos是使用了一个嵌入式数据库。

如果想使用自己的数据库(目前只支持mysql数据库)

1 conf目录下,修改application.properties文件。

spring.datasource.platform=mysql

db.num=1
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root            #使用的mysql用户名
db.password=xxx    #使用的mysql连接密码

2 将conf/nacos-mysql.sql表结构导入到自己的数据库中

3 重新启动启动nacos,会发现之前的配置文件没有了。重新添加配置文件,在mysql表里看到自己的配置文件内容。

集群

为了保证nacos本身的高可用,可以用三台nacos组成集群。

集群首先要使用自定义数据库,不然三台集群的配置文件都不能保证一致,集群的基本意义就没了。

1 复制conf目录下的cluster.conf.example,重命名为cluster.conf,写入三台nacos的ip地址

192.168.0.101
192.168.0.102
192.168.0.103

如果在同一台机器上测试,可以设定不同端口

127.0.0.1:8848
127.0.0.1:8858
127.0.0.1:8868

2 复制两个nacos,放在不同的机器上(单机测试则去conf/application.properties修改端口)。启动三台nacos。

3 nginx代理配置

# 集群节点
upstream nacos {
 server 192.168.0.101:8848 weight=1;
 server 192.168.0.102:8848 weight=1;
 server 192.168.0.103:8848 weight=1;
}
# 本地集群节点
#upstream nacos {
 #server 127.0.0.1:8848 weight=1;
 #server 127.0.0.1:8858 weight=1;
 #server 127.0.0.1:8868 weight=1;
#}

server {
    listen       80;
    server_name  localhost;
    location /nacos/ {
        #代理
        proxy_pass http://nacos/nacos/;
    }
}

4 访问
浏览器访问http://localhost/nacos/index.html即可

tip: 保证了Nacos不会有单点故障后,其背后的Mysql最好也做一个主从备份或高可用。

posted @ 2020-05-18 17:37  淘气小饼干  阅读(4208)  评论(0编辑  收藏  举报